aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/3c501.c3
-rw-r--r--drivers/net/3c501.h2
-rw-r--r--drivers/net/3c503.c21
-rw-r--r--drivers/net/3c505.c51
-rw-r--r--drivers/net/3c507.c15
-rw-r--r--drivers/net/3c509.c6
-rw-r--r--drivers/net/3c515.c13
-rw-r--r--drivers/net/3c523.c46
-rw-r--r--drivers/net/3c527.c4
-rw-r--r--drivers/net/3c59x.c13
-rw-r--r--drivers/net/7990.c1
-rw-r--r--drivers/net/8139cp.c47
-rw-r--r--drivers/net/8139too.c57
-rw-r--r--drivers/net/82596.c48
-rw-r--r--drivers/net/8390.c50
-rw-r--r--drivers/net/8390.h15
-rw-r--r--drivers/net/8390p.c50
-rw-r--r--drivers/net/Kconfig64
-rw-r--r--drivers/net/Makefile11
-rw-r--r--drivers/net/a2065.c5
-rw-r--r--drivers/net/ac3200.c5
-rw-r--r--drivers/net/acenic.c37
-rw-r--r--drivers/net/amd8111e.c12
-rw-r--r--drivers/net/apne.c29
-rw-r--r--drivers/net/appletalk/cops.c9
-rw-r--r--drivers/net/appletalk/ipddp.c6
-rw-r--r--drivers/net/appletalk/ltpc.c13
-rw-r--r--drivers/net/arcnet/arc-rawmode.c5
-rw-r--r--drivers/net/arcnet/arc-rimi.c16
-rw-r--r--drivers/net/arcnet/arcnet.c32
-rw-r--r--drivers/net/arcnet/capmode.c9
-rw-r--r--drivers/net/arcnet/com20020-isa.c4
-rw-r--r--drivers/net/arcnet/com20020-pci.c2
-rw-r--r--drivers/net/arcnet/com20020.c10
-rw-r--r--drivers/net/arcnet/com90io.c4
-rw-r--r--drivers/net/arcnet/com90xx.c12
-rw-r--r--drivers/net/arcnet/rfc1051.c9
-rw-r--r--drivers/net/arcnet/rfc1201.c14
-rw-r--r--drivers/net/ariadne.c21
-rw-r--r--drivers/net/arm/Kconfig10
-rw-r--r--drivers/net/arm/Makefile3
-rw-r--r--drivers/net/arm/am79c961a.c7
-rw-r--r--drivers/net/arm/at91_ether.c11
-rw-r--r--drivers/net/arm/ep93xx_eth.c8
-rw-r--r--drivers/net/arm/ether1.c5
-rw-r--r--drivers/net/arm/ether3.c5
-rw-r--r--drivers/net/arm/etherh.c24
-rw-r--r--drivers/net/arm/ixp4xx_eth.c344
-rw-r--r--drivers/net/arm/ks8695net.c1676
-rw-r--r--drivers/net/arm/ks8695net.h107
-rw-r--r--drivers/net/at1700.c16
-rw-r--r--drivers/net/atarilance.c52
-rw-r--r--drivers/net/atl1e/atl1e_main.c47
-rw-r--r--drivers/net/atlx/atl1.c102
-rw-r--r--drivers/net/atlx/atl1.h4
-rw-r--r--drivers/net/atlx/atl2.c101
-rw-r--r--drivers/net/atlx/atl2.h1
-rw-r--r--drivers/net/atlx/atlx.c13
-rw-r--r--drivers/net/atp.c29
-rw-r--r--drivers/net/au1000_eth.c50
-rw-r--r--drivers/net/ax88796.c9
-rw-r--r--drivers/net/b44.c13
-rw-r--r--drivers/net/bfin_mac.c1
-rw-r--r--drivers/net/bmac.c7
-rw-r--r--drivers/net/bnx2.c100
-rw-r--r--drivers/net/bnx2.h42
-rw-r--r--drivers/net/bnx2x_link.c72
-rw-r--r--drivers/net/bnx2x_link.h10
-rw-r--r--drivers/net/bnx2x_main.c95
-rw-r--r--drivers/net/bonding/Makefile3
-rw-r--r--drivers/net/bonding/bond_3ad.c667
-rw-r--r--drivers/net/bonding/bond_3ad.h59
-rw-r--r--drivers/net/bonding/bond_alb.c37
-rw-r--r--drivers/net/bonding/bond_ipv6.c216
-rw-r--r--drivers/net/bonding/bond_main.c477
-rw-r--r--drivers/net/bonding/bond_sysfs.c160
-rw-r--r--drivers/net/bonding/bonding.h68
-rw-r--r--drivers/net/can/vcan.c24
-rw-r--r--drivers/net/cassini.c16
-rw-r--r--drivers/net/chelsio/cxgb2.c94
-rw-r--r--drivers/net/chelsio/sge.c10
-rw-r--r--drivers/net/cpmac.c15
-rw-r--r--drivers/net/cris/eth_v10.c4
-rw-r--r--drivers/net/cs89x0.c16
-rw-r--r--drivers/net/cxgb3/adapter.h5
-rw-r--r--drivers/net/cxgb3/common.h4
-rw-r--r--drivers/net/cxgb3/cxgb3_ctl_defs.h17
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c130
-rw-r--r--drivers/net/cxgb3/cxgb3_offload.c76
-rw-r--r--drivers/net/cxgb3/sge.c105
-rw-r--r--drivers/net/cxgb3/t3_hw.c26
-rw-r--r--drivers/net/cxgb3/version.h2
-rw-r--r--drivers/net/cxgb3/vsc8211.c2
-rw-r--r--drivers/net/de600.c4
-rw-r--r--drivers/net/de620.c26
-rw-r--r--drivers/net/declance.c7
-rw-r--r--drivers/net/defxx.c27
-rw-r--r--drivers/net/depca.c54
-rw-r--r--drivers/net/dl2k.c28
-rw-r--r--drivers/net/dm9000.c40
-rw-r--r--drivers/net/dummy.c15
-rw-r--r--drivers/net/e100.c68
-rw-r--r--drivers/net/e1000/e1000.h1
-rw-r--r--drivers/net/e1000/e1000_main.c107
-rw-r--r--drivers/net/e1000e/82571.c19
-rw-r--r--drivers/net/e1000e/defines.h8
-rw-r--r--drivers/net/e1000e/e1000.h2
-rw-r--r--drivers/net/e1000e/es2lan.c194
-rw-r--r--drivers/net/e1000e/ethtool.c82
-rw-r--r--drivers/net/e1000e/hw.h8
-rw-r--r--drivers/net/e1000e/ich8lan.c151
-rw-r--r--drivers/net/e1000e/lib.c80
-rw-r--r--drivers/net/e1000e/netdev.c131
-rw-r--r--drivers/net/e1000e/phy.c12
-rw-r--r--drivers/net/e2100.c24
-rw-r--r--drivers/net/eepro.c10
-rw-r--r--drivers/net/eepro100.c2401
-rw-r--r--drivers/net/eexpress.c3
-rw-r--r--drivers/net/ehea/ehea.h2
-rw-r--r--drivers/net/ehea/ehea_main.c9
-rw-r--r--drivers/net/ehea/ehea_qmr.c18
-rw-r--r--drivers/net/enc28j60.c51
-rw-r--r--drivers/net/enic/cq_desc.h5
-rw-r--r--drivers/net/enic/enic.h2
-rw-r--r--drivers/net/enic/enic_main.c86
-rw-r--r--drivers/net/enic/enic_res.c7
-rw-r--r--drivers/net/enic/enic_res.h4
-rw-r--r--drivers/net/enic/vnic_dev.c70
-rw-r--r--drivers/net/enic/vnic_devcmd.h19
-rw-r--r--drivers/net/enic/vnic_intr.h2
-rw-r--r--drivers/net/enic/vnic_resource.h2
-rw-r--r--drivers/net/enic/vnic_rq.h9
-rw-r--r--drivers/net/enic/vnic_rss.h13
-rw-r--r--drivers/net/enic/vnic_wq.h9
-rw-r--r--drivers/net/epic100.c56
-rw-r--r--drivers/net/eql.c12
-rw-r--r--drivers/net/es3210.c34
-rw-r--r--drivers/net/eth16i.c15
-rw-r--r--drivers/net/ewrk3.c18
-rw-r--r--drivers/net/fealnx.c6
-rw-r--r--drivers/net/fec.c6
-rw-r--r--drivers/net/fec_mpc52xx.c3
-rw-r--r--drivers/net/forcedeth.c90
-rw-r--r--drivers/net/fs_enet/fs_enet-main.c9
-rw-r--r--drivers/net/gianfar.c861
-rw-r--r--drivers/net/gianfar.h78
-rw-r--r--drivers/net/gianfar_ethtool.c89
-rw-r--r--drivers/net/gianfar_mii.c212
-rw-r--r--drivers/net/gianfar_mii.h2
-rw-r--r--drivers/net/hamachi.c27
-rw-r--r--drivers/net/hamradio/6pack.c1
-rw-r--r--drivers/net/hamradio/baycom_epp.c1
-rw-r--r--drivers/net/hamradio/bpqether.c8
-rw-r--r--drivers/net/hamradio/dmascc.c13
-rw-r--r--drivers/net/hamradio/hdlcdrv.c1
-rw-r--r--drivers/net/hamradio/mkiss.c4
-rw-r--r--drivers/net/hamradio/scc.c13
-rw-r--r--drivers/net/hamradio/yam.c1
-rw-r--r--drivers/net/hp-plus.c27
-rw-r--r--drivers/net/hp.c25
-rw-r--r--drivers/net/hp100.c24
-rw-r--r--drivers/net/hydra.c28
-rw-r--r--drivers/net/ibm_newemac/core.c11
-rw-r--r--drivers/net/ibmlana.c6
-rw-r--r--drivers/net/ibmveth.c48
-rw-r--r--drivers/net/ifb.c13
-rw-r--r--drivers/net/igb/e1000_defines.h7
-rw-r--r--drivers/net/igb/e1000_mac.c25
-rw-r--r--drivers/net/igb/e1000_regs.h4
-rw-r--r--drivers/net/igb/igb.h44
-rw-r--r--drivers/net/igb/igb_ethtool.c131
-rw-r--r--drivers/net/igb/igb_main.c403
-rw-r--r--drivers/net/ioc3-eth.c13
-rw-r--r--drivers/net/ipg.c9
-rw-r--r--drivers/net/irda/ali-ircc.c17
-rw-r--r--drivers/net/irda/au1k_ir.c1
-rw-r--r--drivers/net/irda/donauboe.c8
-rw-r--r--drivers/net/irda/irda-usb.c15
-rw-r--r--drivers/net/irda/irtty-sir.c7
-rw-r--r--drivers/net/irda/kingsun-sir.c1
-rw-r--r--drivers/net/irda/ks959-sir.c1
-rw-r--r--drivers/net/irda/ksdazzle-sir.c1
-rw-r--r--drivers/net/irda/ma600-sir.c2
-rw-r--r--drivers/net/irda/mcs7780.c1
-rw-r--r--drivers/net/irda/nsc-ircc.c17
-rw-r--r--drivers/net/irda/pxaficp_ir.c4
-rw-r--r--drivers/net/irda/sa1100_ir.c28
-rw-r--r--drivers/net/irda/sir_dev.c12
-rw-r--r--drivers/net/irda/smsc-ircc2.c6
-rw-r--r--drivers/net/irda/stir4200.c1
-rw-r--r--drivers/net/irda/via-ircc.c16
-rw-r--r--drivers/net/irda/vlsi_ir.c37
-rw-r--r--drivers/net/irda/w83977af_ir.c29
-rw-r--r--drivers/net/isa-skeleton.c16
-rw-r--r--drivers/net/iseries_veth.c14
-rw-r--r--drivers/net/ixgb/ixgb_main.c58
-rw-r--r--drivers/net/ixgbe/Makefile2
-rw-r--r--drivers/net/ixgbe/ixgbe.h32
-rw-r--r--drivers/net/ixgbe/ixgbe_82598.c192
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb.c332
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb.h184
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb_82598.c398
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb_82598.h94
-rw-r--r--drivers/net/ixgbe/ixgbe_dcb_nl.c641
-rw-r--r--drivers/net/ixgbe/ixgbe_ethtool.c134
-rw-r--r--drivers/net/ixgbe/ixgbe_main.c485
-rw-r--r--drivers/net/ixgbe/ixgbe_phy.c326
-rw-r--r--drivers/net/ixgbe/ixgbe_phy.h25
-rw-r--r--drivers/net/ixgbe/ixgbe_type.h28
-rw-r--r--drivers/net/ixp2000/ixpdev.c6
-rw-r--r--drivers/net/jazzsonic.c4
-rw-r--r--drivers/net/jme.c71
-rw-r--r--drivers/net/jme.h36
-rw-r--r--drivers/net/korina.c5
-rw-r--r--drivers/net/lance.c32
-rw-r--r--drivers/net/lib82596.c14
-rw-r--r--drivers/net/lib8390.c20
-rw-r--r--drivers/net/lne390.c29
-rw-r--r--drivers/net/loopback.c29
-rw-r--r--drivers/net/lp486e.c29
-rw-r--r--drivers/net/mac8390.c22
-rw-r--r--drivers/net/mac89x0.c16
-rw-r--r--drivers/net/macb.c18
-rw-r--r--drivers/net/mace.c34
-rw-r--r--drivers/net/macmace.c6
-rw-r--r--drivers/net/macsonic.c9
-rw-r--r--drivers/net/macvlan.c49
-rw-r--r--drivers/net/meth.c4
-rw-r--r--drivers/net/mlx4/cq.c11
-rw-r--r--drivers/net/mlx4/en_cq.c13
-rw-r--r--drivers/net/mlx4/en_main.c4
-rw-r--r--drivers/net/mlx4/en_netdev.c48
-rw-r--r--drivers/net/mlx4/en_params.c20
-rw-r--r--drivers/net/mlx4/en_rx.c9
-rw-r--r--drivers/net/mlx4/en_tx.c29
-rw-r--r--drivers/net/mlx4/eq.c121
-rw-r--r--drivers/net/mlx4/main.c53
-rw-r--r--drivers/net/mlx4/mcg.c25
-rw-r--r--drivers/net/mlx4/mlx4.h14
-rw-r--r--drivers/net/mlx4/mlx4_en.h12
-rw-r--r--drivers/net/mlx4/profile.c4
-rw-r--r--drivers/net/mv643xx_eth.c525
-rw-r--r--drivers/net/mvme147.c9
-rw-r--r--drivers/net/myri10ge/myri10ge.c71
-rw-r--r--drivers/net/myri10ge/myri10ge_mcp.h175
-rw-r--r--drivers/net/myri10ge/myri10ge_mcp_gen_header.h2
-rw-r--r--drivers/net/myri_sbus.c27
-rw-r--r--drivers/net/natsemi.c12
-rw-r--r--drivers/net/ne-h8300.c30
-rw-r--r--drivers/net/ne.c29
-rw-r--r--drivers/net/ne2.c29
-rw-r--r--drivers/net/ne2k-pci.c28
-rw-r--r--drivers/net/ne3210.c31
-rw-r--r--drivers/net/netconsole.c9
-rw-r--r--drivers/net/netx-eth.c1
-rw-r--r--drivers/net/netxen/netxen_nic_ethtool.c10
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c6
-rw-r--r--drivers/net/netxen/netxen_nic_init.c2
-rw-r--r--drivers/net/netxen/netxen_nic_main.c57
-rw-r--r--drivers/net/netxen/netxen_nic_niu.c7
-rw-r--r--drivers/net/ni5010.c15
-rw-r--r--drivers/net/ni52.c43
-rw-r--r--drivers/net/ni65.c39
-rw-r--r--drivers/net/niu.c145
-rw-r--r--drivers/net/niu.h2
-rw-r--r--drivers/net/ns83820.c28
-rw-r--r--drivers/net/pasemi_mac.c14
-rw-r--r--drivers/net/pasemi_mac_ethtool.c4
-rw-r--r--drivers/net/pci-skeleton.c8
-rw-r--r--drivers/net/pcmcia/3c574_cs.c6
-rw-r--r--drivers/net/pcmcia/3c589_cs.c6
-rw-r--r--drivers/net/pcmcia/axnet_cs.c22
-rw-r--r--drivers/net/pcmcia/com20020_cs.c6
-rw-r--r--drivers/net/pcmcia/fmvj18x_cs.c79
-rw-r--r--drivers/net/pcmcia/nmclan_cs.c6
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c3
-rw-r--r--drivers/net/pcmcia/smc91c92_cs.c5
-rw-r--r--drivers/net/pcmcia/xirc2ps_cs.c6
-rw-r--r--drivers/net/pcnet32.c10
-rw-r--r--drivers/net/phy/Kconfig23
-rw-r--r--drivers/net/phy/Makefile5
-rw-r--r--drivers/net/phy/broadcom.c216
-rw-r--r--drivers/net/phy/et1011c.c113
-rw-r--r--drivers/net/phy/mdio-gpio.c296
-rw-r--r--drivers/net/phy/mdio-ofgpio.c204
-rw-r--r--drivers/net/phy/mdio_bus.c39
-rw-r--r--drivers/net/phy/national.c155
-rw-r--r--drivers/net/phy/phy.c2
-rw-r--r--drivers/net/phy/phy_device.c54
-rw-r--r--drivers/net/phy/smsc.c28
-rw-r--r--drivers/net/phy/ste10Xp.c137
-rw-r--r--drivers/net/plip.c35
-rw-r--r--drivers/net/ppp_async.c6
-rw-r--r--drivers/net/ppp_generic.c234
-rw-r--r--drivers/net/ppp_synctty.c6
-rw-r--r--drivers/net/pppoe.c5
-rw-r--r--drivers/net/pppol2tp.c94
-rw-r--r--drivers/net/ps3_gelic_net.c6
-rw-r--r--drivers/net/ps3_gelic_wireless.c37
-rw-r--r--drivers/net/ps3_gelic_wireless.h4
-rw-r--r--drivers/net/qla3xxx.c42
-rw-r--r--drivers/net/qlge/qlge_ethtool.c2
-rw-r--r--drivers/net/qlge/qlge_main.c79
-rw-r--r--drivers/net/qlge/qlge_mpi.c2
-rw-r--r--drivers/net/r6040.c51
-rw-r--r--drivers/net/r8169.c57
-rw-r--r--drivers/net/rionet.c31
-rw-r--r--drivers/net/rrunner.c25
-rw-r--r--drivers/net/s2io.c146
-rw-r--r--drivers/net/sb1000.c1
-rw-r--r--drivers/net/sb1250-mac.c11
-rw-r--r--drivers/net/sc92031.c30
-rw-r--r--drivers/net/seeq8005.c13
-rw-r--r--drivers/net/sfc/Kconfig8
-rw-r--r--drivers/net/sfc/Makefile5
-rw-r--r--drivers/net/sfc/boards.c206
-rw-r--r--drivers/net/sfc/boards.h14
-rw-r--r--drivers/net/sfc/efx.c449
-rw-r--r--drivers/net/sfc/efx.h12
-rw-r--r--drivers/net/sfc/enum.h36
-rw-r--r--drivers/net/sfc/ethtool.c175
-rw-r--r--drivers/net/sfc/falcon.c480
-rw-r--r--drivers/net/sfc/falcon.h3
-rw-r--r--drivers/net/sfc/falcon_gmac.c229
-rw-r--r--drivers/net/sfc/falcon_hwdefs.h161
-rw-r--r--drivers/net/sfc/falcon_xmac.c261
-rw-r--r--drivers/net/sfc/gmii.h137
-rw-r--r--drivers/net/sfc/mac.h16
-rw-r--r--drivers/net/sfc/mdio_10g.c483
-rw-r--r--drivers/net/sfc/mdio_10g.h63
-rw-r--r--drivers/net/sfc/mtd.c268
-rw-r--r--drivers/net/sfc/net_driver.h131
-rw-r--r--drivers/net/sfc/phy.h7
-rw-r--r--drivers/net/sfc/rx.c2
-rw-r--r--drivers/net/sfc/selftest.c145
-rw-r--r--drivers/net/sfc/selftest.h14
-rw-r--r--drivers/net/sfc/sfe4001.c225
-rw-r--r--drivers/net/sfc/spi.h34
-rw-r--r--drivers/net/sfc/tenxpress.c796
-rw-r--r--drivers/net/sfc/workarounds.h12
-rw-r--r--drivers/net/sfc/xfp_phy.c29
-rw-r--r--drivers/net/sgiseeq.c7
-rw-r--r--drivers/net/sh_eth.c3
-rw-r--r--drivers/net/sis190.c7
-rw-r--r--drivers/net/sis900.c99
-rw-r--r--drivers/net/skfp/skfddi.c27
-rw-r--r--drivers/net/skge.c103
-rw-r--r--drivers/net/sky2.c56
-rw-r--r--drivers/net/slip.c12
-rw-r--r--drivers/net/smc-mca.c27
-rw-r--r--drivers/net/smc-ultra.c27
-rw-r--r--drivers/net/smc-ultra32.c5
-rw-r--r--drivers/net/smc911x.c16
-rw-r--r--drivers/net/smc9194.c13
-rw-r--r--drivers/net/smc91x.c42
-rw-r--r--drivers/net/smc91x.h58
-rw-r--r--drivers/net/smsc911x.c2071
-rw-r--r--drivers/net/smsc911x.h390
-rw-r--r--drivers/net/smsc9420.c1744
-rw-r--r--drivers/net/smsc9420.h275
-rw-r--r--drivers/net/sonic.c1
-rw-r--r--drivers/net/sonic.h20
-rw-r--r--drivers/net/spider_net.c17
-rw-r--r--drivers/net/spider_net_ethtool.c8
-rw-r--r--drivers/net/starfire.c29
-rw-r--r--drivers/net/stnic.c25
-rw-r--r--drivers/net/sun3_82586.c40
-rw-r--r--drivers/net/sun3lance.c10
-rw-r--r--drivers/net/sunbmac.c22
-rw-r--r--drivers/net/sundance.c6
-rw-r--r--drivers/net/sungem.c65
-rw-r--r--drivers/net/sunhme.c31
-rw-r--r--drivers/net/sunlance.c7
-rw-r--r--drivers/net/sunqe.c15
-rw-r--r--drivers/net/sunvnet.c5
-rw-r--r--drivers/net/tc35815.c49
-rw-r--r--drivers/net/tehuti.c73
-rw-r--r--drivers/net/tg3.c1068
-rw-r--r--drivers/net/tg3.h188
-rw-r--r--drivers/net/tlan.c214
-rw-r--r--drivers/net/tokenring/3c359.c13
-rw-r--r--drivers/net/tokenring/Kconfig2
-rw-r--r--drivers/net/tokenring/abyss.c4
-rw-r--r--drivers/net/tokenring/ibmtr.c15
-rw-r--r--drivers/net/tokenring/lanstreamer.c36
-rw-r--r--drivers/net/tokenring/madgemc.c12
-rw-r--r--drivers/net/tokenring/olympic.c52
-rw-r--r--drivers/net/tokenring/proteon.c7
-rw-r--r--drivers/net/tokenring/skisa.c7
-rw-r--r--drivers/net/tokenring/smctr.c2
-rw-r--r--drivers/net/tokenring/tms380tr.c15
-rw-r--r--drivers/net/tokenring/tmspci.c5
-rw-r--r--drivers/net/tsi108_eth.c12
-rw-r--r--drivers/net/tulip/de2104x.c54
-rw-r--r--drivers/net/tulip/de4x5.c17
-rw-r--r--drivers/net/tulip/dmfe.c7
-rw-r--r--drivers/net/tulip/eeprom.c2
-rw-r--r--drivers/net/tulip/interrupt.c10
-rw-r--r--drivers/net/tulip/tulip_core.c15
-rw-r--r--drivers/net/tulip/uli526x.c8
-rw-r--r--drivers/net/tulip/winbond-840.c16
-rw-r--r--drivers/net/tulip/xircom_cb.c4
-rw-r--r--drivers/net/tun.c41
-rw-r--r--drivers/net/typhoon.c15
-rw-r--r--drivers/net/ucc_geth.c408
-rw-r--r--drivers/net/ucc_geth.h1
-rw-r--r--drivers/net/usb/asix.c5
-rw-r--r--drivers/net/usb/catc.c43
-rw-r--r--drivers/net/usb/dm9601.c5
-rw-r--r--drivers/net/usb/hso.c34
-rw-r--r--drivers/net/usb/kaweth.c17
-rw-r--r--drivers/net/usb/mcs7830.c9
-rw-r--r--drivers/net/usb/pegasus.c74
-rw-r--r--drivers/net/usb/rtl8150.c38
-rw-r--r--drivers/net/usb/smsc95xx.c110
-rw-r--r--drivers/net/usb/usbnet.c5
-rw-r--r--drivers/net/veth.c30
-rw-r--r--drivers/net/via-rhine.c47
-rw-r--r--drivers/net/via-velocity.c28
-rw-r--r--drivers/net/virtio_net.c217
-rw-r--r--drivers/net/wan/Kconfig9
-rw-r--r--drivers/net/wan/Makefile3
-rw-r--r--drivers/net/wan/c101.c6
-rw-r--r--drivers/net/wan/cosa.c1
-rw-r--r--drivers/net/wan/cycx_x25.c91
-rw-r--r--drivers/net/wan/dlci.c37
-rw-r--r--drivers/net/wan/dscc4.c4
-rw-r--r--drivers/net/wan/farsync.c2
-rw-r--r--drivers/net/wan/hd64570.c (renamed from drivers/net/wan/hd6457x.c)255
-rw-r--r--drivers/net/wan/hd64572.c640
-rw-r--r--drivers/net/wan/hdlc_fr.c10
-rw-r--r--drivers/net/wan/hdlc_ppp.c649
-rw-r--r--drivers/net/wan/hostess_sv11.c1
-rw-r--r--drivers/net/wan/ixp4xx_hss.c1325
-rw-r--r--drivers/net/wan/lapbether.c3
-rw-r--r--drivers/net/wan/lmc/lmc_main.c1
-rw-r--r--drivers/net/wan/lmc/lmc_proto.c1
-rw-r--r--drivers/net/wan/n2.c9
-rw-r--r--drivers/net/wan/pc300_drv.c22
-rw-r--r--drivers/net/wan/pc300too.c121
-rw-r--r--drivers/net/wan/pci200syn.c79
-rw-r--r--drivers/net/wan/sbni.c101
-rw-r--r--drivers/net/wan/sdla.c48
-rw-r--r--drivers/net/wan/sealevel.c1
-rw-r--r--drivers/net/wan/syncppp.c1480
-rw-r--r--drivers/net/wan/wanxl.c9
-rw-r--r--drivers/net/wan/x25_asy.c52
-rw-r--r--drivers/net/wan/z85230.c12
-rw-r--r--drivers/net/wd.c29
-rw-r--r--drivers/net/wireless/Kconfig163
-rw-r--r--drivers/net/wireless/Makefile22
-rw-r--r--drivers/net/wireless/adm8211.c52
-rw-r--r--drivers/net/wireless/adm8211.h2
-rw-r--r--drivers/net/wireless/airo.c243
-rw-r--r--drivers/net/wireless/arlan-main.c27
-rw-r--r--drivers/net/wireless/ath5k/ath5k.h102
-rw-r--r--drivers/net/wireless/ath5k/attach.c14
-rw-r--r--drivers/net/wireless/ath5k/base.c191
-rw-r--r--drivers/net/wireless/ath5k/desc.c4
-rw-r--r--drivers/net/wireless/ath5k/dma.c190
-rw-r--r--drivers/net/wireless/ath5k/eeprom.c1194
-rw-r--r--drivers/net/wireless/ath5k/eeprom.h253
-rw-r--r--drivers/net/wireless/ath5k/initvals.c8
-rw-r--r--drivers/net/wireless/ath5k/pcu.c233
-rw-r--r--drivers/net/wireless/ath5k/phy.c9
-rw-r--r--drivers/net/wireless/ath5k/qcu.c37
-rw-r--r--drivers/net/wireless/ath5k/reg.h16
-rw-r--r--drivers/net/wireless/ath5k/reset.c9
-rw-r--r--drivers/net/wireless/ath9k/Kconfig11
-rw-r--r--drivers/net/wireless/ath9k/Makefile9
-rw-r--r--drivers/net/wireless/ath9k/ani.c852
-rw-r--r--drivers/net/wireless/ath9k/ath9k.h432
-rw-r--r--drivers/net/wireless/ath9k/beacon.c319
-rw-r--r--drivers/net/wireless/ath9k/calib.c1021
-rw-r--r--drivers/net/wireless/ath9k/core.c1886
-rw-r--r--drivers/net/wireless/ath9k/core.h926
-rw-r--r--drivers/net/wireless/ath9k/debug.c262
-rw-r--r--drivers/net/wireless/ath9k/eeprom.c2824
-rw-r--r--drivers/net/wireless/ath9k/hw.c8490
-rw-r--r--drivers/net/wireless/ath9k/hw.h165
-rw-r--r--drivers/net/wireless/ath9k/initvals.h1938
-rw-r--r--drivers/net/wireless/ath9k/mac.c946
-rw-r--r--drivers/net/wireless/ath9k/main.c2353
-rw-r--r--drivers/net/wireless/ath9k/phy.c24
-rw-r--r--drivers/net/wireless/ath9k/phy.h5
-rw-r--r--drivers/net/wireless/ath9k/rc.c1832
-rw-r--r--drivers/net/wireless/ath9k/rc.h220
-rw-r--r--drivers/net/wireless/ath9k/recv.c1242
-rw-r--r--drivers/net/wireless/ath9k/reg.h109
-rw-r--r--drivers/net/wireless/ath9k/regd.c85
-rw-r--r--drivers/net/wireless/ath9k/regd.h2
-rw-r--r--drivers/net/wireless/ath9k/xmit.c1532
-rw-r--r--drivers/net/wireless/atmel.c79
-rw-r--r--drivers/net/wireless/b43/b43.h1
-rw-r--r--drivers/net/wireless/b43/debugfs.c1
-rw-r--r--drivers/net/wireless/b43/debugfs.h1
-rw-r--r--drivers/net/wireless/b43/dma.c4
-rw-r--r--drivers/net/wireless/b43/main.c280
-rw-r--r--drivers/net/wireless/b43/phy_a.c4
-rw-r--r--drivers/net/wireless/b43/phy_common.c18
-rw-r--r--drivers/net/wireless/b43/phy_g.c28
-rw-r--r--drivers/net/wireless/b43/pio.c3
-rw-r--r--drivers/net/wireless/b43/xmit.c64
-rw-r--r--drivers/net/wireless/b43/xmit.h5
-rw-r--r--drivers/net/wireless/b43legacy/b43legacy.h5
-rw-r--r--drivers/net/wireless/b43legacy/debugfs.c2
-rw-r--r--drivers/net/wireless/b43legacy/dma.c48
-rw-r--r--drivers/net/wireless/b43legacy/main.c211
-rw-r--r--drivers/net/wireless/b43legacy/phy.c6
-rw-r--r--drivers/net/wireless/b43legacy/pio.c31
-rw-r--r--drivers/net/wireless/b43legacy/xmit.c26
-rw-r--r--drivers/net/wireless/b43legacy/xmit.h2
-rw-r--r--drivers/net/wireless/hostap/Kconfig13
-rw-r--r--drivers/net/wireless/hostap/hostap.h2
-rw-r--r--drivers/net/wireless/hostap/hostap_80211.h2
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_rx.c72
-rw-r--r--drivers/net/wireless/hostap/hostap_80211_tx.c23
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.c253
-rw-r--r--drivers/net/wireless/hostap/hostap_ap.h8
-rw-r--r--drivers/net/wireless/hostap/hostap_common.h13
-rw-r--r--drivers/net/wireless/hostap/hostap_hw.c71
-rw-r--r--drivers/net/wireless/hostap/hostap_info.c16
-rw-r--r--drivers/net/wireless/hostap/hostap_ioctl.c157
-rw-r--r--drivers/net/wireless/hostap/hostap_main.c45
-rw-r--r--drivers/net/wireless/hostap/hostap_pci.c2
-rw-r--r--drivers/net/wireless/hostap/hostap_proc.c35
-rw-r--r--drivers/net/wireless/hostap/hostap_wlan.h8
-rw-r--r--drivers/net/wireless/ipw2x00/Kconfig191
-rw-r--r--drivers/net/wireless/ipw2x00/Makefile14
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.c (renamed from drivers/net/wireless/ipw2100.c)71
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.h (renamed from drivers/net/wireless/ipw2100.h)0
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.c (renamed from drivers/net/wireless/ipw2200.c)482
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.h (renamed from drivers/net/wireless/ipw2200.h)2
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_geo.c195
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_module.c293
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_rx.c1799
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_tx.c546
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_wx.c760
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig2
-rw-r--r--drivers/net/wireless/iwlwifi/Makefile3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-commands.h148
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-core.h28
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-debug.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-hw.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-io.h24
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-led.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-led.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-rs.c223
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-rs.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c125
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.h40
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-hw.h203
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c251
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000-hw.h64
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c440
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c108
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c179
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.h22
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c1241
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-calib.c19
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-calib.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h536
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c335
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h78
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-csr.h8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.h33
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c83
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h183
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.c50
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.h15
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fh.h173
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-helpers.h111
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.h37
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-led.c7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-led.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c38
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-prph.h8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rfkill.c12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rfkill.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c230
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c131
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-spectrum.c198
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-spectrum.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c259
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.h16
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c438
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c751
-rw-r--r--drivers/net/wireless/libertas/assoc.c69
-rw-r--r--drivers/net/wireless/libertas/cmd.c32
-rw-r--r--drivers/net/wireless/libertas/cmd.h3
-rw-r--r--drivers/net/wireless/libertas/debugfs.c11
-rw-r--r--drivers/net/wireless/libertas/decl.h4
-rw-r--r--drivers/net/wireless/libertas/defs.h14
-rw-r--r--drivers/net/wireless/libertas/dev.h7
-rw-r--r--drivers/net/wireless/libertas/ethtool.c14
-rw-r--r--drivers/net/wireless/libertas/host.h9
-rw-r--r--drivers/net/wireless/libertas/hostcmd.h26
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c3
-rw-r--r--drivers/net/wireless/libertas/if_usb.c7
-rw-r--r--drivers/net/wireless/libertas/main.c135
-rw-r--r--drivers/net/wireless/libertas/persistcfg.c18
-rw-r--r--drivers/net/wireless/libertas/radiotap.h3
-rw-r--r--drivers/net/wireless/libertas/scan.c105
-rw-r--r--drivers/net/wireless/libertas/scan.h4
-rw-r--r--drivers/net/wireless/libertas/tx.c2
-rw-r--r--drivers/net/wireless/libertas/types.h5
-rw-r--r--drivers/net/wireless/libertas/wext.c80
-rw-r--r--drivers/net/wireless/libertas_tf/cmd.c5
-rw-r--r--drivers/net/wireless/libertas_tf/main.c8
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c294
-rw-r--r--drivers/net/wireless/netwave_cs.c6
-rw-r--r--drivers/net/wireless/orinoco/Makefile12
-rw-r--r--drivers/net/wireless/orinoco/airport.c (renamed from drivers/net/wireless/airport.c)2
-rw-r--r--drivers/net/wireless/orinoco/hermes.c (renamed from drivers/net/wireless/hermes.c)0
-rw-r--r--drivers/net/wireless/orinoco/hermes.h (renamed from drivers/net/wireless/hermes.h)0
-rw-r--r--drivers/net/wireless/orinoco/hermes_dld.c (renamed from drivers/net/wireless/hermes_dld.c)0
-rw-r--r--drivers/net/wireless/orinoco/hermes_dld.h (renamed from drivers/net/wireless/hermes_dld.h)0
-rw-r--r--drivers/net/wireless/orinoco/hermes_rid.h (renamed from drivers/net/wireless/hermes_rid.h)0
-rw-r--r--drivers/net/wireless/orinoco/orinoco.c (renamed from drivers/net/wireless/orinoco.c)231
-rw-r--r--drivers/net/wireless/orinoco/orinoco.h (renamed from drivers/net/wireless/orinoco.h)9
-rw-r--r--drivers/net/wireless/orinoco/orinoco_cs.c (renamed from drivers/net/wireless/orinoco_cs.c)10
-rw-r--r--drivers/net/wireless/orinoco/orinoco_nortel.c (renamed from drivers/net/wireless/orinoco_nortel.c)0
-rw-r--r--drivers/net/wireless/orinoco/orinoco_pci.c (renamed from drivers/net/wireless/orinoco_pci.c)0
-rw-r--r--drivers/net/wireless/orinoco/orinoco_pci.h (renamed from drivers/net/wireless/orinoco_pci.h)0
-rw-r--r--drivers/net/wireless/orinoco/orinoco_plx.c (renamed from drivers/net/wireless/orinoco_plx.c)0
-rw-r--r--drivers/net/wireless/orinoco/orinoco_tmd.c (renamed from drivers/net/wireless/orinoco_tmd.c)0
-rw-r--r--drivers/net/wireless/orinoco/spectrum_cs.c (renamed from drivers/net/wireless/spectrum_cs.c)31
-rw-r--r--drivers/net/wireless/p54/p54.h74
-rw-r--r--drivers/net/wireless/p54/p54common.c1620
-rw-r--r--drivers/net/wireless/p54/p54common.h349
-rw-r--r--drivers/net/wireless/p54/p54pci.c70
-rw-r--r--drivers/net/wireless/p54/p54pci.h2
-rw-r--r--drivers/net/wireless/p54/p54usb.c261
-rw-r--r--drivers/net/wireless/p54/p54usb.h1
-rw-r--r--drivers/net/wireless/prism54/isl_ioctl.c24
-rw-r--r--drivers/net/wireless/prism54/islpci_hotplug.c8
-rw-r--r--drivers/net/wireless/ray_cs.c12
-rw-r--r--drivers/net/wireless/rndis_wlan.c95
-rw-r--r--drivers/net/wireless/rt2x00/Kconfig1
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c373
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c407
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c443
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.h5
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h113
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c202
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00crypto.c79
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00debug.c47
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00debug.h13
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c86
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00leds.c88
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h33
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c56
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.c41
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00pci.h37
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c94
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.h47
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c145
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.h141
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c469
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c689
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.h2
-rw-r--r--drivers/net/wireless/rtl818x/Makefile7
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180.h (renamed from drivers/net/wireless/rtl8180.h)0
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_dev.c (renamed from drivers/net/wireless/rtl8180_dev.c)48
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_grf5101.c (renamed from drivers/net/wireless/rtl8180_grf5101.c)0
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_grf5101.h (renamed from drivers/net/wireless/rtl8180_grf5101.h)0
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_max2820.c (renamed from drivers/net/wireless/rtl8180_max2820.c)0
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_max2820.h (renamed from drivers/net/wireless/rtl8180_max2820.h)0
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_rtl8225.c (renamed from drivers/net/wireless/rtl8180_rtl8225.c)14
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_rtl8225.h (renamed from drivers/net/wireless/rtl8180_rtl8225.h)0
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_sa2400.c (renamed from drivers/net/wireless/rtl8180_sa2400.c)0
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180_sa2400.h (renamed from drivers/net/wireless/rtl8180_sa2400.h)0
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187.h (renamed from drivers/net/wireless/rtl8187.h)8
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_dev.c (renamed from drivers/net/wireless/rtl8187_dev.c)459
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_rtl8225.c (renamed from drivers/net/wireless/rtl8187_rtl8225.c)397
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_rtl8225.h (renamed from drivers/net/wireless/rtl8187_rtl8225.h)0
-rw-r--r--drivers/net/wireless/rtl818x/rtl818x.h (renamed from drivers/net/wireless/rtl818x.h)1
-rw-r--r--drivers/net/wireless/strip.c22
-rw-r--r--drivers/net/wireless/wavelan.c122
-rw-r--r--drivers/net/wireless/wavelan_cs.c39
-rw-r--r--drivers/net/wireless/wl3501.h4
-rw-r--r--drivers/net/wireless/wl3501_cs.c11
-rw-r--r--drivers/net/wireless/zd1201.c131
-rw-r--r--drivers/net/wireless/zd1211rw/zd_chip.c4
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c44
-rw-r--r--drivers/net/wireless/zd1211rw/zd_usb.c2
-rw-r--r--drivers/net/xen-netfront.c9
-rw-r--r--drivers/net/xtsonic.c6
-rw-r--r--drivers/net/yellowfin.c42
-rw-r--r--drivers/net/znet.c28
-rw-r--r--drivers/net/zorro8390.c29
696 files changed, 53721 insertions, 35553 deletions
diff --git a/drivers/net/3c501.c b/drivers/net/3c501.c
index 7d15e7c6bcad..3d1318a3e688 100644
--- a/drivers/net/3c501.c
+++ b/drivers/net/3c501.c
@@ -297,8 +297,8 @@ static int __init el1_probe1(struct net_device *dev, int ioaddr)
if (el_debug)
printk(KERN_DEBUG "%s", version);
- memset(dev->priv, 0, sizeof(struct net_local));
lp = netdev_priv(dev);
+ memset(lp, 0, sizeof(struct net_local));
spin_lock_init(&lp->lock);
/*
@@ -725,7 +725,6 @@ static void el_receive(struct net_device *dev)
insb(DATAPORT, skb_put(skb, pkt_len), pkt_len);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
}
diff --git a/drivers/net/3c501.h b/drivers/net/3c501.h
index cfec64efff78..f40b0493337a 100644
--- a/drivers/net/3c501.h
+++ b/drivers/net/3c501.h
@@ -23,7 +23,7 @@ static const struct ethtool_ops netdev_ethtool_ops;
static int el_debug = EL_DEBUG;
/*
- * Board-specific info in dev->priv.
+ * Board-specific info in netdev_priv(dev).
*/
struct net_local
diff --git a/drivers/net/3c503.c b/drivers/net/3c503.c
index 900b0ffdcc68..c092c3929224 100644
--- a/drivers/net/3c503.c
+++ b/drivers/net/3c503.c
@@ -168,6 +168,21 @@ out:
}
#endif
+static const struct net_device_ops el2_netdev_ops = {
+ .ndo_open = el2_open,
+ .ndo_stop = el2_close,
+
+ .ndo_start_xmit = eip_start_xmit,
+ .ndo_tx_timeout = eip_tx_timeout,
+ .ndo_get_stats = eip_get_stats,
+ .ndo_set_multicast_list = eip_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = eip_poll,
+#endif
+};
+
/* Probe for the Etherlink II card at I/O port base IOADDR,
returning non-zero on success. If found, set the station
address and memory parameters in DEVICE. */
@@ -177,7 +192,6 @@ el2_probe1(struct net_device *dev, int ioaddr)
int i, iobase_reg, membase_reg, saved_406, wordlength, retval;
static unsigned version_printed;
unsigned long vendor_id;
- DECLARE_MAC_BUF(mac);
if (!request_region(ioaddr, EL2_IO_EXTENT, DRV_NAME))
return -EBUSY;
@@ -228,7 +242,7 @@ el2_probe1(struct net_device *dev, int ioaddr)
/* Retrieve and print the ethernet address. */
for (i = 0; i < 6; i++)
dev->dev_addr[i] = inb(ioaddr + i);
- printk("%s", print_mac(mac, dev->dev_addr));
+ printk("%pM", dev->dev_addr);
/* Map the 8390 back into the window. */
outb(ECNTRL_THIN, ioaddr + 0x406);
@@ -336,8 +350,7 @@ el2_probe1(struct net_device *dev, int ioaddr)
ei_status.saved_irq = dev->irq;
- dev->open = &el2_open;
- dev->stop = &el2_close;
+ dev->netdev_ops = &el2_netdev_ops;
dev->ethtool_ops = &netdev_ethtool_ops;
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = eip_poll;
diff --git a/drivers/net/3c505.c b/drivers/net/3c505.c
index a424869707a5..6124605bef05 100644
--- a/drivers/net/3c505.c
+++ b/drivers/net/3c505.c
@@ -203,10 +203,10 @@ static inline int inb_command(unsigned int base_addr)
static inline void outb_control(unsigned char val, struct net_device *dev)
{
outb(val, dev->base_addr + PORT_CONTROL);
- ((elp_device *)(dev->priv))->hcr_val = val;
+ ((elp_device *)(netdev_priv(dev)))->hcr_val = val;
}
-#define HCR_VAL(x) (((elp_device *)((x)->priv))->hcr_val)
+#define HCR_VAL(x) (((elp_device *)(netdev_priv(x)))->hcr_val)
static inline void outb_command(unsigned char val, unsigned int base_addr)
{
@@ -247,7 +247,7 @@ static inline int get_status(unsigned int base_addr)
static inline void set_hsf(struct net_device *dev, int hsf)
{
- elp_device *adapter = dev->priv;
+ elp_device *adapter = netdev_priv(dev);
unsigned long flags;
spin_lock_irqsave(&adapter->lock, flags);
@@ -260,7 +260,7 @@ static bool start_receive(struct net_device *, pcb_struct *);
static inline void adapter_reset(struct net_device *dev)
{
unsigned long timeout;
- elp_device *adapter = dev->priv;
+ elp_device *adapter = netdev_priv(dev);
unsigned char orig_hcr = adapter->hcr_val;
outb_control(0, dev);
@@ -293,7 +293,7 @@ static inline void adapter_reset(struct net_device *dev)
*/
static inline void check_3c505_dma(struct net_device *dev)
{
- elp_device *adapter = dev->priv;
+ elp_device *adapter = netdev_priv(dev);
if (adapter->dmaing && time_after(jiffies, adapter->current_dma.start_time + 10)) {
unsigned long flags, f;
printk(KERN_ERR "%s: DMA %s timed out, %d bytes left\n", dev->name, adapter->current_dma.direction ? "download" : "upload", get_dma_residue(dev->dma));
@@ -340,7 +340,7 @@ static inline bool send_pcb_fast(unsigned int base_addr, unsigned char byte)
/* Check to see if the receiver needs restarting, and kick it if so */
static inline void prime_rx(struct net_device *dev)
{
- elp_device *adapter = dev->priv;
+ elp_device *adapter = netdev_priv(dev);
while (adapter->rx_active < ELP_RX_PCBS && netif_running(dev)) {
if (!start_receive(dev, &adapter->itx_pcb))
break;
@@ -375,7 +375,7 @@ static bool send_pcb(struct net_device *dev, pcb_struct * pcb)
{
int i;
unsigned long timeout;
- elp_device *adapter = dev->priv;
+ elp_device *adapter = netdev_priv(dev);
unsigned long flags;
check_3c505_dma(dev);
@@ -463,7 +463,7 @@ static bool receive_pcb(struct net_device *dev, pcb_struct * pcb)
unsigned long timeout;
unsigned long flags;
- elp_device *adapter = dev->priv;
+ elp_device *adapter = netdev_priv(dev);
set_hsf(dev, 0);
@@ -543,7 +543,7 @@ static bool receive_pcb(struct net_device *dev, pcb_struct * pcb)
static bool start_receive(struct net_device *dev, pcb_struct * tx_pcb)
{
bool status;
- elp_device *adapter = dev->priv;
+ elp_device *adapter = netdev_priv(dev);
if (elp_debug >= 3)
printk(KERN_DEBUG "%s: restarting receiver\n", dev->name);
@@ -571,7 +571,7 @@ static bool start_receive(struct net_device *dev, pcb_struct * tx_pcb)
static void receive_packet(struct net_device *dev, int len)
{
int rlen;
- elp_device *adapter = dev->priv;
+ elp_device *adapter = netdev_priv(dev);
void *target;
struct sk_buff *skb;
unsigned long flags;
@@ -638,13 +638,10 @@ static irqreturn_t elp_interrupt(int irq, void *dev_id)
int len;
int dlen;
int icount = 0;
- struct net_device *dev;
- elp_device *adapter;
+ struct net_device *dev = dev_id;
+ elp_device *adapter = netdev_priv(dev);
unsigned long timeout;
- dev = dev_id;
- adapter = (elp_device *) dev->priv;
-
spin_lock(&adapter->lock);
do {
@@ -672,7 +669,6 @@ static irqreturn_t elp_interrupt(int irq, void *dev_id)
skb->protocol = eth_type_trans(skb,dev);
dev->stats.rx_bytes += skb->len;
netif_rx(skb);
- dev->last_rx = jiffies;
}
}
adapter->dmaing = 0;
@@ -838,11 +834,9 @@ static irqreturn_t elp_interrupt(int irq, void *dev_id)
static int elp_open(struct net_device *dev)
{
- elp_device *adapter;
+ elp_device *adapter = netdev_priv(dev);
int retval;
- adapter = dev->priv;
-
if (elp_debug >= 3)
printk(KERN_DEBUG "%s: request to open device\n", dev->name);
@@ -971,7 +965,7 @@ static int elp_open(struct net_device *dev)
static bool send_packet(struct net_device *dev, struct sk_buff *skb)
{
- elp_device *adapter = dev->priv;
+ elp_device *adapter = netdev_priv(dev);
unsigned long target;
unsigned long flags;
@@ -1062,7 +1056,7 @@ static void elp_timeout(struct net_device *dev)
static int elp_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned long flags;
- elp_device *adapter = dev->priv;
+ elp_device *adapter = netdev_priv(dev);
spin_lock_irqsave(&adapter->lock, flags);
check_3c505_dma(dev);
@@ -1104,7 +1098,7 @@ static int elp_start_xmit(struct sk_buff *skb, struct net_device *dev)
static struct net_device_stats *elp_get_stats(struct net_device *dev)
{
- elp_device *adapter = (elp_device *) dev->priv;
+ elp_device *adapter = netdev_priv(dev);
if (elp_debug >= 3)
printk(KERN_DEBUG "%s: request for stats\n", dev->name);
@@ -1166,9 +1160,7 @@ static const struct ethtool_ops netdev_ethtool_ops = {
static int elp_close(struct net_device *dev)
{
- elp_device *adapter;
-
- adapter = dev->priv;
+ elp_device *adapter = netdev_priv(dev);
if (elp_debug >= 3)
printk(KERN_DEBUG "%s: request to close device\n", dev->name);
@@ -1209,7 +1201,7 @@ static int elp_close(struct net_device *dev)
static void elp_set_mc_list(struct net_device *dev)
{
- elp_device *adapter = (elp_device *) dev->priv;
+ elp_device *adapter = netdev_priv(dev);
struct dev_mc_list *dmi = dev->mc_list;
int i;
unsigned long flags;
@@ -1380,12 +1372,11 @@ static int __init elp_autodetect(struct net_device *dev)
static int __init elplus_setup(struct net_device *dev)
{
- elp_device *adapter = dev->priv;
+ elp_device *adapter = netdev_priv(dev);
int i, tries, tries1, okay;
unsigned long timeout;
unsigned long cookie = 0;
int err = -ENODEV;
- DECLARE_MAC_BUF(mac);
/*
* setup adapter structure
@@ -1522,9 +1513,9 @@ static int __init elplus_setup(struct net_device *dev)
* print remainder of startup message
*/
printk(KERN_INFO "%s: 3c505 at %#lx, irq %d, dma %d, "
- "addr %s, ",
+ "addr %pM, ",
dev->name, dev->base_addr, dev->irq, dev->dma,
- print_mac(mac, dev->dev_addr));
+ dev->dev_addr);
/*
* read more information from the adapter
diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c
index 030c147211ba..423e65d0ba73 100644
--- a/drivers/net/3c507.c
+++ b/drivers/net/3c507.c
@@ -357,7 +357,6 @@ static int __init el16_probe1(struct net_device *dev, int ioaddr)
static unsigned char init_ID_done, version_printed;
int i, irq, irqval, retval;
struct net_local *lp;
- DECLARE_MAC_BUF(mac);
if (init_ID_done == 0) {
ushort lrs_state = 0xff;
@@ -405,7 +404,7 @@ static int __init el16_probe1(struct net_device *dev, int ioaddr)
outb(0x01, ioaddr + MISC_CTRL);
for (i = 0; i < 6; i++)
dev->dev_addr[i] = inb(ioaddr + i);
- printk(" %s", print_mac(mac, dev->dev_addr));
+ printk(" %pM", dev->dev_addr);
if (mem_start)
net_debug = mem_start & 7;
@@ -866,7 +865,6 @@ static void el16_rx(struct net_device *dev)
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
}
@@ -938,14 +936,3 @@ cleanup_module(void)
}
#endif /* MODULE */
MODULE_LICENSE("GPL");
-
-
-/*
- * Local variables:
- * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -I/usr/src/linux/drivers/net -Wall -Wstrict-prototypes -O6 -m486 -c 3c507.c"
- * version-control: t
- * kept-new-versions: 5
- * tab-width: 4
- * c-indent-level: 4
- * End:
- */
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c
index c7a4f3bcc2bc..535c234286ea 100644
--- a/drivers/net/3c509.c
+++ b/drivers/net/3c509.c
@@ -541,7 +541,6 @@ static int __devinit el3_common_init(struct net_device *dev)
{
struct el3_private *lp = netdev_priv(dev);
int err;
- DECLARE_MAC_BUF(mac);
const char *if_names[] = {"10baseT", "AUI", "undefined", "BNC"};
spin_lock_init(&lp->lock);
@@ -575,9 +574,9 @@ static int __devinit el3_common_init(struct net_device *dev)
}
printk(KERN_INFO "%s: 3c5x9 found at %#3.3lx, %s port, "
- "address %s, IRQ %d.\n",
+ "address %pM, IRQ %d.\n",
dev->name, dev->base_addr, if_names[(dev->if_port & 0x03)],
- print_mac(mac, dev->dev_addr), dev->irq);
+ dev->dev_addr, dev->irq);
if (el3_debug > 0)
printk(KERN_INFO "%s", version);
@@ -1075,7 +1074,6 @@ el3_rx(struct net_device *dev)
outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
skb->protocol = eth_type_trans(skb,dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_bytes += pkt_len;
dev->stats.rx_packets++;
continue;
diff --git a/drivers/net/3c515.c b/drivers/net/3c515.c
index a0f8b6e2d0af..39ac12233aa7 100644
--- a/drivers/net/3c515.c
+++ b/drivers/net/3c515.c
@@ -570,7 +570,6 @@ static int corkscrew_setup(struct net_device *dev, int ioaddr,
unsigned int eeprom[0x40], checksum = 0; /* EEPROM contents */
int i;
int irq;
- DECLARE_MAC_BUF(mac);
#ifdef __ISAPNP__
if (idev) {
@@ -636,7 +635,7 @@ static int corkscrew_setup(struct net_device *dev, int ioaddr,
checksum = (checksum ^ (checksum >> 8)) & 0xff;
if (checksum != 0x00)
printk(" ***INVALID CHECKSUM %4.4x*** ", checksum);
- printk(" %s", print_mac(mac, dev->dev_addr));
+ printk(" %pM", dev->dev_addr);
if (eeprom[16] == 0x11c7) { /* Corkscrew */
if (request_dma(dev->dma, "3c515")) {
printk(", DMA %d allocation failed", dev->dma);
@@ -1302,7 +1301,6 @@ static int corkscrew_rx(struct net_device *dev)
outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
/* Wait a limited time to go to next packet. */
@@ -1389,7 +1387,6 @@ static int boomerang_rx(struct net_device *dev)
}
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
}
entry = (++vp->cur_rx) % RX_RING_SIZE;
@@ -1580,11 +1577,3 @@ void cleanup_module(void)
}
}
#endif /* MODULE */
-
-/*
- * Local variables:
- * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c 3c515.c"
- * c-indent-level: 4
- * tab-width: 4
- * End:
- */
diff --git a/drivers/net/3c523.c b/drivers/net/3c523.c
index e2ce41d3828e..ff41e1ff5603 100644
--- a/drivers/net/3c523.c
+++ b/drivers/net/3c523.c
@@ -308,7 +308,7 @@ static int elmc_open(struct net_device *dev)
static int __init check586(struct net_device *dev, unsigned long where, unsigned size)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
char *iscp_addrs[2];
int i = 0;
@@ -347,9 +347,9 @@ static int __init check586(struct net_device *dev, unsigned long where, unsigned
* set iscp at the right place, called by elmc_probe and open586.
*/
-void alloc586(struct net_device *dev)
+static void alloc586(struct net_device *dev)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
elmc_id_reset586();
DELAY(2);
@@ -383,7 +383,6 @@ static int elmc_getinfo(char *buf, int slot, void *d)
{
int len = 0;
struct net_device *dev = d;
- DECLARE_MAC_BUF(mac);
if (dev == NULL)
return len;
@@ -398,8 +397,8 @@ static int elmc_getinfo(char *buf, int slot, void *d)
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: %s\n",
- print_mac(mac, dev->dev_addr));
+ len += sprintf(buf + len, "Hardware Address: %pM\n",
+ dev->dev_addr);
return len;
} /* elmc_getinfo() */
@@ -416,8 +415,7 @@ static int __init do_elmc_probe(struct net_device *dev)
int i = 0;
unsigned int size = 0;
int retval;
- struct priv *pr = dev->priv;
- DECLARE_MAC_BUF(mac);
+ struct priv *pr = netdev_priv(dev);
if (MCA_bus == 0) {
return -ENODEV;
@@ -543,8 +541,8 @@ static int __init do_elmc_probe(struct net_device *dev)
for (i = 0; i < 6; i++)
dev->dev_addr[i] = inb(dev->base_addr + i);
- printk(KERN_INFO "%s: hardware address %s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "%s: hardware address %pM\n",
+ dev->name, dev->dev_addr);
dev->open = &elmc_open;
dev->stop = &elmc_close;
@@ -578,13 +576,14 @@ err_out:
return retval;
}
+#ifdef MODULE
static void cleanup_card(struct net_device *dev)
{
- mca_set_adapter_procfn(((struct priv *) (dev->priv))->slot, NULL, NULL);
+ mca_set_adapter_procfn(((struct priv *)netdev_priv(dev))->slot,
+ NULL, NULL);
release_region(dev->base_addr, ELMC_IO_EXTENT);
}
-
-#ifndef MODULE
+#else
struct net_device * __init elmc_probe(int unit)
{
struct net_device *dev = alloc_etherdev(sizeof(struct priv));
@@ -616,7 +615,7 @@ static int init586(struct net_device *dev)
void *ptr;
unsigned long s;
int i, result = 0;
- struct priv *p = (struct priv *) dev->priv;
+ 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;
@@ -852,7 +851,7 @@ 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 = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
memset((char *) rfd, 0, sizeof(struct rfd_struct) * p->num_recv_buffs);
p->rfd_first = rfd;
@@ -913,7 +912,7 @@ elmc_interrupt(int irq, void *dev_id)
}
/* reading ELMC_CTRL also clears the INT bit. */
- p = (struct priv *) dev->priv;
+ p = netdev_priv(dev);
while ((stat = p->scb->status & STAT_MASK))
{
@@ -969,7 +968,7 @@ static void elmc_rcv_int(struct net_device *dev)
unsigned short totlen;
struct sk_buff *skb;
struct rbd_struct *rbd;
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
for (; (status = p->rfd_top->status) & STAT_COMPL;) {
rbd = (struct rbd_struct *) make32(p->rfd_top->rbd_offset);
@@ -985,7 +984,6 @@ static void elmc_rcv_int(struct net_device *dev)
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->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += totlen;
} else {
@@ -1013,7 +1011,7 @@ static void elmc_rcv_int(struct net_device *dev)
static void elmc_rnr_int(struct net_device *dev)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
dev->stats.rx_errors++;
@@ -1036,7 +1034,7 @@ static void elmc_rnr_int(struct net_device *dev)
static void elmc_xmt_int(struct net_device *dev)
{
int status;
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
status = p->xmit_cmds[p->xmit_last]->cmd_status;
if (!(status & STAT_COMPL)) {
@@ -1079,7 +1077,7 @@ static void elmc_xmt_int(struct net_device *dev)
static void startrecv586(struct net_device *dev)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
p->scb->rfa_offset = make16(p->rfd_first);
p->scb->cmd = RUC_START;
@@ -1093,7 +1091,7 @@ static void startrecv586(struct net_device *dev)
static void elmc_timeout(struct net_device *dev)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
/* COMMAND-UNIT active? */
if (p->scb->status & CU_ACTIVE) {
#ifdef DEBUG
@@ -1129,7 +1127,7 @@ static int elmc_send_packet(struct sk_buff *skb, struct net_device *dev)
#ifndef NO_NOPCOMMANDS
int next_nop;
#endif
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
netif_stop_queue(dev);
@@ -1200,7 +1198,7 @@ static int elmc_send_packet(struct sk_buff *skb, struct net_device *dev)
static struct net_device_stats *elmc_get_stats(struct net_device *dev)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
unsigned short crc, aln, rsc, ovrn;
crc = p->scb->crc_errs; /* get error-statistic from the ni82586 */
diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c
index abc84f765973..2df3af3b9b20 100644
--- a/drivers/net/3c527.c
+++ b/drivers/net/3c527.c
@@ -335,7 +335,6 @@ static int __init mc32_probe1(struct net_device *dev, int slot)
"82586 initialisation failure",
"Adapter list configuration error"
};
- DECLARE_MAC_BUF(mac);
/* Time to play MCA games */
@@ -405,7 +404,7 @@ static int __init mc32_probe1(struct net_device *dev, int slot)
dev->dev_addr[i] = mca_read_pos(slot,3);
}
- printk("%s: Address %s", dev->name, print_mac(mac, dev->dev_addr));
+ printk("%s: Address %pM", dev->name, dev->dev_addr);
mca_write_pos(slot, 6, 0);
mca_write_pos(slot, 7, 0);
@@ -1187,7 +1186,6 @@ static void mc32_rx_ring(struct net_device *dev)
}
skb->protocol=eth_type_trans(skb,dev);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += length;
netif_rx(skb);
diff --git a/drivers/net/3c59x.c b/drivers/net/3c59x.c
index 9ba295d9dd97..665e7fdf27a1 100644
--- a/drivers/net/3c59x.c
+++ b/drivers/net/3c59x.c
@@ -803,7 +803,7 @@ static int vortex_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
- if (dev && dev->priv) {
+ if (dev && netdev_priv(dev)) {
if (netif_running(dev)) {
netif_device_detach(dev);
vortex_down(dev, 1);
@@ -1013,7 +1013,6 @@ static int __devinit vortex_probe1(struct device *gendev,
const char *print_name = "3c59x";
struct pci_dev *pdev = NULL;
struct eisa_device *edev = NULL;
- DECLARE_MAC_BUF(mac);
if (!printed_version) {
printk (version);
@@ -1026,7 +1025,7 @@ static int __devinit vortex_probe1(struct device *gendev,
}
if ((edev = DEVICE_EISA(gendev))) {
- print_name = edev->dev.bus_id;
+ print_name = dev_name(&edev->dev);
}
}
@@ -1206,7 +1205,7 @@ static int __devinit vortex_probe1(struct device *gendev,
((__be16 *)dev->dev_addr)[i] = htons(eeprom[i + 10]);
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
if (print_info)
- printk(" %s", print_mac(mac, dev->dev_addr));
+ printk(" %pM", dev->dev_addr);
/* Unfortunately an all zero eeprom passes the checksum and this
gets found in the wild in failure cases. Crypto is hard 8) */
if (!is_valid_ether_addr(dev->dev_addr)) {
@@ -2447,7 +2446,6 @@ static int vortex_rx(struct net_device *dev)
iowrite16(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
/* Wait a limited time to go to next packet. */
for (i = 200; i >= 0; i--)
@@ -2530,7 +2528,6 @@ boomerang_rx(struct net_device *dev)
}
}
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
}
entry = (++vp->cur_rx) % RX_RING_SIZE;
@@ -2886,7 +2883,7 @@ static void vortex_get_drvinfo(struct net_device *dev,
strcpy(info->bus_info, pci_name(VORTEX_PCI(vp)));
} else {
if (VORTEX_EISA(vp))
- sprintf(info->bus_info, vp->gendev->bus_id);
+ sprintf(info->bus_info, dev_name(vp->gendev));
else
sprintf(info->bus_info, "EISA 0x%lx %d",
dev->base_addr, dev->irq);
@@ -3217,7 +3214,7 @@ static void __exit vortex_eisa_cleanup(void)
#endif
if (compaq_net_device) {
- vp = compaq_net_device->priv;
+ vp = netdev_priv(compaq_net_device);
ioaddr = ioport_map(compaq_net_device->base_addr,
VORTEX_TOTAL_SIZE);
diff --git a/drivers/net/7990.c b/drivers/net/7990.c
index ad6b8a5b6574..7a331acc34ad 100644
--- a/drivers/net/7990.c
+++ b/drivers/net/7990.c
@@ -336,7 +336,6 @@ static int lance_rx (struct net_device *dev)
len);
skb->protocol = eth_type_trans (skb, dev);
netif_rx (skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
}
diff --git a/drivers/net/8139cp.c b/drivers/net/8139cp.c
index 9ba1f0b46429..dd7ac8290aec 100644
--- a/drivers/net/8139cp.c
+++ b/drivers/net/8139cp.c
@@ -457,7 +457,6 @@ static inline void cp_rx_skb (struct cp_private *cp, struct sk_buff *skb,
cp->dev->stats.rx_packets++;
cp->dev->stats.rx_bytes += skb->len;
- cp->dev->last_rx = jiffies;
#if CP_VLAN_TAG_USED
if (cp->vlgrp && (desc->opts2 & cpu_to_le32(RxVlanTagged))) {
@@ -605,7 +604,7 @@ rx_next:
spin_lock_irqsave(&cp->lock, flags);
cpw16_f(IntrMask, cp_intr_mask);
- __netif_rx_complete(dev, napi);
+ __netif_rx_complete(napi);
spin_unlock_irqrestore(&cp->lock, flags);
}
@@ -642,9 +641,9 @@ static irqreturn_t cp_interrupt (int irq, void *dev_instance)
}
if (status & (RxOK | RxErr | RxEmpty | RxFIFOOvr))
- if (netif_rx_schedule_prep(dev, &cp->napi)) {
+ if (netif_rx_schedule_prep(&cp->napi)) {
cpw16_f(IntrMask, cp_norx_intr_mask);
- __netif_rx_schedule(dev, &cp->napi);
+ __netif_rx_schedule(&cp->napi);
}
if (status & (TxOK | TxErr | TxEmpty | SWInt))
@@ -1818,6 +1817,26 @@ static void cp_set_d3_state (struct cp_private *cp)
pci_set_power_state (cp->pdev, PCI_D3hot);
}
+static const struct net_device_ops cp_netdev_ops = {
+ .ndo_open = cp_open,
+ .ndo_stop = cp_close,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_multicast_list = cp_set_rx_mode,
+ .ndo_get_stats = cp_get_stats,
+ .ndo_do_ioctl = cp_ioctl,
+ .ndo_start_xmit = cp_start_xmit,
+ .ndo_tx_timeout = cp_tx_timeout,
+#if CP_VLAN_TAG_USED
+ .ndo_vlan_rx_register = cp_vlan_rx_register,
+#endif
+#ifdef BROKEN
+ .ndo_change_mtu = cp_change_mtu,
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = cp_poll_controller,
+#endif
+};
+
static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *dev;
@@ -1826,7 +1845,6 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
void __iomem *regs;
resource_size_t pciaddr;
unsigned int addr_len, i, pci_using_dac;
- DECLARE_MAC_BUF(mac);
#ifndef MODULE
static int version_printed;
@@ -1931,26 +1949,13 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
cpu_to_le16(read_eeprom (regs, i + 7, addr_len));
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
- dev->open = cp_open;
- dev->stop = cp_close;
- dev->set_multicast_list = cp_set_rx_mode;
- dev->hard_start_xmit = cp_start_xmit;
- dev->get_stats = cp_get_stats;
- dev->do_ioctl = cp_ioctl;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = cp_poll_controller;
-#endif
+ dev->netdev_ops = &cp_netdev_ops;
netif_napi_add(dev, &cp->napi, cp_rx_poll, 16);
-#ifdef BROKEN
- dev->change_mtu = cp_change_mtu;
-#endif
dev->ethtool_ops = &cp_ethtool_ops;
- dev->tx_timeout = cp_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
#if CP_VLAN_TAG_USED
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
- dev->vlan_rx_register = cp_vlan_rx_register;
#endif
if (pci_using_dac)
@@ -1967,10 +1972,10 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_iomap;
printk (KERN_INFO "%s: RTL-8139C+ at 0x%lx, "
- "%s, IRQ %d\n",
+ "%pM, IRQ %d\n",
dev->name,
dev->base_addr,
- print_mac(mac, dev->dev_addr),
+ dev->dev_addr,
dev->irq);
pci_set_drvdata(pdev, dev);
diff --git a/drivers/net/8139too.c b/drivers/net/8139too.c
index 63f906b04899..fe370f805793 100644
--- a/drivers/net/8139too.c
+++ b/drivers/net/8139too.c
@@ -741,8 +741,7 @@ static void rtl8139_chip_reset (void __iomem *ioaddr)
}
-static int __devinit rtl8139_init_board (struct pci_dev *pdev,
- struct net_device **dev_out)
+static __devinit struct net_device * rtl8139_init_board (struct pci_dev *pdev)
{
void __iomem *ioaddr;
struct net_device *dev;
@@ -756,13 +755,11 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
assert (pdev != NULL);
- *dev_out = NULL;
-
/* dev and priv zeroed in alloc_etherdev */
dev = alloc_etherdev (sizeof (*tp));
if (dev == NULL) {
dev_err(&pdev->dev, "Unable to alloc new net device\n");
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
}
SET_NETDEV_DEV(dev, &pdev->dev);
@@ -906,16 +903,29 @@ match:
rtl8139_chip_reset (ioaddr);
- *dev_out = dev;
- return 0;
+ return dev;
err_out:
__rtl8139_cleanup_dev (dev);
if (disable_dev_on_err)
pci_disable_device (pdev);
- return rc;
+ return ERR_PTR(rc);
}
+static const struct net_device_ops rtl8139_netdev_ops = {
+ .ndo_open = rtl8139_open,
+ .ndo_stop = rtl8139_close,
+ .ndo_get_stats = rtl8139_get_stats,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_start_xmit = rtl8139_start_xmit,
+ .ndo_set_multicast_list = rtl8139_set_rx_mode,
+ .ndo_do_ioctl = netdev_ioctl,
+ .ndo_tx_timeout = rtl8139_tx_timeout,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = rtl8139_poll_controller,
+#endif
+
+};
static int __devinit rtl8139_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
@@ -925,7 +935,6 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
int i, addr_len, option;
void __iomem *ioaddr;
static int board_idx = -1;
- DECLARE_MAC_BUF(mac);
assert (pdev != NULL);
assert (ent != NULL);
@@ -959,9 +968,9 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
use_io = 1;
}
- i = rtl8139_init_board (pdev, &dev);
- if (i < 0)
- return i;
+ dev = rtl8139_init_board (pdev);
+ if (IS_ERR(dev))
+ return PTR_ERR(dev);
assert (dev != NULL);
tp = netdev_priv(dev);
@@ -977,19 +986,10 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
/* The Rtl8139-specific entries in the device structure. */
- dev->open = rtl8139_open;
- dev->hard_start_xmit = rtl8139_start_xmit;
- netif_napi_add(dev, &tp->napi, rtl8139_poll, 64);
- dev->stop = rtl8139_close;
- dev->get_stats = rtl8139_get_stats;
- dev->set_multicast_list = rtl8139_set_rx_mode;
- dev->do_ioctl = netdev_ioctl;
+ dev->netdev_ops = &rtl8139_netdev_ops;
dev->ethtool_ops = &rtl8139_ethtool_ops;
- dev->tx_timeout = rtl8139_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = rtl8139_poll_controller;
-#endif
+ netif_napi_add(dev, &tp->napi, rtl8139_poll, 64);
/* note: the hardware is not capable of sg/csum/highdma, however
* through the use of skb_copy_and_csum_dev we enable these
@@ -1024,11 +1024,11 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
pci_set_drvdata (pdev, dev);
printk (KERN_INFO "%s: %s at 0x%lx, "
- "%s, IRQ %d\n",
+ "%pM, IRQ %d\n",
dev->name,
board_info[ent->driver_data].name,
dev->base_addr,
- print_mac(mac, dev->dev_addr),
+ dev->dev_addr,
dev->irq);
printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n",
@@ -2026,7 +2026,6 @@ no_early_rx:
skb->protocol = eth_type_trans (skb, dev);
- dev->last_rx = jiffies;
dev->stats.rx_bytes += pkt_size;
dev->stats.rx_packets++;
@@ -2129,7 +2128,7 @@ static int rtl8139_poll(struct napi_struct *napi, int budget)
*/
spin_lock_irqsave(&tp->lock, flags);
RTL_W16_F(IntrMask, rtl8139_intr_mask);
- __netif_rx_complete(dev, napi);
+ __netif_rx_complete(napi);
spin_unlock_irqrestore(&tp->lock, flags);
}
spin_unlock(&tp->rx_lock);
@@ -2179,9 +2178,9 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance)
/* Receive packets are processed by poll routine.
If not running start it now. */
if (status & RxAckBits){
- if (netif_rx_schedule_prep(dev, &tp->napi)) {
+ if (netif_rx_schedule_prep(&tp->napi)) {
RTL_W16_F (IntrMask, rtl8139_norx_intr_mask);
- __netif_rx_schedule(dev, &tp->napi);
+ __netif_rx_schedule(&tp->napi);
}
}
diff --git a/drivers/net/82596.c b/drivers/net/82596.c
index da292e647eb1..b273596368e3 100644
--- a/drivers/net/82596.c
+++ b/drivers/net/82596.c
@@ -457,7 +457,7 @@ static inline int wait_cfg(struct net_device *dev, struct i596_cmd *cmd, int del
static void i596_display_data(struct net_device *dev)
{
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = dev->ml_priv;
struct i596_cmd *cmd;
struct i596_rfd *rfd;
struct i596_rbd *rbd;
@@ -527,7 +527,7 @@ static irqreturn_t i596_error(int irq, void *dev_id)
static inline void init_rx_bufs(struct net_device *dev)
{
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = dev->ml_priv;
int i;
struct i596_rfd *rfd;
struct i596_rbd *rbd;
@@ -578,7 +578,7 @@ static inline void init_rx_bufs(struct net_device *dev)
static inline void remove_rx_bufs(struct net_device *dev)
{
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = dev->ml_priv;
struct i596_rbd *rbd;
int i;
@@ -592,7 +592,7 @@ static inline void remove_rx_bufs(struct net_device *dev)
static void rebuild_rx_bufs(struct net_device *dev)
{
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = dev->ml_priv;
int i;
/* Ensure rx frame/buffer descriptors are tidy */
@@ -611,7 +611,7 @@ static void rebuild_rx_bufs(struct net_device *dev)
static int init_i596_mem(struct net_device *dev)
{
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = dev->ml_priv;
#if !defined(ENABLE_MVME16x_NET) && !defined(ENABLE_BVME6000_NET) || defined(ENABLE_APRICOT)
short ioaddr = dev->base_addr;
#endif
@@ -764,7 +764,7 @@ failed:
static inline int i596_rx(struct net_device *dev)
{
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = dev->ml_priv;
struct i596_rfd *rfd;
struct i596_rbd *rbd;
int frames = 0;
@@ -841,7 +841,6 @@ memory_squeeze:
pkt_len);
#endif
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes+=pkt_len;
}
@@ -959,7 +958,7 @@ static void i596_reset(struct net_device *dev, struct i596_private *lp,
static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd)
{
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = dev->ml_priv;
int ioaddr = dev->base_addr;
unsigned long flags;
@@ -1029,7 +1028,7 @@ static int i596_open(struct net_device *dev)
static void i596_tx_timeout (struct net_device *dev)
{
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = dev->ml_priv;
int ioaddr = dev->base_addr;
/* Transmitter timeout, serious problems. */
@@ -1058,7 +1057,7 @@ static void i596_tx_timeout (struct net_device *dev)
static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = dev->ml_priv;
struct tx_cmd *tx_cmd;
struct i596_tbd *tbd;
short length = skb->len;
@@ -1116,12 +1115,8 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
static void print_eth(unsigned char *add, char *str)
{
- DECLARE_MAC_BUF(mac);
- DECLARE_MAC_BUF(mac2);
-
- printk(KERN_DEBUG "i596 0x%p, %s --> %s %02X%02X, %s\n",
- add, print_mac(mac, add + 6), print_mac(mac2, add),
- add[12], add[13], str);
+ printk(KERN_DEBUG "i596 0x%p, %pM --> %pM %02X%02X, %s\n",
+ add, add + 6, add, add[12], add[13], str);
}
static int io = 0x300;
@@ -1244,9 +1239,9 @@ found:
dev->tx_timeout = i596_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
- dev->priv = (void *)(dev->mem_start);
+ dev->ml_priv = (void *)(dev->mem_start);
- lp = dev->priv;
+ lp = dev->ml_priv;
DEB(DEB_INIT,printk(KERN_DEBUG "%s: lp at 0x%08lx (%zd bytes), "
"lp->scb at 0x%08lx\n",
dev->name, (unsigned long)lp,
@@ -1307,7 +1302,7 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id)
}
ioaddr = dev->base_addr;
- lp = dev->priv;
+ lp = dev->ml_priv;
spin_lock (&lp->lock);
@@ -1450,7 +1445,7 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id)
static int i596_close(struct net_device *dev)
{
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = dev->ml_priv;
unsigned long flags;
netif_stop_queue(dev);
@@ -1500,7 +1495,7 @@ static int i596_close(struct net_device *dev)
static void set_multicast_list(struct net_device *dev)
{
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = dev->ml_priv;
int config = 0, cnt;
DEB(DEB_MULTI,printk(KERN_DEBUG "%s: set multicast list, %d entries, promisc %s, allmulti %s\n",
@@ -1544,7 +1539,6 @@ static void set_multicast_list(struct net_device *dev)
struct dev_mc_list *dmi;
unsigned char *cp;
struct mc_cmd *cmd;
- DECLARE_MAC_BUF(mac);
if (wait_cfg(dev, &lp->mc_cmd.cmd, 1000, "multicast list change request timed out"))
return;
@@ -1555,8 +1549,8 @@ static void set_multicast_list(struct net_device *dev)
for (dmi = dev->mc_list; cnt && dmi != NULL; dmi = dmi->next, cnt--, cp += 6) {
memcpy(cp, dmi->dmi_addr, 6);
if (i596_debug > 1)
- DEB(DEB_MULTI,printk(KERN_INFO "%s: Adding address %s\n",
- dev->name, print_mac(mac, cp)));
+ DEB(DEB_MULTI,printk(KERN_INFO "%s: Adding address %pM\n",
+ dev->name, cp));
}
i596_add_cmd(dev, &cmd->cmd);
}
@@ -1604,9 +1598,3 @@ void __exit cleanup_module(void)
}
#endif /* MODULE */
-
-/*
- * Local variables:
- * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c 82596.c"
- * End:
- */
diff --git a/drivers/net/8390.c b/drivers/net/8390.c
index f72a2e87d569..fbe609a51e02 100644
--- a/drivers/net/8390.c
+++ b/drivers/net/8390.c
@@ -17,6 +17,30 @@ int ei_close(struct net_device *dev)
}
EXPORT_SYMBOL(ei_close);
+int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ return __ei_start_xmit(skb, dev);
+}
+EXPORT_SYMBOL(ei_start_xmit);
+
+struct net_device_stats *ei_get_stats(struct net_device *dev)
+{
+ return __ei_get_stats(dev);
+}
+EXPORT_SYMBOL(ei_get_stats);
+
+void ei_set_multicast_list(struct net_device *dev)
+{
+ __ei_set_multicast_list(dev);
+}
+EXPORT_SYMBOL(ei_set_multicast_list);
+
+void ei_tx_timeout(struct net_device *dev)
+{
+ __ei_tx_timeout(dev);
+}
+EXPORT_SYMBOL(ei_tx_timeout);
+
irqreturn_t ei_interrupt(int irq, void *dev_id)
{
return __ei_interrupt(irq, dev_id);
@@ -31,9 +55,33 @@ void ei_poll(struct net_device *dev)
EXPORT_SYMBOL(ei_poll);
#endif
+const struct net_device_ops ei_netdev_ops = {
+ .ndo_open = ei_open,
+ .ndo_stop = ei_close,
+ .ndo_start_xmit = ei_start_xmit,
+ .ndo_tx_timeout = ei_tx_timeout,
+ .ndo_get_stats = ei_get_stats,
+ .ndo_set_multicast_list = ei_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = ei_poll,
+#endif
+};
+EXPORT_SYMBOL(ei_netdev_ops);
+
struct net_device *__alloc_ei_netdev(int size)
{
- return ____alloc_ei_netdev(size);
+ struct net_device *dev = ____alloc_ei_netdev(size);
+#ifdef CONFIG_COMPAT_NET_DEV_OPS
+ if (dev) {
+ dev->hard_start_xmit = ei_start_xmit;
+ dev->get_stats = ei_get_stats;
+ dev->set_multicast_list = ei_set_multicast_list;
+ dev->tx_timeout = ei_tx_timeout;
+ }
+#endif
+ return dev;
}
EXPORT_SYMBOL(__alloc_ei_netdev);
diff --git a/drivers/net/8390.h b/drivers/net/8390.h
index 8e209f5e7c11..3c61d6d2748a 100644
--- a/drivers/net/8390.h
+++ b/drivers/net/8390.h
@@ -33,11 +33,19 @@ extern void ei_poll(struct net_device *dev);
extern void eip_poll(struct net_device *dev);
#endif
+
/* Without I/O delay - non ISA or later chips */
extern void NS8390_init(struct net_device *dev, int startp);
extern int ei_open(struct net_device *dev);
extern int ei_close(struct net_device *dev);
extern irqreturn_t ei_interrupt(int irq, void *dev_id);
+extern void ei_tx_timeout(struct net_device *dev);
+extern int ei_start_xmit(struct sk_buff *skb, struct net_device *dev);
+extern void ei_set_multicast_list(struct net_device *dev);
+extern struct net_device_stats *ei_get_stats(struct net_device *dev);
+
+extern const struct net_device_ops ei_netdev_ops;
+
extern struct net_device *__alloc_ei_netdev(int size);
static inline struct net_device *alloc_ei_netdev(void)
{
@@ -49,6 +57,13 @@ extern void NS8390p_init(struct net_device *dev, int startp);
extern int eip_open(struct net_device *dev);
extern int eip_close(struct net_device *dev);
extern irqreturn_t eip_interrupt(int irq, void *dev_id);
+extern void eip_tx_timeout(struct net_device *dev);
+extern int eip_start_xmit(struct sk_buff *skb, struct net_device *dev);
+extern void eip_set_multicast_list(struct net_device *dev);
+extern struct net_device_stats *eip_get_stats(struct net_device *dev);
+
+extern const struct net_device_ops eip_netdev_ops;
+
extern struct net_device *__alloc_eip_netdev(int size);
static inline struct net_device *alloc_eip_netdev(void)
{
diff --git a/drivers/net/8390p.c b/drivers/net/8390p.c
index 4c6eea4611a2..ee70b358a816 100644
--- a/drivers/net/8390p.c
+++ b/drivers/net/8390p.c
@@ -22,6 +22,30 @@ int eip_close(struct net_device *dev)
}
EXPORT_SYMBOL(eip_close);
+int eip_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ return __ei_start_xmit(skb, dev);
+}
+EXPORT_SYMBOL(eip_start_xmit);
+
+struct net_device_stats *eip_get_stats(struct net_device *dev)
+{
+ return __ei_get_stats(dev);
+}
+EXPORT_SYMBOL(eip_get_stats);
+
+void eip_set_multicast_list(struct net_device *dev)
+{
+ __ei_set_multicast_list(dev);
+}
+EXPORT_SYMBOL(eip_set_multicast_list);
+
+void eip_tx_timeout(struct net_device *dev)
+{
+ __ei_tx_timeout(dev);
+}
+EXPORT_SYMBOL(eip_tx_timeout);
+
irqreturn_t eip_interrupt(int irq, void *dev_id)
{
return __ei_interrupt(irq, dev_id);
@@ -36,9 +60,33 @@ void eip_poll(struct net_device *dev)
EXPORT_SYMBOL(eip_poll);
#endif
+const struct net_device_ops eip_netdev_ops = {
+ .ndo_open = eip_open,
+ .ndo_stop = eip_close,
+ .ndo_start_xmit = eip_start_xmit,
+ .ndo_tx_timeout = eip_tx_timeout,
+ .ndo_get_stats = eip_get_stats,
+ .ndo_set_multicast_list = eip_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = eip_poll,
+#endif
+};
+EXPORT_SYMBOL(eip_netdev_ops);
+
struct net_device *__alloc_eip_netdev(int size)
{
- return ____alloc_ei_netdev(size);
+ struct net_device *dev = ____alloc_ei_netdev(size);
+#ifdef CONFIG_COMPAT_NET_DEV_OPS
+ if (dev) {
+ dev->hard_start_xmit = eip_start_xmit;
+ dev->get_stats = eip_get_stats;
+ dev->set_multicast_list = eip_set_multicast_list;
+ dev->tx_timeout = eip_tx_timeout;
+ }
+#endif
+ return dev;
}
EXPORT_SYMBOL(__alloc_eip_netdev);
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 231eeaf1d552..72a9212da865 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -61,6 +61,7 @@ config DUMMY
config BONDING
tristate "Bonding driver support"
depends on INET
+ depends on IPV6 || IPV6=n
---help---
Say 'Y' or 'M' if you wish to be able to 'bond' multiple Ethernet
Channels together. This is called 'Etherchannel' by Cisco,
@@ -978,6 +979,20 @@ config SMC911X
called smc911x. If you want to compile it as a module, say M
here and read <file:Documentation/kbuild/modules.txt>
+config SMSC911X
+ tristate "SMSC LAN911x/LAN921x families embedded ethernet support"
+ depends on ARM || SUPERH
+ select CRC32
+ select MII
+ select PHYLIB
+ ---help---
+ Say Y here if you want support for SMSC LAN911x and LAN921x families
+ of ethernet controllers.
+
+ To compile this driver as a module, choose M here and read
+ <file:Documentation/networking/net-modules.txt>. The module
+ will be called smsc911x.
+
config NET_VENDOR_RACAL
bool "Racal-Interlan (Micom) NI cards"
depends on ISA
@@ -1414,19 +1429,6 @@ config TC35815
depends on NET_PCI && PCI && MIPS
select PHYLIB
-config EEPRO100
- tristate "EtherExpressPro/100 support (eepro100, original Becker driver)"
- depends on NET_PCI && PCI
- select MII
- help
- If you have an Intel EtherExpress PRO/100 PCI network (Ethernet)
- card, 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 eepro100.
-
-
config E100
tristate "Intel(R) PRO/100+ support"
depends on NET_PCI && PCI
@@ -1636,6 +1638,22 @@ config EPIC100
More specific information and updates are available from
<http://www.scyld.com/network/epic100.html>.
+config SMSC9420
+ tristate "SMSC LAN9420 PCI ethernet adapter support"
+ depends on NET_PCI && PCI
+ select CRC32
+ select PHYLIB
+ select SMSC_PHY
+ help
+ This is a driver for SMSC's LAN9420 PCI ethernet adapter.
+ Say Y if you want it compiled into the kernel,
+ and read the Ethernet-HOWTO, available from
+ <http://www.linuxdoc.org/docs.html#howto>.
+
+ This driver is also available as a module. The module will be
+ called smsc9420. If you want to compile it as a module, say M
+ here and read <file:Documentation/kbuild/modules.txt>
+
config SUNDANCE
tristate "Sundance Alta support"
depends on NET_PCI && PCI
@@ -1981,10 +1999,10 @@ config IP1000
will be called ipg. This is recommended.
config IGB
- tristate "Intel(R) 82575 PCI-Express Gigabit Ethernet support"
+ tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support"
depends on PCI
---help---
- This driver supports Intel(R) 82575 gigabit ethernet family of
+ This driver supports Intel(R) 82575/82576 gigabit ethernet family of
adapters. For more information on how to identify your adapter, go
to the Adapter & Driver ID Guide at:
@@ -2276,10 +2294,6 @@ config UGETH_MAGIC_PACKET
bool "Magic Packet detection support"
depends on UCC_GETH
-config UGETH_FILTERING
- bool "Mac address filtering support"
- depends on UCC_GETH
-
config UGETH_TX_ON_DEMAND
bool "Transmit on Demand support"
depends on UCC_GETH
@@ -2450,6 +2464,16 @@ config IXGBE_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 IXGBE_DCB
+ bool "Data Center Bridging (DCB) Support"
+ default n
+ depends on IXGBE && DCB
+ ---help---
+ Say Y here if you want to use Data Center Bridging (DCB) in the
+ driver.
+
+ If unsure, say N.
+
config IXGB
tristate "Intel(R) PRO/10GbE support"
depends on PCI
@@ -2626,7 +2650,7 @@ config RIONET_RX_SIZE
default "128"
config FDDI
- bool "FDDI driver support"
+ tristate "FDDI driver support"
depends on (PCI || EISA || TC)
help
Fiber Distributed Data Interface is a high speed local area network
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 017383ad5ec6..e5c34b464211 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -53,10 +53,10 @@ obj-$(CONFIG_VORTEX) += 3c59x.o
obj-$(CONFIG_TYPHOON) += typhoon.o
obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
obj-$(CONFIG_PCNET32) += pcnet32.o
-obj-$(CONFIG_EEPRO100) += eepro100.o
obj-$(CONFIG_E100) += e100.o
obj-$(CONFIG_TLAN) += tlan.o
obj-$(CONFIG_EPIC100) += epic100.o
+obj-$(CONFIG_SMSC9420) += smsc9420.o
obj-$(CONFIG_SIS190) += sis190.o
obj-$(CONFIG_SIS900) += sis900.o
obj-$(CONFIG_R6040) += r6040.o
@@ -98,7 +98,7 @@ obj-$(CONFIG_HAMACHI) += hamachi.o
obj-$(CONFIG_NET) += Space.o loopback.o
obj-$(CONFIG_SEEQ8005) += seeq8005.o
obj-$(CONFIG_NET_SB1000) += sb1000.o
-obj-$(CONFIG_MAC8390) += mac8390.o
+obj-$(CONFIG_MAC8390) += mac8390.o 8390.o
obj-$(CONFIG_APNE) += apne.o 8390.o
obj-$(CONFIG_PCMCIA_PCNET) += 8390.o
obj-$(CONFIG_HP100) += hp100.o
@@ -125,7 +125,7 @@ obj-$(CONFIG_NE3210) += ne3210.o 8390.o
obj-$(CONFIG_SB1250_MAC) += sb1250-mac.o
obj-$(CONFIG_B44) += b44.o
obj-$(CONFIG_FORCEDETH) += forcedeth.o
-obj-$(CONFIG_NE_H8300) += ne-h8300.o
+obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
obj-$(CONFIG_AX88796) += ax88796.o
obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
@@ -191,7 +191,7 @@ obj-$(CONFIG_SC92031) += sc92031.o
obj-$(CONFIG_LP486E) += lp486e.o
obj-$(CONFIG_ETH16I) += eth16i.o
-obj-$(CONFIG_ZORRO8390) += zorro8390.o
+obj-$(CONFIG_ZORRO8390) += zorro8390.o 8390.o
obj-$(CONFIG_HPLANCE) += hplance.o 7990.o
obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o
obj-$(CONFIG_EQUALIZER) += eql.o
@@ -203,7 +203,7 @@ obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
obj-$(CONFIG_DECLANCE) += declance.o
obj-$(CONFIG_ATARILANCE) += atarilance.o
obj-$(CONFIG_A2065) += a2065.o
-obj-$(CONFIG_HYDRA) += hydra.o
+obj-$(CONFIG_HYDRA) += hydra.o 8390.o
obj-$(CONFIG_ARIADNE) += ariadne.o
obj-$(CONFIG_CS89x0) += cs89x0.o
obj-$(CONFIG_MACSONIC) += macsonic.o
@@ -220,6 +220,7 @@ obj-$(CONFIG_S2IO) += s2io.o
obj-$(CONFIG_MYRI10GE) += myri10ge/
obj-$(CONFIG_SMC91X) += smc91x.o
obj-$(CONFIG_SMC911X) += smc911x.o
+obj-$(CONFIG_SMSC911X) += smsc911x.o
obj-$(CONFIG_BFIN_MAC) += bfin_mac.o
obj-$(CONFIG_DM9000) += dm9000.o
obj-$(CONFIG_PASEMI_MAC) += pasemi_mac_driver.o
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c
index 9c0837435b68..7a60bdd9a242 100644
--- a/drivers/net/a2065.c
+++ b/drivers/net/a2065.c
@@ -324,7 +324,6 @@ static int lance_rx (struct net_device *dev)
len);
skb->protocol = eth_type_trans (skb, dev);
netif_rx (skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
}
@@ -710,7 +709,6 @@ static int __devinit a2065_init_one(struct zorro_dev *z,
unsigned long board, base_addr, mem_start;
struct resource *r1, *r2;
int err;
- DECLARE_MAC_BUF(mac);
board = z->resource.start;
base_addr = board+A2065_LANCE;
@@ -787,8 +785,7 @@ static int __devinit a2065_init_one(struct zorro_dev *z,
zorro_set_drvdata(z, dev);
printk(KERN_INFO "%s: A2065 at 0x%08lx, Ethernet Address "
- "%s\n", dev->name, board,
- print_mac(mac, dev->dev_addr));
+ "%pM\n", dev->name, board, dev->dev_addr);
return 0;
}
diff --git a/drivers/net/ac3200.c b/drivers/net/ac3200.c
index b1448637107f..071a851a2ea1 100644
--- a/drivers/net/ac3200.c
+++ b/drivers/net/ac3200.c
@@ -146,7 +146,6 @@ out:
static int __init ac_probe1(int ioaddr, struct net_device *dev)
{
int i, retval;
- DECLARE_MAC_BUF(mac);
if (!request_region(ioaddr, AC_IO_EXTENT, DRV_NAME))
return -EBUSY;
@@ -171,8 +170,8 @@ static int __init ac_probe1(int ioaddr, struct net_device *dev)
for (i = 0; i < 6; i++)
dev->dev_addr[i] = inb(ioaddr + AC_SA_PROM + i);
- printk(KERN_DEBUG "AC3200 in EISA slot %d, node %s",
- ioaddr/0x1000, print_mac(mac, dev->dev_addr));
+ printk(KERN_DEBUG "AC3200 in EISA slot %d, node %pM",
+ ioaddr/0x1000, dev->dev_addr);
#if 0
/* Check the vendor ID/prefix. Redundant after checking the EISA ID */
if (inb(ioaddr + AC_SA_PROM + 0) != AC_ADDR0
diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c
index 66de80b64b92..517fce48d94a 100644
--- a/drivers/net/acenic.c
+++ b/drivers/net/acenic.c
@@ -450,6 +450,20 @@ static const struct ethtool_ops ace_ethtool_ops = {
static void ace_watchdog(struct net_device *dev);
+static const struct net_device_ops ace_netdev_ops = {
+ .ndo_open = ace_open,
+ .ndo_stop = ace_close,
+ .ndo_tx_timeout = ace_watchdog,
+ .ndo_get_stats = ace_get_stats,
+ .ndo_start_xmit = ace_start_xmit,
+ .ndo_set_multicast_list = ace_set_multicast_list,
+ .ndo_set_mac_address = ace_set_mac_addr,
+ .ndo_change_mtu = ace_change_mtu,
+#if ACENIC_DO_VLAN
+ .ndo_vlan_rx_register = ace_vlan_rx_register,
+#endif
+};
+
static int __devinit acenic_probe_one(struct pci_dev *pdev,
const struct pci_device_id *id)
{
@@ -466,27 +480,19 @@ static int __devinit acenic_probe_one(struct pci_dev *pdev,
SET_NETDEV_DEV(dev, &pdev->dev);
- ap = dev->priv;
+ ap = netdev_priv(dev);
ap->pdev = pdev;
ap->name = pci_name(pdev);
dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
#if ACENIC_DO_VLAN
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
- dev->vlan_rx_register = ace_vlan_rx_register;
#endif
- dev->tx_timeout = &ace_watchdog;
dev->watchdog_timeo = 5*HZ;
- dev->open = &ace_open;
- dev->stop = &ace_close;
- dev->hard_start_xmit = &ace_start_xmit;
- dev->get_stats = &ace_get_stats;
- dev->set_multicast_list = &ace_set_multicast_list;
+ dev->netdev_ops = &ace_netdev_ops;
SET_ETHTOOL_OPS(dev, &ace_ethtool_ops);
- dev->set_mac_address = &ace_set_mac_addr;
- dev->change_mtu = &ace_change_mtu;
/* we only display this string ONCE */
if (!boards_found)
@@ -892,7 +898,6 @@ static int __devinit ace_init(struct net_device *dev)
int board_idx, ecode = 0;
short i;
unsigned char cache_size;
- DECLARE_MAC_BUF(mac);
ap = netdev_priv(dev);
regs = ap->regs;
@@ -1019,7 +1024,7 @@ static int __devinit ace_init(struct net_device *dev)
dev->dev_addr[4] = (mac2 >> 8) & 0xff;
dev->dev_addr[5] = mac2 & 0xff;
- printk("MAC: %s\n", print_mac(mac, dev->dev_addr));
+ printk("MAC: %pM\n", dev->dev_addr);
/*
* Looks like this is necessary to deal with on all architectures,
@@ -2034,7 +2039,6 @@ static void ace_rx_int(struct net_device *dev, u32 rxretprd, u32 rxretcsm)
#endif
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += retdesc->size;
@@ -3220,10 +3224,3 @@ static int __devinit read_eeprom_byte(struct net_device *dev,
ap->name, offset);
goto out;
}
-
-
-/*
- * Local variables:
- * compile-command: "gcc -D__SMP__ -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h -c -o acenic.o acenic.c"
- * End:
- */
diff --git a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
index 07a6697e3635..187ac6eb6e94 100644
--- a/drivers/net/amd8111e.c
+++ b/drivers/net/amd8111e.c
@@ -809,7 +809,6 @@ static int amd8111e_rx_poll(struct napi_struct *napi, int budget)
lp->coal_conf.rx_packets++;
lp->coal_conf.rx_bytes += pkt_len;
num_rx_pkt++;
- dev->last_rx = jiffies;
err_next_pkt:
lp->rx_ring[rx_index].buff_phy_addr
@@ -832,7 +831,7 @@ static int amd8111e_rx_poll(struct napi_struct *napi, int budget)
if (rx_pkt_limit > 0) {
/* Receive descriptor is empty now */
spin_lock_irqsave(&lp->lock, flags);
- __netif_rx_complete(dev, napi);
+ __netif_rx_complete(napi);
writel(VAL0|RINTEN0, mmio + INTEN0);
writel(VAL2 | RDMD0, mmio + CMD0);
spin_unlock_irqrestore(&lp->lock, flags);
@@ -1171,11 +1170,11 @@ static irqreturn_t amd8111e_interrupt(int irq, void *dev_id)
/* Check if Receive Interrupt has occurred. */
if (intr0 & RINT0) {
- if (netif_rx_schedule_prep(dev, &lp->napi)) {
+ if (netif_rx_schedule_prep(&lp->napi)) {
/* Disable receive interupts */
writel(RINTEN0, mmio + INTEN0);
/* Schedule a polling routine */
- __netif_rx_schedule(dev, &lp->napi);
+ __netif_rx_schedule(&lp->napi);
} else if (intren0 & RINTEN0) {
printk("************Driver bug! \
interrupt while in poll\n");
@@ -1821,7 +1820,6 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
unsigned long reg_addr,reg_len;
struct amd8111e_priv* lp;
struct net_device* dev;
- DECLARE_MAC_BUF(mac);
err = pci_enable_device(pdev);
if(err){
@@ -1963,8 +1961,8 @@ static int __devinit amd8111e_probe_one(struct pci_dev *pdev,
chip_version = (readl(lp->mmio + CHIPID) & 0xf0000000)>>28;
printk(KERN_INFO "%s: AMD-8111e Driver Version: %s\n",
dev->name,MODULE_VERS);
- printk(KERN_INFO "%s: [ Rev %x ] PCI 10/100BaseT Ethernet %s\n",
- dev->name, chip_version, print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "%s: [ Rev %x ] PCI 10/100BaseT Ethernet %pM\n",
+ dev->name, chip_version, dev->dev_addr);
if (lp->ext_phy_id)
printk(KERN_INFO "%s: Found MII PHY ID 0x%08x at address 0x%02x\n",
dev->name, lp->ext_phy_id, lp->ext_phy_addr);
diff --git a/drivers/net/apne.c b/drivers/net/apne.c
index 867f6fff543c..1437f5d12121 100644
--- a/drivers/net/apne.c
+++ b/drivers/net/apne.c
@@ -78,9 +78,6 @@
struct net_device * __init apne_probe(int unit);
static int apne_probe1(struct net_device *dev, int ioaddr);
-static int apne_open(struct net_device *dev);
-static int apne_close(struct net_device *dev);
-
static void apne_reset_8390(struct net_device *dev);
static void apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
int ring_page);
@@ -207,7 +204,6 @@ static int __init apne_probe1(struct net_device *dev, int ioaddr)
int neX000, ctron;
#endif
static unsigned version_printed;
- DECLARE_MAC_BUF(mac);
if (ei_debug && version_printed++ == 0)
printk(version);
@@ -315,6 +311,7 @@ static int __init apne_probe1(struct net_device *dev, int ioaddr)
dev->base_addr = ioaddr;
dev->irq = IRQ_AMIGA_PORTS;
+ dev->netdev_ops = &ei_netdev_ops;
/* Install the Interrupt handler */
i = request_irq(dev->irq, apne_interrupt, IRQF_SHARED, DRV_NAME, dev);
@@ -323,7 +320,7 @@ static int __init apne_probe1(struct net_device *dev, int ioaddr)
for(i = 0; i < ETHER_ADDR_LEN; i++)
dev->dev_addr[i] = SA_prom[i];
- printk(" %s\n", print_mac(mac, dev->dev_addr));
+ printk(" %pM\n", dev->dev_addr);
printk("%s: %s found.\n", dev->name, name);
@@ -338,11 +335,7 @@ static int __init apne_probe1(struct net_device *dev, int ioaddr)
ei_status.block_input = &apne_block_input;
ei_status.block_output = &apne_block_output;
ei_status.get_8390_hdr = &apne_get_8390_hdr;
- dev->open = &apne_open;
- dev->stop = &apne_close;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = ei_poll;
-#endif
+
NS8390_init(dev, 0);
pcmcia_ack_int(pcmcia_get_intreq()); /* ack PCMCIA int req */
@@ -353,22 +346,6 @@ static int __init apne_probe1(struct net_device *dev, int ioaddr)
return 0;
}
-static int
-apne_open(struct net_device *dev)
-{
- ei_open(dev);
- return 0;
-}
-
-static int
-apne_close(struct net_device *dev)
-{
- if (ei_debug > 1)
- printk("%s: Shutting down ethercard.\n", dev->name);
- ei_close(dev);
- return 0;
-}
-
/* 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
diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
index 735fc9476403..54819a34ba0a 100644
--- a/drivers/net/appletalk/cops.c
+++ b/drivers/net/appletalk/cops.c
@@ -851,7 +851,6 @@ static void cops_rx(struct net_device *dev)
/* Send packet to a higher place. */
netif_rx(skb);
- dev->last_rx = jiffies;
}
static void cops_timeout(struct net_device *dev)
@@ -1025,11 +1024,3 @@ static void __exit cops_module_exit(void)
module_init(cops_module_init);
module_exit(cops_module_exit);
#endif /* MODULE */
-
-/*
- * Local variables:
- * compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O2 -c cops.c"
- * c-basic-offset: 4
- * c-file-offsets: ((substatement-open . 0))
- * End:
- */
diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c
index 1071144edd66..9a0be9b2eaad 100644
--- a/drivers/net/appletalk/ipddp.c
+++ b/drivers/net/appletalk/ipddp.c
@@ -108,7 +108,7 @@ static struct net_device * __init ipddp_init(void)
*/
static struct net_device_stats *ipddp_get_stats(struct net_device *dev)
{
- return dev->priv;
+ return netdev_priv(dev);
}
/*
@@ -170,8 +170,8 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
skb->protocol = htons(ETH_P_ATALK); /* Protocol has changed */
- ((struct net_device_stats *) dev->priv)->tx_packets++;
- ((struct net_device_stats *) dev->priv)->tx_bytes+=skb->len;
+ ((struct net_device_stats *) netdev_priv(dev))->tx_packets++;
+ ((struct net_device_stats *) netdev_priv(dev))->tx_bytes += skb->len;
if(aarp_send_ddp(rt->dev, skb, &rt->at, NULL) < 0)
dev_kfree_skb(skb);
diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
index fef5560bc7a2..dc4d49605603 100644
--- a/drivers/net/appletalk/ltpc.c
+++ b/drivers/net/appletalk/ltpc.c
@@ -726,7 +726,8 @@ static int sendup_buffer (struct net_device *dev)
int dnode, snode, llaptype, len;
int sklen;
struct sk_buff *skb;
- struct net_device_stats *stats = &((struct ltpc_private *)dev->priv)->stats;
+ struct ltpc_private *ltpc_priv = netdev_priv(dev);
+ struct net_device_stats *stats = &ltpc_priv->stats;
struct lt_rcvlap *ltc = (struct lt_rcvlap *) ltdmacbuf;
if (ltc->command != LT_RCVLAP) {
@@ -783,7 +784,6 @@ static int sendup_buffer (struct net_device *dev)
/* toss it onwards */
netif_rx(skb);
- dev->last_rx = jiffies;
return 0;
}
@@ -823,7 +823,8 @@ static int ltpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
struct sockaddr_at *sa = (struct sockaddr_at *) &ifr->ifr_addr;
/* we'll keep the localtalk node address in dev->pa_addr */
- struct atalk_addr *aa = &((struct ltpc_private *)dev->priv)->my_addr;
+ struct ltpc_private *ltpc_priv = netdev_priv(dev);
+ struct atalk_addr *aa = &ltpc_priv->my_addr;
struct lt_init c;
int ltflags;
@@ -904,7 +905,8 @@ static int ltpc_xmit(struct sk_buff *skb, struct net_device *dev)
* and skb->len is the length of the ddp data + ddp header
*/
- struct net_device_stats *stats = &((struct ltpc_private *)dev->priv)->stats;
+ struct ltpc_private *ltpc_priv = netdev_priv(dev);
+ struct net_device_stats *stats = &ltpc_priv->stats;
int i;
struct lt_sendlap cbuf;
@@ -943,7 +945,8 @@ static int ltpc_xmit(struct sk_buff *skb, struct net_device *dev)
static struct net_device_stats *ltpc_get_stats(struct net_device *dev)
{
- struct net_device_stats *stats = &((struct ltpc_private *) dev->priv)->stats;
+ struct ltpc_private *ltpc_priv = netdev_priv(dev);
+ struct net_device_stats *stats = &ltpc_priv->stats;
return stats;
}
diff --git a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c
index e0a18e7c73cb..3ff9affb1a91 100644
--- a/drivers/net/arcnet/arc-rawmode.c
+++ b/drivers/net/arcnet/arc-rawmode.c
@@ -87,7 +87,7 @@ MODULE_LICENSE("GPL");
static void rx(struct net_device *dev, int bufnum,
struct archdr *pkthdr, int length)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
struct sk_buff *skb;
struct archdr *pkt = pkthdr;
int ofs;
@@ -125,7 +125,6 @@ static void rx(struct net_device *dev, int bufnum,
skb->protocol = __constant_htons(ETH_P_ARCNET);
;
netif_rx(skb);
- dev->last_rx = jiffies;
}
@@ -168,7 +167,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
int bufnum)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
struct arc_hardware *hard = &pkt->hard;
int ofs;
diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c
index 8c8d6c453c45..e3082a9350fc 100644
--- a/drivers/net/arcnet/arc-rimi.c
+++ b/drivers/net/arcnet/arc-rimi.c
@@ -194,7 +194,7 @@ static int __init arcrimi_found(struct net_device *dev)
/* initialize the rest of the device structure. */
- lp = dev->priv;
+ lp = netdev_priv(dev);
lp->card_name = "RIM I";
lp->hw.command = arcrimi_command;
lp->hw.status = arcrimi_status;
@@ -260,7 +260,7 @@ err_free_irq:
*/
static int arcrimi_reset(struct net_device *dev, int really_reset)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->mem_start + 0x800;
BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS());
@@ -281,7 +281,7 @@ static int arcrimi_reset(struct net_device *dev, int really_reset)
static void arcrimi_setmask(struct net_device *dev, int mask)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->mem_start + 0x800;
AINTMASK(mask);
@@ -289,7 +289,7 @@ static void arcrimi_setmask(struct net_device *dev, int mask)
static int arcrimi_status(struct net_device *dev)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->mem_start + 0x800;
return ASTATUS();
@@ -297,7 +297,7 @@ static int arcrimi_status(struct net_device *dev)
static void arcrimi_command(struct net_device *dev, int cmd)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->mem_start + 0x800;
ACOMMAND(cmd);
@@ -306,7 +306,7 @@ static void arcrimi_command(struct net_device *dev, int cmd)
static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset,
void *buf, int count)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count));
}
@@ -315,7 +315,7 @@ static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset,
static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offset,
void *buf, int count)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
}
@@ -361,7 +361,7 @@ static int __init arc_rimi_init(void)
static void __exit arc_rimi_exit(void)
{
struct net_device *dev = my_dev;
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
unregister_netdev(dev);
iounmap(lp->mem_start);
diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
index a5b07691e466..6b53e5ed125c 100644
--- a/drivers/net/arcnet/arcnet.c
+++ b/drivers/net/arcnet/arcnet.c
@@ -181,7 +181,7 @@ EXPORT_SYMBOL(arcnet_dump_skb);
static void arcnet_dump_packet(struct net_device *dev, int bufnum,
char *desc, int take_arcnet_lock)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
int i, length;
unsigned long flags = 0;
static uint8_t buf[512];
@@ -247,7 +247,7 @@ void arcnet_unregister_proto(struct ArcProto *proto)
*/
static void release_arcbuf(struct net_device *dev, int bufnum)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
int i;
lp->buf_queue[lp->first_free_buf++] = bufnum;
@@ -269,7 +269,7 @@ static void release_arcbuf(struct net_device *dev, int bufnum)
*/
static int get_arcbuf(struct net_device *dev)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
int buf = -1, i;
if (!atomic_dec_and_test(&lp->buf_lock)) {
@@ -357,7 +357,7 @@ struct net_device *alloc_arcdev(char *name)
dev = alloc_netdev(sizeof(struct arcnet_local),
name && *name ? name : "arc%d", arcdev_setup);
if(dev) {
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
spin_lock_init(&lp->lock);
}
@@ -374,7 +374,7 @@ struct net_device *alloc_arcdev(char *name)
*/
static int arcnet_open(struct net_device *dev)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
int count, newmtu, error;
BUGMSG(D_INIT,"opened.");
@@ -474,7 +474,7 @@ static int arcnet_open(struct net_device *dev)
/* The inverse routine to arcnet_open - shuts down the card. */
static int arcnet_close(struct net_device *dev)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
netif_stop_queue(dev);
@@ -556,7 +556,7 @@ static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
static int arcnet_rebuild_header(struct sk_buff *skb)
{
struct net_device *dev = skb->dev;
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
int status = 0; /* default is failure */
unsigned short type;
uint8_t daddr=0;
@@ -603,7 +603,7 @@ static int arcnet_rebuild_header(struct sk_buff *skb)
/* Called by the kernel in order to transmit a packet. */
static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
struct archdr *pkt;
struct arc_rfc1201 *soft;
struct ArcProto *proto;
@@ -693,7 +693,7 @@ static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
*/
static int go_tx(struct net_device *dev)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
BUGMSG(D_DURING, "go_tx: status=%Xh, intmask=%Xh, next_tx=%d, cur_tx=%d\n",
ASTATUS(), lp->intmask, lp->next_tx, lp->cur_tx);
@@ -723,7 +723,7 @@ static int go_tx(struct net_device *dev)
static void arcnet_timeout(struct net_device *dev)
{
unsigned long flags;
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
int status = ASTATUS();
char *msg;
@@ -771,8 +771,8 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
BUGMSG(D_DURING, "\n");
BUGMSG(D_DURING, "in arcnet_interrupt\n");
-
- lp = dev->priv;
+
+ lp = netdev_priv(dev);
BUG_ON(!lp);
spin_lock(&lp->lock);
@@ -1010,7 +1010,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id)
*/
static void arcnet_rx(struct net_device *dev, int bufnum)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
struct archdr pkt;
struct arc_rfc1201 *soft;
int length, ofs;
@@ -1074,7 +1074,7 @@ static void arcnet_rx(struct net_device *dev, int bufnum)
*/
static struct net_device_stats *arcnet_get_stats(struct net_device *dev)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
return &lp->stats;
}
@@ -1091,7 +1091,7 @@ static void null_rx(struct net_device *dev, int bufnum,
static int null_build_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, uint8_t daddr)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
BUGMSG(D_PROTO,
"tx: can't build header for encap %02Xh; load a protocol driver.\n",
@@ -1106,7 +1106,7 @@ static int null_build_header(struct sk_buff *skb, struct net_device *dev,
static int null_prepare_tx(struct net_device *dev, struct archdr *pkt,
int length, int bufnum)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
struct arc_hardware newpkt;
BUGMSG(D_PROTO, "tx: no encap for this host; load a protocol driver.\n");
diff --git a/drivers/net/arcnet/capmode.c b/drivers/net/arcnet/capmode.c
index 02cb8f1c1148..30580bbe252d 100644
--- a/drivers/net/arcnet/capmode.c
+++ b/drivers/net/arcnet/capmode.c
@@ -61,7 +61,7 @@ static struct ArcProto capmode_proto =
};
-void arcnet_cap_init(void)
+static void arcnet_cap_init(void)
{
int count;
@@ -103,7 +103,7 @@ MODULE_LICENSE("GPL");
static void rx(struct net_device *dev, int bufnum,
struct archdr *pkthdr, int length)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
struct sk_buff *skb;
struct archdr *pkt = pkthdr;
char *pktbuf, *pkthdrbuf;
@@ -151,7 +151,6 @@ static void rx(struct net_device *dev, int bufnum,
skb->protocol = __constant_htons(ETH_P_ARCNET);
;
netif_rx(skb);
- dev->last_rx = jiffies;
}
@@ -198,7 +197,7 @@ static int build_header(struct sk_buff *skb,
static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
int bufnum)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
struct arc_hardware *hard = &pkt->hard;
int ofs;
@@ -250,7 +249,7 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
static int ack_tx(struct net_device *dev, int acked)
{
- struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
struct sk_buff *ackskb;
struct archdr *ackpkt;
int length=sizeof(struct arc_cap);
diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c
index 9289e6103de5..ea53a940272f 100644
--- a/drivers/net/arcnet/com20020-isa.c
+++ b/drivers/net/arcnet/com20020-isa.c
@@ -52,7 +52,7 @@ static int __init com20020isa_probe(struct net_device *dev)
{
int ioaddr;
unsigned long airqmask;
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
int err;
BUGLVL(D_NORMAL) printk(VERSION);
@@ -151,7 +151,7 @@ static int __init com20020_init(void)
if (node && node != 0xff)
dev->dev_addr[0] = node;
- lp = dev->priv;
+ lp = netdev_priv(dev);
lp->backplane = backplane;
lp->clockp = clockp & 7;
lp->clockm = clockm & 3;
diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c
index b8c0fa6d401d..8b51f632581d 100644
--- a/drivers/net/arcnet/com20020-pci.c
+++ b/drivers/net/arcnet/com20020-pci.c
@@ -72,7 +72,7 @@ static int __devinit com20020pci_probe(struct pci_dev *pdev, const struct pci_de
dev = alloc_arcdev(device);
if (!dev)
return -ENOMEM;
- lp = dev->priv;
+ lp = netdev_priv(dev);
pci_set_drvdata(pdev, dev);
diff --git a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
index 70124a944e7d..103688358fb8 100644
--- a/drivers/net/arcnet/com20020.c
+++ b/drivers/net/arcnet/com20020.c
@@ -89,7 +89,7 @@ static void com20020_copy_to_card(struct net_device *dev, int bufnum,
int com20020_check(struct net_device *dev)
{
int ioaddr = dev->base_addr, status;
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
ARCRESET0;
mdelay(RESETtime);
@@ -159,7 +159,7 @@ int com20020_found(struct net_device *dev, int shared)
/* Initialize the rest of the device structure. */
- lp = dev->priv;
+ lp = netdev_priv(dev);
lp->hw.owner = THIS_MODULE;
lp->hw.command = com20020_command;
@@ -233,7 +233,7 @@ int com20020_found(struct net_device *dev, int shared)
*/
static int com20020_reset(struct net_device *dev, int really_reset)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
u_int ioaddr = dev->base_addr;
u_char inbyte;
@@ -300,7 +300,7 @@ static int com20020_status(struct net_device *dev)
static void com20020_close(struct net_device *dev)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
int ioaddr = dev->base_addr;
/* disable transmitter */
@@ -317,7 +317,7 @@ static void com20020_close(struct net_device *dev)
*/
static void com20020_set_mc_list(struct net_device *dev)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
int ioaddr = dev->base_addr;
if ((dev->flags & IFF_PROMISC) && (dev->flags & IFF_UP)) { /* Enable promiscuous mode */
diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c
index 6599f1046c7b..89de29b3b1dc 100644
--- a/drivers/net/arcnet/com90io.c
+++ b/drivers/net/arcnet/com90io.c
@@ -248,7 +248,7 @@ static int __init com90io_found(struct net_device *dev)
return -EBUSY;
}
- lp = dev->priv;
+ lp = netdev_priv(dev);
lp->card_name = "COM90xx I/O";
lp->hw.command = com90io_command;
lp->hw.status = com90io_status;
@@ -290,7 +290,7 @@ static int __init com90io_found(struct net_device *dev)
*/
static int com90io_reset(struct net_device *dev, int really_reset)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
short ioaddr = dev->base_addr;
BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS());
diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c
index 0d45553ff75c..d762fe46251e 100644
--- a/drivers/net/arcnet/com90xx.c
+++ b/drivers/net/arcnet/com90xx.c
@@ -468,7 +468,7 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, void __iomem
release_mem_region(shmem, MIRROR_SIZE);
return -ENOMEM;
}
- lp = dev->priv;
+ lp = netdev_priv(dev);
/* find the real shared memory start/end points, including mirrors */
/* guess the actual size of one "memory mirror" - the number of
@@ -583,9 +583,9 @@ static void com90xx_setmask(struct net_device *dev, int mask)
*
* However, it does make sure the card is in a defined state.
*/
-int com90xx_reset(struct net_device *dev, int really_reset)
+static int com90xx_reset(struct net_device *dev, int really_reset)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
short ioaddr = dev->base_addr;
BUGMSG(D_INIT, "Resetting (status=%02Xh)\n", ASTATUS());
@@ -621,7 +621,7 @@ int com90xx_reset(struct net_device *dev, int really_reset)
static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset,
void *buf, int count)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset;
TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count));
}
@@ -630,7 +630,7 @@ static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset,
static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offset,
void *buf, int count)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset;
TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
}
@@ -656,7 +656,7 @@ static void __exit com90xx_exit(void)
for (count = 0; count < numcards; count++) {
dev = cards[count];
- lp = dev->priv;
+ lp = netdev_priv(dev);
unregister_netdev(dev);
free_irq(dev->irq, dev);
diff --git a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c
index dab185bc51f1..49d39a9cb696 100644
--- a/drivers/net/arcnet/rfc1051.c
+++ b/drivers/net/arcnet/rfc1051.c
@@ -88,7 +88,7 @@ MODULE_LICENSE("GPL");
*/
static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
struct archdr *pkt = (struct archdr *) skb->data;
struct arc_rfc1051 *soft = &pkt->soft.rfc1051;
int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE;
@@ -125,7 +125,7 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
static void rx(struct net_device *dev, int bufnum,
struct archdr *pkthdr, int length)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
struct sk_buff *skb;
struct archdr *pkt = pkthdr;
int ofs;
@@ -159,7 +159,6 @@ static void rx(struct net_device *dev, int bufnum,
skb->protocol = type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
}
@@ -169,7 +168,7 @@ static void rx(struct net_device *dev, int bufnum,
static int build_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, uint8_t daddr)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE;
struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size);
struct arc_rfc1051 *soft = &pkt->soft.rfc1051;
@@ -220,7 +219,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
int bufnum)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
struct arc_hardware *hard = &pkt->hard;
int ofs;
diff --git a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c
index 6d6d95cc4404..2303d3a1f4b6 100644
--- a/drivers/net/arcnet/rfc1201.c
+++ b/drivers/net/arcnet/rfc1201.c
@@ -92,7 +92,7 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
{
struct archdr *pkt = (struct archdr *) skb->data;
struct arc_rfc1201 *soft = &pkt->soft.rfc1201;
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE;
/* Pull off the arcnet header. */
@@ -134,7 +134,7 @@ static __be16 type_trans(struct sk_buff *skb, struct net_device *dev)
static void rx(struct net_device *dev, int bufnum,
struct archdr *pkthdr, int length)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
struct sk_buff *skb;
struct archdr *pkt = pkthdr;
struct arc_rfc1201 *soft = &pkthdr->soft.rfc1201;
@@ -230,7 +230,6 @@ static void rx(struct net_device *dev, int bufnum,
skb->protocol = type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
} else { /* split packet */
/*
* NOTE: MSDOS ARP packet correction should only need to apply to
@@ -366,7 +365,6 @@ static void rx(struct net_device *dev, int bufnum,
skb->protocol = type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
}
}
}
@@ -376,7 +374,7 @@ static void rx(struct net_device *dev, int bufnum,
static int build_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, uint8_t daddr)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE;
struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size);
struct arc_rfc1201 *soft = &pkt->soft.rfc1201;
@@ -443,7 +441,7 @@ static int build_header(struct sk_buff *skb, struct net_device *dev,
static void load_pkt(struct net_device *dev, struct arc_hardware *hard,
struct arc_rfc1201 *soft, int softlen, int bufnum)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
int ofs;
/* assume length <= XMTU: someone should have handled that by now. */
@@ -476,7 +474,7 @@ static void load_pkt(struct net_device *dev, struct arc_hardware *hard,
static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
int bufnum)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
const int maxsegsize = XMTU - RFC1201_HDR_SIZE;
struct Outgoing *out;
@@ -511,7 +509,7 @@ static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
static int continue_tx(struct net_device *dev, int bufnum)
{
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
struct Outgoing *out = &lp->outgoing;
struct arc_hardware *hard = &out->pkt->hard;
struct arc_rfc1201 *soft = &out->pkt->soft.rfc1201, *newsoft;
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c
index 29e53eb71c74..e1d72e06f3e1 100644
--- a/drivers/net/ariadne.c
+++ b/drivers/net/ariadne.c
@@ -165,7 +165,6 @@ static int __devinit ariadne_init_one(struct zorro_dev *z,
struct net_device *dev;
struct ariadne_private *priv;
int err;
- DECLARE_MAC_BUF(mac);
r1 = request_mem_region(base_addr, sizeof(struct Am79C960), "Am79C960");
if (!r1)
@@ -215,9 +214,8 @@ static int __devinit ariadne_init_one(struct zorro_dev *z,
}
zorro_set_drvdata(z, dev);
- printk(KERN_INFO "%s: Ariadne at 0x%08lx, Ethernet Address "
- "%s\n", dev->name, board,
- print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "%s: Ariadne at 0x%08lx, Ethernet Address %pM\n",
+ dev->name, board, dev->dev_addr);
return 0;
}
@@ -613,14 +611,10 @@ static int ariadne_start_xmit(struct sk_buff *skb, struct net_device *dev)
#if 0
{
- DECLARE_MAC_BUF(mac);
- DECLARE_MAC_BUF(mac2);
-
- printk(KERN_DEBUG "TX pkt type 0x%04x from %s to %s "
+ printk(KERN_DEBUG "TX pkt type 0x%04x from %pM to %pM "
" data 0x%08x len %d\n",
((u_short *)skb->data)[6],
- print_mac(mac, ((const u8 *)skb->data)+6),
- print_mac(mac, (const u8 *)skb->data),
+ skb->data + 6, skb->data,
(int)skb->data, (int)skb->len);
}
#endif
@@ -743,25 +737,22 @@ static int ariadne_rx(struct net_device *dev)
skb->protocol=eth_type_trans(skb,dev);
#if 0
{
- DECLARE_MAC_BUF(mac);
-
printk(KERN_DEBUG "RX pkt type 0x%04x from ",
((u_short *)skb->data)[6]);
{
u_char *ptr = &((u_char *)skb->data)[6];
- printk("%s", print_mac(mac, ptr));
+ printk("%pM", ptr);
}
printk(" to ");
{
u_char *ptr = (u_char *)skb->data;
- printk("%s", print_mac(mac, ptr));
+ printk("%pM", ptr);
}
printk(" data 0x%08x len %d\n", (int)skb->data, (int)skb->len);
}
#endif
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
}
diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
index 8eda6eeb43b7..2895db13bfa4 100644
--- a/drivers/net/arm/Kconfig
+++ b/drivers/net/arm/Kconfig
@@ -40,6 +40,14 @@ config ARM_AT91_ETHER
If you wish to compile a kernel for the AT91RM9200 and enable
ethernet support, then you should always answer Y to this.
+config ARM_KS8695_ETHER
+ tristate "KS8695 Ethernet support"
+ depends on ARM && ARCH_KS8695
+ select MII
+ help
+ If you wish to compile a kernel for the KS8695 and want to
+ use the internal ethernet then you should answer Y to this.
+
config EP93XX_ETH
tristate "EP93xx Ethernet support"
depends on ARM && ARCH_EP93XX
@@ -51,7 +59,7 @@ config EP93XX_ETH
config IXP4XX_ETH
tristate "Intel IXP4xx Ethernet support"
depends on ARM && ARCH_IXP4XX && IXP4XX_NPE && IXP4XX_QMGR
- select MII
+ select PHYLIB
help
Say Y here if you want to use built-in Ethernet ports
on IXP4xx processor.
diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile
index 7c812ac2b6a5..c69c0cdba4a2 100644
--- a/drivers/net/arm/Makefile
+++ b/drivers/net/arm/Makefile
@@ -4,9 +4,10 @@
#
obj-$(CONFIG_ARM_AM79C961A) += am79c961a.o
-obj-$(CONFIG_ARM_ETHERH) += etherh.o
+obj-$(CONFIG_ARM_ETHERH) += etherh.o ../8390.o
obj-$(CONFIG_ARM_ETHER3) += ether3.o
obj-$(CONFIG_ARM_ETHER1) += ether1.o
obj-$(CONFIG_ARM_AT91_ETHER) += at91_ether.o
+obj-$(CONFIG_ARM_KS8695_ETHER) += ks8695net.o
obj-$(CONFIG_EP93XX_ETH) += ep93xx_eth.o
obj-$(CONFIG_IXP4XX_ETH) += ixp4xx_eth.o
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c
index aa4a5246be53..0c628a9e5339 100644
--- a/drivers/net/arm/am79c961a.c
+++ b/drivers/net/arm/am79c961a.c
@@ -532,7 +532,6 @@ am79c961_rx(struct net_device *dev, struct dev_priv *priv)
am_writeword(dev, hdraddr + 2, RMD_OWN);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
priv->stats.rx_bytes += len;
priv->stats.rx_packets ++;
} else {
@@ -745,10 +744,8 @@ static int __init am79c961_probe(struct platform_device *pdev)
ret = register_netdev(dev);
if (ret == 0) {
- DECLARE_MAC_BUF(mac);
-
- printk(KERN_INFO "%s: ether address %s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "%s: ether address %pM\n",
+ dev->name, dev->dev_addr);
return 0;
}
diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c
index 6f431a887e7e..442938d50380 100644
--- a/drivers/net/arm/at91_ether.c
+++ b/drivers/net/arm/at91_ether.c
@@ -485,7 +485,6 @@ static void update_mac_address(struct net_device *dev)
static int set_mac_address(struct net_device *dev, void* addr)
{
struct sockaddr *address = addr;
- DECLARE_MAC_BUF(mac);
if (!is_valid_ether_addr(address->sa_data))
return -EADDRNOTAVAIL;
@@ -493,8 +492,8 @@ static int set_mac_address(struct net_device *dev, void* addr)
memcpy(dev->dev_addr, address->sa_data, dev->addr_len);
update_mac_address(dev);
- printk("%s: Setting MAC address to %s\n", dev->name,
- print_mac(mac, dev->dev_addr));
+ printk("%s: Setting MAC address to %pM\n", dev->name,
+ dev->dev_addr);
return 0;
}
@@ -894,7 +893,6 @@ static void at91ether_rx(struct net_device *dev)
memcpy(skb_put(skb, pktlen), p_recv, pktlen);
skb->protocol = eth_type_trans(skb, dev);
- dev->last_rx = jiffies;
dev->stats.rx_bytes += pktlen;
netif_rx(skb);
}
@@ -978,7 +976,6 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add
struct at91_private *lp;
unsigned int val;
int res;
- DECLARE_MAC_BUF(mac);
dev = alloc_etherdev(sizeof(struct at91_private));
if (!dev)
@@ -1084,11 +1081,11 @@ static int __init at91ether_setup(unsigned long phy_type, unsigned short phy_add
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 (%s)\n",
+ 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",
- print_mac(mac, dev->dev_addr));
+ dev->dev_addr);
if ((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)
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index 1267444d79da..6ecc600c1bcc 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -259,8 +259,6 @@ static int ep93xx_rx(struct net_device *dev, int processed, int budget)
skb_put(skb, length);
skb->protocol = eth_type_trans(skb, dev);
- dev->last_rx = jiffies;
-
netif_receive_skb(skb);
ep->stats.rx_packets++;
@@ -300,7 +298,7 @@ poll_some_more:
int more = 0;
spin_lock_irq(&ep->rx_lock);
- __netif_rx_complete(dev, napi);
+ __netif_rx_complete(napi);
wrl(ep, REG_INTEN, REG_INTEN_TX | REG_INTEN_RX);
if (ep93xx_have_more_rx(ep)) {
wrl(ep, REG_INTEN, REG_INTEN_TX);
@@ -417,9 +415,9 @@ static irqreturn_t ep93xx_irq(int irq, void *dev_id)
if (status & REG_INTSTS_RX) {
spin_lock(&ep->rx_lock);
- if (likely(netif_rx_schedule_prep(dev, &ep->napi))) {
+ if (likely(netif_rx_schedule_prep(&ep->napi))) {
wrl(ep, REG_INTEN, REG_INTEN_TX);
- __netif_rx_schedule(dev, &ep->napi);
+ __netif_rx_schedule(&ep->napi);
}
spin_unlock(&ep->rx_lock);
}
diff --git a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c
index 3bb9e293e2ef..e380de454463 100644
--- a/drivers/net/arm/ether1.c
+++ b/drivers/net/arm/ether1.c
@@ -996,7 +996,6 @@ ether1_probe(struct expansion_card *ec, const struct ecard_id *id)
{
struct net_device *dev;
int i, ret = 0;
- DECLARE_MAC_BUF(mac);
ether1_banner();
@@ -1044,8 +1043,8 @@ ether1_probe(struct expansion_card *ec, const struct ecard_id *id)
if (ret)
goto free;
- printk(KERN_INFO "%s: ether1 in slot %d, %s\n",
- dev->name, ec->slot_no, print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "%s: ether1 in slot %d, %pM\n",
+ dev->name, ec->slot_no, dev->dev_addr);
ecard_set_drvdata(ec, dev);
return 0;
diff --git a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c
index 67e96ae85035..21a7bef12d3b 100644
--- a/drivers/net/arm/ether3.c
+++ b/drivers/net/arm/ether3.c
@@ -776,7 +776,6 @@ ether3_probe(struct expansion_card *ec, const struct ecard_id *id)
const struct ether3_data *data = id->data;
struct net_device *dev;
int bus_type, ret;
- DECLARE_MAC_BUF(mac);
ether3_banner();
@@ -859,8 +858,8 @@ ether3_probe(struct expansion_card *ec, const struct ecard_id *id)
if (ret)
goto free;
- printk("%s: %s in slot %d, %s\n",
- dev->name, data->name, ec->slot_no, print_mac(mac, dev->dev_addr));
+ printk("%s: %s in slot %d, %pM\n",
+ dev->name, data->name, ec->slot_no, dev->dev_addr);
ecard_set_drvdata(ec, dev);
return 0;
diff --git a/drivers/net/arm/etherh.c b/drivers/net/arm/etherh.c
index 5c5f1e470d3c..6278606d1049 100644
--- a/drivers/net/arm/etherh.c
+++ b/drivers/net/arm/etherh.c
@@ -637,6 +637,21 @@ static const struct ethtool_ops etherh_ethtool_ops = {
.get_drvinfo = etherh_get_drvinfo,
};
+static const struct net_device_ops etherh_netdev_ops = {
+ .ndo_open = etherh_open,
+ .ndo_stop = etherh_close,
+ .ndo_set_config = etherh_set_config,
+ .ndo_start_xmit = ei_start_xmit,
+ .ndo_tx_timeout = ei_tx_timeout,
+ .ndo_get_stats = ei_get_stats,
+ .ndo_set_multicast_list = ei_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = ei_poll,
+#endif
+};
+
static u32 etherh_regoffsets[16];
static u32 etherm_regoffsets[16];
@@ -648,7 +663,6 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
struct net_device *dev;
struct etherh_priv *eh;
int ret;
- DECLARE_MAC_BUF(mac);
etherh_banner();
@@ -664,9 +678,7 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
SET_NETDEV_DEV(dev, &ec->dev);
- dev->open = etherh_open;
- dev->stop = etherh_close;
- dev->set_config = etherh_set_config;
+ dev->netdev_ops = &etherh_netdev_ops;
dev->irq = ec->irq;
dev->ethtool_ops = &etherh_ethtool_ops;
@@ -746,8 +758,8 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
if (ret)
goto free;
- printk(KERN_INFO "%s: %s in slot %d, %s\n",
- dev->name, data->name, ec->slot_no, print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "%s: %s in slot %d, %pM\n",
+ dev->name, data->name, ec->slot_no, dev->dev_addr);
ecard_set_drvdata(ec, dev);
diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c
index e2d702b8b2e4..26af411fc428 100644
--- a/drivers/net/arm/ixp4xx_eth.c
+++ b/drivers/net/arm/ixp4xx_eth.c
@@ -30,12 +30,11 @@
#include <linux/etherdevice.h>
#include <linux/io.h>
#include <linux/kernel.h>
-#include <linux/mii.h>
+#include <linux/phy.h>
#include <linux/platform_device.h>
#include <mach/npe.h>
#include <mach/qmgr.h>
-#define DEBUG_QUEUES 0
#define DEBUG_DESC 0
#define DEBUG_RX 0
#define DEBUG_TX 0
@@ -59,7 +58,6 @@
#define NAPI_WEIGHT 16
#define MDIO_INTERVAL (3 * HZ)
#define MAX_MDIO_RETRIES 100 /* microseconds, typically 30 cycles */
-#define MAX_MII_RESET_RETRIES 100 /* mdio_read() cycles, typically 4 */
#define MAX_CLOSE_WAIT 1000 /* microseconds, typically 2-3 cycles */
#define NPE_ID(port_id) ((port_id) >> 4)
@@ -164,15 +162,14 @@ struct port {
struct npe *npe;
struct net_device *netdev;
struct napi_struct napi;
- struct net_device_stats stat;
- struct mii_if_info mii;
- struct delayed_work mdio_thread;
+ struct phy_device *phydev;
struct eth_plat_info *plat;
buffer_t *rx_buff_tab[RX_DESCS], *tx_buff_tab[TX_DESCS];
struct desc *desc_tab; /* coherent */
u32 desc_tab_phys;
int id; /* logical port ID */
- u16 mii_bmcr;
+ int speed, duplex;
+ u8 firmware[4];
};
/* NPE message structure */
@@ -243,19 +240,20 @@ static inline void memcpy_swab32(u32 *dest, u32 *src, int cnt)
static spinlock_t mdio_lock;
static struct eth_regs __iomem *mdio_regs; /* mdio command and status only */
+struct mii_bus *mdio_bus;
static int ports_open;
static struct port *npe_port_tab[MAX_NPES];
static struct dma_pool *dma_pool;
-static u16 mdio_cmd(struct net_device *dev, int phy_id, int location,
- int write, u16 cmd)
+static int ixp4xx_mdio_cmd(struct mii_bus *bus, int phy_id, int location,
+ int write, u16 cmd)
{
int cycles = 0;
if (__raw_readl(&mdio_regs->mdio_command[3]) & 0x80) {
- printk(KERN_ERR "%s: MII not ready to transmit\n", dev->name);
- return 0;
+ printk(KERN_ERR "%s: MII not ready to transmit\n", bus->name);
+ return -1;
}
if (write) {
@@ -274,107 +272,119 @@ static u16 mdio_cmd(struct net_device *dev, int phy_id, int location,
}
if (cycles == MAX_MDIO_RETRIES) {
- printk(KERN_ERR "%s: MII write failed\n", dev->name);
- return 0;
+ printk(KERN_ERR "%s #%i: MII write failed\n", bus->name,
+ phy_id);
+ return -1;
}
#if DEBUG_MDIO
- printk(KERN_DEBUG "%s: mdio_cmd() took %i cycles\n", dev->name,
- cycles);
+ printk(KERN_DEBUG "%s #%i: mdio_%s() took %i cycles\n", bus->name,
+ phy_id, write ? "write" : "read", cycles);
#endif
if (write)
return 0;
if (__raw_readl(&mdio_regs->mdio_status[3]) & 0x80) {
- printk(KERN_ERR "%s: MII read failed\n", dev->name);
- return 0;
+#if DEBUG_MDIO
+ printk(KERN_DEBUG "%s #%i: MII read failed\n", bus->name,
+ phy_id);
+#endif
+ return 0xFFFF; /* don't return error */
}
return (__raw_readl(&mdio_regs->mdio_status[0]) & 0xFF) |
- (__raw_readl(&mdio_regs->mdio_status[1]) << 8);
+ ((__raw_readl(&mdio_regs->mdio_status[1]) & 0xFF) << 8);
}
-static int mdio_read(struct net_device *dev, int phy_id, int location)
+static int ixp4xx_mdio_read(struct mii_bus *bus, int phy_id, int location)
{
unsigned long flags;
- u16 val;
+ int ret;
spin_lock_irqsave(&mdio_lock, flags);
- val = mdio_cmd(dev, phy_id, location, 0, 0);
+ ret = ixp4xx_mdio_cmd(bus, phy_id, location, 0, 0);
spin_unlock_irqrestore(&mdio_lock, flags);
- return val;
+#if DEBUG_MDIO
+ printk(KERN_DEBUG "%s #%i: MII read [%i] -> 0x%X\n", bus->name,
+ phy_id, location, ret);
+#endif
+ return ret;
}
-static void mdio_write(struct net_device *dev, int phy_id, int location,
- int val)
+static int ixp4xx_mdio_write(struct mii_bus *bus, int phy_id, int location,
+ u16 val)
{
unsigned long flags;
+ int ret;
spin_lock_irqsave(&mdio_lock, flags);
- mdio_cmd(dev, phy_id, location, 1, val);
+ ret = ixp4xx_mdio_cmd(bus, phy_id, location, 1, val);
spin_unlock_irqrestore(&mdio_lock, flags);
+#if DEBUG_MDIO
+ printk(KERN_DEBUG "%s #%i: MII read [%i] <- 0x%X, err = %i\n",
+ bus->name, phy_id, location, val, ret);
+#endif
+ return ret;
}
-static void phy_reset(struct net_device *dev, int phy_id)
+static int ixp4xx_mdio_register(void)
{
- struct port *port = netdev_priv(dev);
- int cycles = 0;
+ int err;
- mdio_write(dev, phy_id, MII_BMCR, port->mii_bmcr | BMCR_RESET);
+ if (!(mdio_bus = mdiobus_alloc()))
+ return -ENOMEM;
- while (cycles < MAX_MII_RESET_RETRIES) {
- if (!(mdio_read(dev, phy_id, MII_BMCR) & BMCR_RESET)) {
-#if DEBUG_MDIO
- printk(KERN_DEBUG "%s: phy_reset() took %i cycles\n",
- dev->name, cycles);
-#endif
- return;
- }
- udelay(1);
- cycles++;
- }
+ /* All MII PHY accesses use NPE-B Ethernet registers */
+ spin_lock_init(&mdio_lock);
+ mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT;
+ __raw_writel(DEFAULT_CORE_CNTRL, &mdio_regs->core_control);
+
+ mdio_bus->name = "IXP4xx MII Bus";
+ mdio_bus->read = &ixp4xx_mdio_read;
+ mdio_bus->write = &ixp4xx_mdio_write;
+ strcpy(mdio_bus->id, "0");
- printk(KERN_ERR "%s: MII reset failed\n", dev->name);
+ if ((err = mdiobus_register(mdio_bus)))
+ mdiobus_free(mdio_bus);
+ return err;
}
-static void eth_set_duplex(struct port *port)
+static void ixp4xx_mdio_remove(void)
{
- if (port->mii.full_duplex)
- __raw_writel(DEFAULT_TX_CNTRL0 & ~TX_CNTRL0_HALFDUPLEX,
- &port->regs->tx_control[0]);
- else
- __raw_writel(DEFAULT_TX_CNTRL0 | TX_CNTRL0_HALFDUPLEX,
- &port->regs->tx_control[0]);
+ mdiobus_unregister(mdio_bus);
+ mdiobus_free(mdio_bus);
}
-static void phy_check_media(struct port *port, int init)
+static void ixp4xx_adjust_link(struct net_device *dev)
{
- if (mii_check_media(&port->mii, 1, init))
- eth_set_duplex(port);
- if (port->mii.force_media) { /* mii_check_media() doesn't work */
- struct net_device *dev = port->netdev;
- int cur_link = mii_link_ok(&port->mii);
- int prev_link = netif_carrier_ok(dev);
-
- if (!prev_link && cur_link) {
- printk(KERN_INFO "%s: link up\n", dev->name);
- netif_carrier_on(dev);
- } else if (prev_link && !cur_link) {
+ struct port *port = netdev_priv(dev);
+ struct phy_device *phydev = port->phydev;
+
+ if (!phydev->link) {
+ if (port->speed) {
+ port->speed = 0;
printk(KERN_INFO "%s: link down\n", dev->name);
- netif_carrier_off(dev);
}
+ return;
}
-}
+ if (port->speed == phydev->speed && port->duplex == phydev->duplex)
+ return;
-static void mdio_thread(struct work_struct *work)
-{
- struct port *port = container_of(work, struct port, mdio_thread.work);
+ port->speed = phydev->speed;
+ port->duplex = phydev->duplex;
+
+ if (port->duplex)
+ __raw_writel(DEFAULT_TX_CNTRL0 & ~TX_CNTRL0_HALFDUPLEX,
+ &port->regs->tx_control[0]);
+ else
+ __raw_writel(DEFAULT_TX_CNTRL0 | TX_CNTRL0_HALFDUPLEX,
+ &port->regs->tx_control[0]);
- phy_check_media(port, 0);
- schedule_delayed_work(&port->mdio_thread, MDIO_INTERVAL);
+ printk(KERN_INFO "%s: link up, speed %u Mb/s, %s duplex\n",
+ dev->name, port->speed, port->duplex ? "full" : "half");
}
@@ -412,47 +422,13 @@ static inline void debug_desc(u32 phys, struct desc *desc)
#endif
}
-static inline void debug_queue(unsigned int queue, int is_get, u32 phys)
-{
-#if DEBUG_QUEUES
- static struct {
- int queue;
- char *name;
- } names[] = {
- { TX_QUEUE(0x10), "TX#0 " },
- { TX_QUEUE(0x20), "TX#1 " },
- { TX_QUEUE(0x00), "TX#2 " },
- { RXFREE_QUEUE(0x10), "RX-free#0 " },
- { RXFREE_QUEUE(0x20), "RX-free#1 " },
- { RXFREE_QUEUE(0x00), "RX-free#2 " },
- { TXDONE_QUEUE, "TX-done " },
- };
- int i;
-
- for (i = 0; i < ARRAY_SIZE(names); i++)
- if (names[i].queue == queue)
- break;
-
- printk(KERN_DEBUG "Queue %i %s%s %X\n", queue,
- i < ARRAY_SIZE(names) ? names[i].name : "",
- is_get ? "->" : "<-", phys);
-#endif
-}
-
-static inline u32 queue_get_entry(unsigned int queue)
-{
- u32 phys = qmgr_get_entry(queue);
- debug_queue(queue, 1, phys);
- return phys;
-}
-
static inline int queue_get_desc(unsigned int queue, struct port *port,
int is_tx)
{
u32 phys, tab_phys, n_desc;
struct desc *tab;
- if (!(phys = queue_get_entry(queue)))
+ if (!(phys = qmgr_get_entry(queue)))
return -1;
phys &= ~0x1F; /* mask out non-address bits */
@@ -468,7 +444,6 @@ static inline int queue_get_desc(unsigned int queue, struct port *port,
static inline void queue_put_desc(unsigned int queue, u32 phys,
struct desc *desc)
{
- debug_queue(queue, 0, phys);
debug_desc(phys, desc);
BUG_ON(phys & 0x1F);
qmgr_put_entry(queue, phys);
@@ -498,7 +473,7 @@ static void eth_rx_irq(void *pdev)
printk(KERN_DEBUG "%s: eth_rx_irq\n", dev->name);
#endif
qmgr_disable_irq(port->plat->rxq);
- netif_rx_schedule(dev, &port->napi);
+ netif_rx_schedule(&port->napi);
}
static int eth_poll(struct napi_struct *napi, int budget)
@@ -526,7 +501,7 @@ static int eth_poll(struct napi_struct *napi, int budget)
printk(KERN_DEBUG "%s: eth_poll netif_rx_complete\n",
dev->name);
#endif
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
qmgr_enable_irq(rxq);
if (!qmgr_stat_empty(rxq) &&
netif_rx_reschedule(dev, napi)) {
@@ -562,7 +537,7 @@ static int eth_poll(struct napi_struct *napi, int budget)
#endif
if (!skb) {
- port->stat.rx_dropped++;
+ dev->stats.rx_dropped++;
/* put the desc back on RX-ready queue */
desc->buf_len = MAX_MRU;
desc->pkt_len = 0;
@@ -588,9 +563,8 @@ static int eth_poll(struct napi_struct *napi, int budget)
debug_pkt(dev, "eth_poll", skb->data, skb->len);
skb->protocol = eth_type_trans(skb, dev);
- dev->last_rx = jiffies;
- port->stat.rx_packets++;
- port->stat.rx_bytes += skb->len;
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += skb->len;
netif_receive_skb(skb);
/* put the new buffer on RX-free queue */
@@ -618,7 +592,7 @@ static void eth_txdone_irq(void *unused)
#if DEBUG_TX
printk(KERN_DEBUG DRV_NAME ": eth_txdone_irq\n");
#endif
- while ((phys = queue_get_entry(TXDONE_QUEUE)) != 0) {
+ while ((phys = qmgr_get_entry(TXDONE_QUEUE)) != 0) {
u32 npe_id, n_desc;
struct port *port;
struct desc *desc;
@@ -635,8 +609,8 @@ static void eth_txdone_irq(void *unused)
debug_desc(phys, desc);
if (port->tx_buff_tab[n_desc]) { /* not the draining packet */
- port->stat.tx_packets++;
- port->stat.tx_bytes += desc->pkt_len;
+ port->netdev->stats.tx_packets++;
+ port->netdev->stats.tx_bytes += desc->pkt_len;
dma_unmap_tx(port, desc);
#if DEBUG_TX
@@ -674,7 +648,7 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev)
if (unlikely(skb->len > MAX_MRU)) {
dev_kfree_skb(skb);
- port->stat.tx_errors++;
+ dev->stats.tx_errors++;
return NETDEV_TX_OK;
}
@@ -690,7 +664,7 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev)
bytes = ALIGN(offset + len, 4);
if (!(mem = kmalloc(bytes, GFP_ATOMIC))) {
dev_kfree_skb(skb);
- port->stat.tx_dropped++;
+ dev->stats.tx_dropped++;
return NETDEV_TX_OK;
}
memcpy_swab32(mem, (u32 *)((int)skb->data & ~3), bytes / 4);
@@ -704,7 +678,7 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev)
#else
kfree(mem);
#endif
- port->stat.tx_dropped++;
+ dev->stats.tx_dropped++;
return NETDEV_TX_OK;
}
@@ -747,12 +721,6 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev)
}
-static struct net_device_stats *eth_stats(struct net_device *dev)
-{
- struct port *port = netdev_priv(dev);
- return &port->stat;
-}
-
static void eth_set_mcast_list(struct net_device *dev)
{
struct port *port = netdev_priv(dev);
@@ -786,41 +754,80 @@ static void eth_set_mcast_list(struct net_device *dev)
static int eth_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
{
struct port *port = netdev_priv(dev);
- unsigned int duplex_chg;
- int err;
if (!netif_running(dev))
return -EINVAL;
- err = generic_mii_ioctl(&port->mii, if_mii(req), cmd, &duplex_chg);
- if (duplex_chg)
- eth_set_duplex(port);
- return err;
+ return phy_mii_ioctl(port->phydev, if_mii(req), cmd);
+}
+
+/* ethtool support */
+
+static void ixp4xx_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ struct port *port = netdev_priv(dev);
+ strcpy(info->driver, DRV_NAME);
+ snprintf(info->fw_version, sizeof(info->fw_version), "%u:%u:%u:%u",
+ port->firmware[0], port->firmware[1],
+ port->firmware[2], port->firmware[3]);
+ strcpy(info->bus_info, "internal");
}
+static int ixp4xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct port *port = netdev_priv(dev);
+ return phy_ethtool_gset(port->phydev, cmd);
+}
+
+static int ixp4xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct port *port = netdev_priv(dev);
+ return phy_ethtool_sset(port->phydev, cmd);
+}
+
+static int ixp4xx_nway_reset(struct net_device *dev)
+{
+ struct port *port = netdev_priv(dev);
+ return phy_start_aneg(port->phydev);
+}
+
+static 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,
+};
+
static int request_queues(struct port *port)
{
int err;
- err = qmgr_request_queue(RXFREE_QUEUE(port->id), RX_DESCS, 0, 0);
+ err = qmgr_request_queue(RXFREE_QUEUE(port->id), RX_DESCS, 0, 0,
+ "%s:RX-free", port->netdev->name);
if (err)
return err;
- err = qmgr_request_queue(port->plat->rxq, RX_DESCS, 0, 0);
+ err = qmgr_request_queue(port->plat->rxq, RX_DESCS, 0, 0,
+ "%s:RX", port->netdev->name);
if (err)
goto rel_rxfree;
- err = qmgr_request_queue(TX_QUEUE(port->id), TX_DESCS, 0, 0);
+ err = qmgr_request_queue(TX_QUEUE(port->id), TX_DESCS, 0, 0,
+ "%s:TX", port->netdev->name);
if (err)
goto rel_rx;
- err = qmgr_request_queue(port->plat->txreadyq, TX_DESCS, 0, 0);
+ err = qmgr_request_queue(port->plat->txreadyq, TX_DESCS, 0, 0,
+ "%s:TX-ready", port->netdev->name);
if (err)
goto rel_tx;
/* TX-done queue handles skbs sent out by the NPEs */
if (!ports_open) {
- err = qmgr_request_queue(TXDONE_QUEUE, TXDONE_QUEUE_LEN, 0, 0);
+ err = qmgr_request_queue(TXDONE_QUEUE, TXDONE_QUEUE_LEN, 0, 0,
+ "%s:TX-done", DRV_NAME);
if (err)
goto rel_txready;
}
@@ -944,10 +951,12 @@ static int eth_open(struct net_device *dev)
npe_name(npe));
return -EIO;
}
+ port->firmware[0] = msg.byte4;
+ port->firmware[1] = msg.byte5;
+ port->firmware[2] = msg.byte6;
+ port->firmware[3] = msg.byte7;
}
- mdio_write(dev, port->plat->phy, MII_BMCR, port->mii_bmcr);
-
memset(&msg, 0, sizeof(msg));
msg.cmd = NPE_VLAN_SETRXQOSENTRY;
msg.eth_id = port->id;
@@ -985,6 +994,9 @@ static int eth_open(struct net_device *dev)
return err;
}
+ port->speed = 0; /* force "link up" message */
+ phy_start(port->phydev);
+
for (i = 0; i < ETH_ALEN; i++)
__raw_writel(dev->dev_addr[i], &port->regs->hw_addr[i]);
__raw_writel(0x08, &port->regs->random_seed);
@@ -1012,10 +1024,8 @@ static int eth_open(struct net_device *dev)
__raw_writel(DEFAULT_RX_CNTRL0, &port->regs->rx_control[0]);
napi_enable(&port->napi);
- phy_check_media(port, 1);
eth_set_mcast_list(dev);
netif_start_queue(dev);
- schedule_delayed_work(&port->mdio_thread, MDIO_INTERVAL);
qmgr_set_irq(port->plat->rxq, QUEUE_IRQ_SRC_NOT_EMPTY,
eth_rx_irq, dev);
@@ -1026,7 +1036,7 @@ static int eth_open(struct net_device *dev)
}
ports_open++;
/* we may already have RX data, enables IRQ */
- netif_rx_schedule(dev, &port->napi);
+ netif_rx_schedule(&port->napi);
return 0;
}
@@ -1106,25 +1116,31 @@ static int eth_close(struct net_device *dev)
printk(KERN_CRIT "%s: unable to disable loopback\n",
dev->name);
- port->mii_bmcr = mdio_read(dev, port->plat->phy, MII_BMCR) &
- ~(BMCR_RESET | BMCR_PDOWN); /* may have been altered */
- mdio_write(dev, port->plat->phy, MII_BMCR,
- port->mii_bmcr | BMCR_PDOWN);
+ phy_stop(port->phydev);
if (!ports_open)
qmgr_disable_irq(TXDONE_QUEUE);
- cancel_rearming_delayed_work(&port->mdio_thread);
destroy_queues(port);
release_queues(port);
return 0;
}
+static const struct net_device_ops ixp4xx_netdev_ops = {
+ .ndo_open = eth_open,
+ .ndo_stop = eth_close,
+ .ndo_start_xmit = eth_xmit,
+ .ndo_set_multicast_list = eth_set_mcast_list,
+ .ndo_do_ioctl = eth_ioctl,
+
+};
+
static int __devinit eth_init_one(struct platform_device *pdev)
{
struct port *port;
struct net_device *dev;
struct eth_plat_info *plat = pdev->dev.platform_data;
u32 regs_phys;
+ char phy_id[BUS_ID_SIZE];
int err;
if (!(dev = alloc_etherdev(sizeof(struct port))))
@@ -1153,12 +1169,8 @@ static int __devinit eth_init_one(struct platform_device *pdev)
goto err_free;
}
- dev->open = eth_open;
- dev->hard_start_xmit = eth_xmit;
- dev->stop = eth_close;
- dev->get_stats = eth_stats;
- dev->do_ioctl = eth_ioctl;
- dev->set_multicast_list = eth_set_mcast_list;
+ dev->netdev_ops = &ixp4xx_netdev_ops;
+ dev->ethtool_ops = &ixp4xx_ethtool_ops;
dev->tx_queue_len = 100;
netif_napi_add(dev, &port->napi, eth_poll, NAPI_WEIGHT);
@@ -1191,22 +1203,19 @@ static int __devinit eth_init_one(struct platform_device *pdev)
__raw_writel(DEFAULT_CORE_CNTRL, &port->regs->core_control);
udelay(50);
- port->mii.dev = dev;
- port->mii.mdio_read = mdio_read;
- port->mii.mdio_write = mdio_write;
- port->mii.phy_id = plat->phy;
- port->mii.phy_id_mask = 0x1F;
- port->mii.reg_num_mask = 0x1F;
+ snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, "0", plat->phy);
+ port->phydev = phy_connect(dev, phy_id, &ixp4xx_adjust_link, 0,
+ PHY_INTERFACE_MODE_MII);
+ if (IS_ERR(port->phydev)) {
+ printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+ return PTR_ERR(port->phydev);
+ }
+
+ port->phydev->irq = PHY_POLL;
printk(KERN_INFO "%s: MII PHY %i on %s\n", dev->name, plat->phy,
npe_name(port->npe));
- phy_reset(dev, plat->phy);
- port->mii_bmcr = mdio_read(dev, plat->phy, MII_BMCR) &
- ~(BMCR_RESET | BMCR_PDOWN);
- mdio_write(dev, plat->phy, MII_BMCR, port->mii_bmcr | BMCR_PDOWN);
-
- INIT_DELAYED_WORK(&port->mdio_thread, mdio_thread);
return 0;
err_unreg:
@@ -1232,7 +1241,7 @@ static int __devexit eth_remove_one(struct platform_device *pdev)
return 0;
}
-static struct platform_driver drv = {
+static struct platform_driver ixp4xx_eth_driver = {
.driver.name = DRV_NAME,
.probe = eth_init_one,
.remove = eth_remove_one,
@@ -1240,20 +1249,19 @@ static struct platform_driver drv = {
static int __init eth_init_module(void)
{
+ int err;
if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEB_ETH0))
return -ENOSYS;
- /* All MII PHY accesses use NPE-B Ethernet registers */
- spin_lock_init(&mdio_lock);
- mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT;
- __raw_writel(DEFAULT_CORE_CNTRL, &mdio_regs->core_control);
-
- return platform_driver_register(&drv);
+ if ((err = ixp4xx_mdio_register()))
+ return err;
+ return platform_driver_register(&ixp4xx_eth_driver);
}
static void __exit eth_cleanup_module(void)
{
- platform_driver_unregister(&drv);
+ platform_driver_unregister(&ixp4xx_eth_driver);
+ ixp4xx_mdio_remove();
}
MODULE_AUTHOR("Krzysztof Halasa");
diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c
new file mode 100644
index 000000000000..592daee9dc28
--- /dev/null
+++ b/drivers/net/arm/ks8695net.c
@@ -0,0 +1,1676 @@
+/*
+ * Micrel KS8695 (Centaur) Ethernet.
+ *
+ * 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.
+ *
+ * Copyright 2008 Simtec Electronics
+ * Daniel Silverstone <dsilvers@simtec.co.uk>
+ * Vincent Sanders <vince@simtec.co.uk>
+ */
+
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/crc32.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/irq.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <asm/irq.h>
+
+#include <mach/regs-switch.h>
+#include <mach/regs-misc.h>
+
+#include "ks8695net.h"
+
+#define MODULENAME "ks8695_ether"
+#define MODULEVERSION "1.01"
+
+/*
+ * Transmit and device reset timeout, default 5 seconds.
+ */
+static int watchdog = 5000;
+
+/* Hardware structures */
+
+/**
+ * struct rx_ring_desc - Receive descriptor ring element
+ * @status: The status of the descriptor element (E.g. who owns it)
+ * @length: The number of bytes in the block pointed to by data_ptr
+ * @data_ptr: The physical address of the data block to receive into
+ * @next_desc: The physical address of the next descriptor element.
+ */
+struct rx_ring_desc {
+ __le32 status;
+ __le32 length;
+ __le32 data_ptr;
+ __le32 next_desc;
+};
+
+/**
+ * struct tx_ring_desc - Transmit descriptor ring element
+ * @owner: Who owns the descriptor
+ * @status: The number of bytes in the block pointed to by data_ptr
+ * @data_ptr: The physical address of the data block to receive into
+ * @next_desc: The physical address of the next descriptor element.
+ */
+struct tx_ring_desc {
+ __le32 owner;
+ __le32 status;
+ __le32 data_ptr;
+ __le32 next_desc;
+};
+
+/**
+ * struct ks8695_skbuff - sk_buff wrapper for rx/tx rings.
+ * @skb: The buffer in the ring
+ * @dma_ptr: The mapped DMA pointer of the buffer
+ * @length: The number of bytes mapped to dma_ptr
+ */
+struct ks8695_skbuff {
+ struct sk_buff *skb;
+ dma_addr_t dma_ptr;
+ u32 length;
+};
+
+/* Private device structure */
+
+#define MAX_TX_DESC 8
+#define MAX_TX_DESC_MASK 0x7
+#define MAX_RX_DESC 16
+#define MAX_RX_DESC_MASK 0xf
+
+#define MAX_RXBUF_SIZE 0x700
+
+#define TX_RING_DMA_SIZE (sizeof(struct tx_ring_desc) * MAX_TX_DESC)
+#define RX_RING_DMA_SIZE (sizeof(struct rx_ring_desc) * MAX_RX_DESC)
+#define RING_DMA_SIZE (TX_RING_DMA_SIZE + RX_RING_DMA_SIZE)
+
+/**
+ * enum ks8695_dtype - Device type
+ * @KS8695_DTYPE_WAN: This device is a WAN interface
+ * @KS8695_DTYPE_LAN: This device is a LAN interface
+ * @KS8695_DTYPE_HPNA: This device is an HPNA interface
+ */
+enum ks8695_dtype {
+ KS8695_DTYPE_WAN,
+ KS8695_DTYPE_LAN,
+ KS8695_DTYPE_HPNA,
+};
+
+/**
+ * struct ks8695_priv - Private data for the KS8695 Ethernet
+ * @in_suspend: Flag to indicate if we're suspending/resuming
+ * @ndev: The net_device for this interface
+ * @dev: The platform device object for this interface
+ * @dtype: The type of this device
+ * @io_regs: The ioremapped registers for this interface
+ * @rx_irq_name: The textual name of the RX IRQ from the platform data
+ * @tx_irq_name: The textual name of the TX IRQ from the platform data
+ * @link_irq_name: The textual name of the link IRQ from the
+ * platform data if available
+ * @rx_irq: The IRQ number for the RX IRQ
+ * @tx_irq: The IRQ number for the TX IRQ
+ * @link_irq: The IRQ number for the link IRQ if available
+ * @regs_req: The resource request for the registers region
+ * @phyiface_req: The resource request for the phy/switch region
+ * if available
+ * @phyiface_regs: The ioremapped registers for the phy/switch if available
+ * @ring_base: The base pointer of the dma coherent memory for the rings
+ * @ring_base_dma: The DMA mapped equivalent of ring_base
+ * @tx_ring: The pointer in ring_base of the TX ring
+ * @tx_ring_used: The number of slots in the TX ring which are occupied
+ * @tx_ring_next_slot: The next slot to fill in the TX ring
+ * @tx_ring_dma: The DMA mapped equivalent of tx_ring
+ * @tx_buffers: The sk_buff mappings for the TX ring
+ * @txq_lock: A lock to protect the tx_buffers tx_ring_used etc variables
+ * @rx_ring: The pointer in ring_base of the RX ring
+ * @rx_ring_dma: The DMA mapped equivalent of rx_ring
+ * @rx_buffers: The sk_buff mappings for the RX ring
+ * @next_rx_desc_read: The next RX descriptor to read from on IRQ
+ * @msg_enable: The flags for which messages to emit
+ */
+struct ks8695_priv {
+ int in_suspend;
+ struct net_device *ndev;
+ struct device *dev;
+ enum ks8695_dtype dtype;
+ void __iomem *io_regs;
+
+ const char *rx_irq_name, *tx_irq_name, *link_irq_name;
+ int rx_irq, tx_irq, link_irq;
+
+ struct resource *regs_req, *phyiface_req;
+ void __iomem *phyiface_regs;
+
+ void *ring_base;
+ dma_addr_t ring_base_dma;
+
+ struct tx_ring_desc *tx_ring;
+ int tx_ring_used;
+ int tx_ring_next_slot;
+ dma_addr_t tx_ring_dma;
+ struct ks8695_skbuff tx_buffers[MAX_TX_DESC];
+ spinlock_t txq_lock;
+
+ struct rx_ring_desc *rx_ring;
+ dma_addr_t rx_ring_dma;
+ struct ks8695_skbuff rx_buffers[MAX_RX_DESC];
+ int next_rx_desc_read;
+
+ int msg_enable;
+};
+
+/* Register access */
+
+/**
+ * ks8695_readreg - Read from a KS8695 ethernet register
+ * @ksp: The device to read from
+ * @reg: The register to read
+ */
+static inline u32
+ks8695_readreg(struct ks8695_priv *ksp, int reg)
+{
+ return readl(ksp->io_regs + reg);
+}
+
+/**
+ * ks8695_writereg - Write to a KS8695 ethernet register
+ * @ksp: The device to write to
+ * @reg: The register to write
+ * @value: The value to write to the register
+ */
+static inline void
+ks8695_writereg(struct ks8695_priv *ksp, int reg, u32 value)
+{
+ writel(value, ksp->io_regs + reg);
+}
+
+/* Utility functions */
+
+/**
+ * ks8695_port_type - Retrieve port-type as user-friendly string
+ * @ksp: The device to return the type for
+ *
+ * Returns a string indicating which of the WAN, LAN or HPNA
+ * ports this device is likely to represent.
+ */
+static const char *
+ks8695_port_type(struct ks8695_priv *ksp)
+{
+ switch (ksp->dtype) {
+ case KS8695_DTYPE_LAN:
+ return "LAN";
+ case KS8695_DTYPE_WAN:
+ return "WAN";
+ case KS8695_DTYPE_HPNA:
+ return "HPNA";
+ }
+
+ return "UNKNOWN";
+}
+
+/**
+ * ks8695_update_mac - Update the MAC registers in the device
+ * @ksp: The device to update
+ *
+ * Updates the MAC registers in the KS8695 device from the address in the
+ * net_device structure associated with this interface.
+ */
+static void
+ks8695_update_mac(struct ks8695_priv *ksp)
+{
+ /* Update the HW with the MAC from the net_device */
+ struct net_device *ndev = ksp->ndev;
+ u32 machigh, maclow;
+
+ maclow = ((ndev->dev_addr[2] << 24) | (ndev->dev_addr[3] << 16) |
+ (ndev->dev_addr[4] << 8) | (ndev->dev_addr[5] << 0));
+ machigh = ((ndev->dev_addr[0] << 8) | (ndev->dev_addr[1] << 0));
+
+ ks8695_writereg(ksp, KS8695_MAL, maclow);
+ ks8695_writereg(ksp, KS8695_MAH, machigh);
+
+}
+
+/**
+ * ks8695_refill_rxbuffers - Re-fill the RX buffer ring
+ * @ksp: The device to refill
+ *
+ * Iterates the RX ring of the device looking for empty slots.
+ * For each empty slot, we allocate and map a new SKB and give it
+ * to the hardware.
+ * This can be called from interrupt context safely.
+ */
+static void
+ks8695_refill_rxbuffers(struct ks8695_priv *ksp)
+{
+ /* Run around the RX ring, filling in any missing sk_buff's */
+ int buff_n;
+
+ for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) {
+ if (!ksp->rx_buffers[buff_n].skb) {
+ struct sk_buff *skb = dev_alloc_skb(MAX_RXBUF_SIZE);
+ dma_addr_t mapping;
+
+ ksp->rx_buffers[buff_n].skb = skb;
+ if (skb == NULL) {
+ /* Failed to allocate one, perhaps
+ * we'll try again later.
+ */
+ break;
+ }
+
+ mapping = dma_map_single(ksp->dev, skb->data,
+ MAX_RXBUF_SIZE,
+ DMA_FROM_DEVICE);
+ if (unlikely(dma_mapping_error(ksp->dev, mapping))) {
+ /* Failed to DMA map this SKB, try later */
+ dev_kfree_skb_irq(skb);
+ ksp->rx_buffers[buff_n].skb = NULL;
+ break;
+ }
+ ksp->rx_buffers[buff_n].dma_ptr = mapping;
+ skb->dev = ksp->ndev;
+ ksp->rx_buffers[buff_n].length = MAX_RXBUF_SIZE;
+
+ /* Record this into the DMA ring */
+ ksp->rx_ring[buff_n].data_ptr = cpu_to_le32(mapping);
+ ksp->rx_ring[buff_n].length =
+ cpu_to_le32(MAX_RXBUF_SIZE);
+
+ wmb();
+
+ /* And give ownership over to the hardware */
+ ksp->rx_ring[buff_n].status = cpu_to_le32(RDES_OWN);
+ }
+ }
+}
+
+/* Maximum number of multicast addresses which the KS8695 HW supports */
+#define KS8695_NR_ADDRESSES 16
+
+/**
+ * ks8695_init_partial_multicast - Init the mcast addr registers
+ * @ksp: The device to initialise
+ * @addr: The multicast address list to use
+ * @nr_addr: The number of addresses in the list
+ *
+ * This routine is a helper for ks8695_set_multicast - it writes
+ * the additional-address registers in the KS8695 ethernet device
+ * and cleans up any others left behind.
+ */
+static void
+ks8695_init_partial_multicast(struct ks8695_priv *ksp,
+ struct dev_mc_list *addr,
+ int nr_addr)
+{
+ u32 low, high;
+ int i;
+
+ for (i = 0; i < nr_addr; i++, addr = addr->next) {
+ /* Ran out of addresses? */
+ if (!addr)
+ break;
+ /* Ran out of space in chip? */
+ BUG_ON(i == KS8695_NR_ADDRESSES);
+
+ low = (addr->dmi_addr[2] << 24) | (addr->dmi_addr[3] << 16) |
+ (addr->dmi_addr[4] << 8) | (addr->dmi_addr[5]);
+ high = (addr->dmi_addr[0] << 8) | (addr->dmi_addr[1]);
+
+ ks8695_writereg(ksp, KS8695_AAL_(i), low);
+ ks8695_writereg(ksp, KS8695_AAH_(i), AAH_E | high);
+ }
+
+ /* Clear the remaining Additional Station Addresses */
+ for (; i < KS8695_NR_ADDRESSES; i++) {
+ ks8695_writereg(ksp, KS8695_AAL_(i), 0);
+ ks8695_writereg(ksp, KS8695_AAH_(i), 0);
+ }
+}
+
+/* Interrupt handling */
+
+/**
+ * ks8695_tx_irq - Transmit IRQ handler
+ * @irq: The IRQ which went off (ignored)
+ * @dev_id: The net_device for the interrupt
+ *
+ * Process the TX ring, clearing out any transmitted slots.
+ * Allows the net_device to pass us new packets once slots are
+ * freed.
+ */
+static irqreturn_t
+ks8695_tx_irq(int irq, void *dev_id)
+{
+ struct net_device *ndev = (struct net_device *)dev_id;
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ int buff_n;
+
+ for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) {
+ if (ksp->tx_buffers[buff_n].skb &&
+ !(ksp->tx_ring[buff_n].owner & cpu_to_le32(TDES_OWN))) {
+ rmb();
+ /* An SKB which is not owned by HW is present */
+ /* Update the stats for the net_device */
+ ndev->stats.tx_packets++;
+ ndev->stats.tx_bytes += ksp->tx_buffers[buff_n].length;
+
+ /* Free the packet from the ring */
+ ksp->tx_ring[buff_n].data_ptr = 0;
+
+ /* Free the sk_buff */
+ dma_unmap_single(ksp->dev,
+ ksp->tx_buffers[buff_n].dma_ptr,
+ ksp->tx_buffers[buff_n].length,
+ DMA_TO_DEVICE);
+ dev_kfree_skb_irq(ksp->tx_buffers[buff_n].skb);
+ ksp->tx_buffers[buff_n].skb = NULL;
+ ksp->tx_ring_used--;
+ }
+ }
+
+ netif_wake_queue(ndev);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * ks8695_rx_irq - Receive IRQ handler
+ * @irq: The IRQ which went off (ignored)
+ * @dev_id: The net_device for the interrupt
+ *
+ * Process the RX ring, passing any received packets up to the
+ * host. If we received anything other than errors, we then
+ * refill the ring.
+ */
+static irqreturn_t
+ks8695_rx_irq(int irq, void *dev_id)
+{
+ struct net_device *ndev = (struct net_device *)dev_id;
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ struct sk_buff *skb;
+ int buff_n;
+ u32 flags;
+ int pktlen;
+ int last_rx_processed = -1;
+
+ buff_n = ksp->next_rx_desc_read;
+ do {
+ if (ksp->rx_buffers[buff_n].skb &&
+ !(ksp->rx_ring[buff_n].status & cpu_to_le32(RDES_OWN))) {
+ rmb();
+ flags = le32_to_cpu(ksp->rx_ring[buff_n].status);
+ /* Found an SKB which we own, this means we
+ * received a packet
+ */
+ if ((flags & (RDES_FS | RDES_LS)) !=
+ (RDES_FS | RDES_LS)) {
+ /* This packet is not the first and
+ * the last segment. Therefore it is
+ * a "spanning" packet and we can't
+ * handle it
+ */
+ goto rx_failure;
+ }
+
+ if (flags & (RDES_ES | RDES_RE)) {
+ /* It's an error packet */
+ ndev->stats.rx_errors++;
+ if (flags & RDES_TL)
+ ndev->stats.rx_length_errors++;
+ if (flags & RDES_RF)
+ ndev->stats.rx_length_errors++;
+ if (flags & RDES_CE)
+ ndev->stats.rx_crc_errors++;
+ if (flags & RDES_RE)
+ ndev->stats.rx_missed_errors++;
+
+ goto rx_failure;
+ }
+
+ pktlen = flags & RDES_FLEN;
+ pktlen -= 4; /* Drop the CRC */
+
+ /* Retrieve the sk_buff */
+ skb = ksp->rx_buffers[buff_n].skb;
+
+ /* Clear it from the ring */
+ ksp->rx_buffers[buff_n].skb = NULL;
+ ksp->rx_ring[buff_n].data_ptr = 0;
+
+ /* Unmap the SKB */
+ dma_unmap_single(ksp->dev,
+ ksp->rx_buffers[buff_n].dma_ptr,
+ ksp->rx_buffers[buff_n].length,
+ DMA_FROM_DEVICE);
+
+ /* Relinquish the SKB to the network layer */
+ skb_put(skb, pktlen);
+ skb->protocol = eth_type_trans(skb, ndev);
+ netif_rx(skb);
+
+ /* Record stats */
+ ndev->last_rx = jiffies;
+ ndev->stats.rx_packets++;
+ ndev->stats.rx_bytes += pktlen;
+ goto rx_finished;
+
+rx_failure:
+ /* This ring entry is an error, but we can
+ * re-use the skb
+ */
+ /* Give the ring entry back to the hardware */
+ ksp->rx_ring[buff_n].status = cpu_to_le32(RDES_OWN);
+rx_finished:
+ /* And note this as processed so we can start
+ * from here next time
+ */
+ last_rx_processed = buff_n;
+ } else {
+ /* Ran out of things to process, stop now */
+ break;
+ }
+ buff_n = (buff_n + 1) & MAX_RX_DESC_MASK;
+ } while (buff_n != ksp->next_rx_desc_read);
+
+ /* And note which RX descriptor we last did anything with */
+ if (likely(last_rx_processed != -1))
+ ksp->next_rx_desc_read =
+ (last_rx_processed + 1) & MAX_RX_DESC_MASK;
+
+ /* And refill the buffers */
+ ks8695_refill_rxbuffers(ksp);
+
+ /* Kick the RX DMA engine, in case it became suspended */
+ ks8695_writereg(ksp, KS8695_DRSC, 0);
+
+ return IRQ_HANDLED;
+}
+
+/**
+ * ks8695_link_irq - Link change IRQ handler
+ * @irq: The IRQ which went off (ignored)
+ * @dev_id: The net_device for the interrupt
+ *
+ * The WAN interface can generate an IRQ when the link changes,
+ * report this to the net layer and the user.
+ */
+static irqreturn_t
+ks8695_link_irq(int irq, void *dev_id)
+{
+ struct net_device *ndev = (struct net_device *)dev_id;
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ u32 ctrl;
+
+ ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
+ if (ctrl & WMC_WLS) {
+ netif_carrier_on(ndev);
+ if (netif_msg_link(ksp))
+ dev_info(ksp->dev,
+ "%s: Link is now up (10%sMbps/%s-duplex)\n",
+ ndev->name,
+ (ctrl & WMC_WSS) ? "0" : "",
+ (ctrl & WMC_WDS) ? "Full" : "Half");
+ } else {
+ netif_carrier_off(ndev);
+ if (netif_msg_link(ksp))
+ dev_info(ksp->dev, "%s: Link is now down.\n",
+ ndev->name);
+ }
+
+ return IRQ_HANDLED;
+}
+
+
+/* KS8695 Device functions */
+
+/**
+ * ks8695_reset - Reset a KS8695 ethernet interface
+ * @ksp: The interface to reset
+ *
+ * Perform an engine reset of the interface and re-program it
+ * with sensible defaults.
+ */
+static void
+ks8695_reset(struct ks8695_priv *ksp)
+{
+ int reset_timeout = watchdog;
+ /* Issue the reset via the TX DMA control register */
+ ks8695_writereg(ksp, KS8695_DTXC, DTXC_TRST);
+ while (reset_timeout--) {
+ if (!(ks8695_readreg(ksp, KS8695_DTXC) & DTXC_TRST))
+ break;
+ msleep(1);
+ }
+
+ if (reset_timeout == 0) {
+ dev_crit(ksp->dev,
+ "Timeout waiting for DMA engines to reset\n");
+ /* And blithely carry on */
+ }
+
+ /* Definitely wait long enough before attempting to program
+ * the engines
+ */
+ msleep(10);
+
+ /* RX: unicast and broadcast */
+ ks8695_writereg(ksp, KS8695_DRXC, DRXC_RU | DRXC_RB);
+ /* TX: pad and add CRC */
+ ks8695_writereg(ksp, KS8695_DTXC, DTXC_TEP | DTXC_TAC);
+}
+
+/**
+ * ks8695_shutdown - Shut down a KS8695 ethernet interface
+ * @ksp: The interface to shut down
+ *
+ * This disables packet RX/TX, cleans up IRQs, drains the rings,
+ * and basically places the interface into a clean shutdown
+ * state.
+ */
+static void
+ks8695_shutdown(struct ks8695_priv *ksp)
+{
+ u32 ctrl;
+ int buff_n;
+
+ /* Disable packet transmission */
+ ctrl = ks8695_readreg(ksp, KS8695_DTXC);
+ ks8695_writereg(ksp, KS8695_DTXC, ctrl & ~DTXC_TE);
+
+ /* Disable packet reception */
+ ctrl = ks8695_readreg(ksp, KS8695_DRXC);
+ ks8695_writereg(ksp, KS8695_DRXC, ctrl & ~DRXC_RE);
+
+ /* Release the IRQs */
+ free_irq(ksp->rx_irq, ksp->ndev);
+ free_irq(ksp->tx_irq, ksp->ndev);
+ if (ksp->link_irq != -1)
+ free_irq(ksp->link_irq, ksp->ndev);
+
+ /* Throw away any pending TX packets */
+ for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) {
+ if (ksp->tx_buffers[buff_n].skb) {
+ /* Remove this SKB from the TX ring */
+ ksp->tx_ring[buff_n].owner = 0;
+ ksp->tx_ring[buff_n].status = 0;
+ ksp->tx_ring[buff_n].data_ptr = 0;
+
+ /* Unmap and bin this SKB */
+ dma_unmap_single(ksp->dev,
+ ksp->tx_buffers[buff_n].dma_ptr,
+ ksp->tx_buffers[buff_n].length,
+ DMA_TO_DEVICE);
+ dev_kfree_skb_irq(ksp->tx_buffers[buff_n].skb);
+ ksp->tx_buffers[buff_n].skb = NULL;
+ }
+ }
+
+ /* Purge the RX buffers */
+ for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) {
+ if (ksp->rx_buffers[buff_n].skb) {
+ /* Remove the SKB from the RX ring */
+ ksp->rx_ring[buff_n].status = 0;
+ ksp->rx_ring[buff_n].data_ptr = 0;
+
+ /* Unmap and bin the SKB */
+ dma_unmap_single(ksp->dev,
+ ksp->rx_buffers[buff_n].dma_ptr,
+ ksp->rx_buffers[buff_n].length,
+ DMA_FROM_DEVICE);
+ dev_kfree_skb_irq(ksp->rx_buffers[buff_n].skb);
+ ksp->rx_buffers[buff_n].skb = NULL;
+ }
+ }
+}
+
+
+/**
+ * ks8695_setup_irq - IRQ setup helper function
+ * @irq: The IRQ number to claim
+ * @irq_name: The name to give the IRQ claimant
+ * @handler: The function to call to handle the IRQ
+ * @ndev: The net_device to pass in as the dev_id argument to the handler
+ *
+ * Return 0 on success.
+ */
+static int
+ks8695_setup_irq(int irq, const char *irq_name,
+ irq_handler_t handler, struct net_device *ndev)
+{
+ int ret;
+
+ ret = request_irq(irq, handler, IRQF_SHARED, irq_name, ndev);
+
+ if (ret) {
+ dev_err(&ndev->dev, "failure to request IRQ %d\n", irq);
+ return ret;
+ }
+
+ return 0;
+}
+
+/**
+ * ks8695_init_net - Initialise a KS8695 ethernet interface
+ * @ksp: The interface to initialise
+ *
+ * This routine fills the RX ring, initialises the DMA engines,
+ * allocates the IRQs and then starts the packet TX and RX
+ * engines.
+ */
+static int
+ks8695_init_net(struct ks8695_priv *ksp)
+{
+ int ret;
+ u32 ctrl;
+
+ ks8695_refill_rxbuffers(ksp);
+
+ /* Initialise the DMA engines */
+ ks8695_writereg(ksp, KS8695_RDLB, (u32) ksp->rx_ring_dma);
+ ks8695_writereg(ksp, KS8695_TDLB, (u32) ksp->tx_ring_dma);
+
+ /* Request the IRQs */
+ ret = ks8695_setup_irq(ksp->rx_irq, ksp->rx_irq_name,
+ ks8695_rx_irq, ksp->ndev);
+ if (ret)
+ return ret;
+ ret = ks8695_setup_irq(ksp->tx_irq, ksp->tx_irq_name,
+ ks8695_tx_irq, ksp->ndev);
+ if (ret)
+ return ret;
+ if (ksp->link_irq != -1) {
+ ret = ks8695_setup_irq(ksp->link_irq, ksp->link_irq_name,
+ ks8695_link_irq, ksp->ndev);
+ if (ret)
+ return ret;
+ }
+
+ /* Set up the ring indices */
+ ksp->next_rx_desc_read = 0;
+ ksp->tx_ring_next_slot = 0;
+ ksp->tx_ring_used = 0;
+
+ /* Bring up transmission */
+ ctrl = ks8695_readreg(ksp, KS8695_DTXC);
+ /* Enable packet transmission */
+ ks8695_writereg(ksp, KS8695_DTXC, ctrl | DTXC_TE);
+
+ /* Bring up the reception */
+ ctrl = ks8695_readreg(ksp, KS8695_DRXC);
+ /* Enable packet reception */
+ ks8695_writereg(ksp, KS8695_DRXC, ctrl | DRXC_RE);
+ /* And start the DMA engine */
+ ks8695_writereg(ksp, KS8695_DRSC, 0);
+
+ /* All done */
+ return 0;
+}
+
+/**
+ * ks8695_release_device - HW resource release for KS8695 e-net
+ * @ksp: The device to be freed
+ *
+ * This unallocates io memory regions, dma-coherent regions etc
+ * which were allocated in ks8695_probe.
+ */
+static void
+ks8695_release_device(struct ks8695_priv *ksp)
+{
+ /* Unmap the registers */
+ iounmap(ksp->io_regs);
+ if (ksp->phyiface_regs)
+ iounmap(ksp->phyiface_regs);
+
+ /* And release the request */
+ release_resource(ksp->regs_req);
+ kfree(ksp->regs_req);
+ if (ksp->phyiface_req) {
+ release_resource(ksp->phyiface_req);
+ kfree(ksp->phyiface_req);
+ }
+
+ /* Free the ring buffers */
+ dma_free_coherent(ksp->dev, RING_DMA_SIZE,
+ ksp->ring_base, ksp->ring_base_dma);
+}
+
+/* Ethtool support */
+
+/**
+ * ks8695_get_msglevel - Get the messages enabled for emission
+ * @ndev: The network device to read from
+ */
+static u32
+ks8695_get_msglevel(struct net_device *ndev)
+{
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+
+ return ksp->msg_enable;
+}
+
+/**
+ * ks8695_set_msglevel - Set the messages enabled for emission
+ * @ndev: The network device to configure
+ * @value: The messages to set for emission
+ */
+static void
+ks8695_set_msglevel(struct net_device *ndev, u32 value)
+{
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+
+ ksp->msg_enable = value;
+}
+
+/**
+ * ks8695_get_settings - Get device-specific settings.
+ * @ndev: The network device to read settings from
+ * @cmd: The ethtool structure to read into
+ */
+static int
+ks8695_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+{
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ u32 ctrl;
+
+ /* All ports on the KS8695 support these... */
+ cmd->supported = (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+ SUPPORTED_TP | SUPPORTED_MII);
+ cmd->transceiver = XCVR_INTERNAL;
+
+ /* Port specific extras */
+ switch (ksp->dtype) {
+ case KS8695_DTYPE_HPNA:
+ cmd->phy_address = 0;
+ /* not supported for HPNA */
+ cmd->autoneg = AUTONEG_DISABLE;
+
+ /* BUG: Erm, dtype hpna implies no phy regs */
+ /*
+ ctrl = readl(KS8695_MISC_VA + KS8695_HMC);
+ cmd->speed = (ctrl & HMC_HSS) ? SPEED_100 : SPEED_10;
+ cmd->duplex = (ctrl & HMC_HDS) ? DUPLEX_FULL : DUPLEX_HALF;
+ */
+ return -EOPNOTSUPP;
+ case KS8695_DTYPE_WAN:
+ cmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
+ cmd->port = PORT_MII;
+ cmd->supported |= (SUPPORTED_Autoneg | SUPPORTED_Pause);
+ cmd->phy_address = 0;
+
+ ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
+ if ((ctrl & WMC_WAND) == 0) {
+ /* auto-negotiation is enabled */
+ cmd->advertising |= ADVERTISED_Autoneg;
+ if (ctrl & WMC_WANA100F)
+ cmd->advertising |= ADVERTISED_100baseT_Full;
+ if (ctrl & WMC_WANA100H)
+ cmd->advertising |= ADVERTISED_100baseT_Half;
+ if (ctrl & WMC_WANA10F)
+ cmd->advertising |= ADVERTISED_10baseT_Full;
+ if (ctrl & WMC_WANA10H)
+ cmd->advertising |= ADVERTISED_10baseT_Half;
+ if (ctrl & WMC_WANAP)
+ cmd->advertising |= ADVERTISED_Pause;
+ cmd->autoneg = AUTONEG_ENABLE;
+
+ cmd->speed = (ctrl & WMC_WSS) ? SPEED_100 : SPEED_10;
+ cmd->duplex = (ctrl & WMC_WDS) ?
+ DUPLEX_FULL : DUPLEX_HALF;
+ } else {
+ /* auto-negotiation is disabled */
+ cmd->autoneg = AUTONEG_DISABLE;
+
+ cmd->speed = (ctrl & WMC_WANF100) ?
+ SPEED_100 : SPEED_10;
+ cmd->duplex = (ctrl & WMC_WANFF) ?
+ DUPLEX_FULL : DUPLEX_HALF;
+ }
+ break;
+ case KS8695_DTYPE_LAN:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+/**
+ * ks8695_set_settings - Set device-specific settings.
+ * @ndev: The network device to configure
+ * @cmd: The settings to configure
+ */
+static int
+ks8695_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+{
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ u32 ctrl;
+
+ if ((cmd->speed != SPEED_10) && (cmd->speed != SPEED_100))
+ return -EINVAL;
+ if ((cmd->duplex != DUPLEX_HALF) && (cmd->duplex != DUPLEX_FULL))
+ return -EINVAL;
+ if (cmd->port != PORT_MII)
+ return -EINVAL;
+ if (cmd->transceiver != XCVR_INTERNAL)
+ return -EINVAL;
+ if ((cmd->autoneg != AUTONEG_DISABLE) &&
+ (cmd->autoneg != AUTONEG_ENABLE))
+ return -EINVAL;
+
+ if (cmd->autoneg == AUTONEG_ENABLE) {
+ if ((cmd->advertising & (ADVERTISED_10baseT_Half |
+ ADVERTISED_10baseT_Full |
+ ADVERTISED_100baseT_Half |
+ ADVERTISED_100baseT_Full)) == 0)
+ return -EINVAL;
+
+ switch (ksp->dtype) {
+ case KS8695_DTYPE_HPNA:
+ /* HPNA does not support auto-negotiation. */
+ return -EINVAL;
+ case KS8695_DTYPE_WAN:
+ ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
+
+ ctrl &= ~(WMC_WAND | WMC_WANA100F | WMC_WANA100H |
+ WMC_WANA10F | WMC_WANA10H);
+ if (cmd->advertising & ADVERTISED_100baseT_Full)
+ ctrl |= WMC_WANA100F;
+ if (cmd->advertising & ADVERTISED_100baseT_Half)
+ ctrl |= WMC_WANA100H;
+ if (cmd->advertising & ADVERTISED_10baseT_Full)
+ ctrl |= WMC_WANA10F;
+ if (cmd->advertising & ADVERTISED_10baseT_Half)
+ ctrl |= WMC_WANA10H;
+
+ /* force a re-negotiation */
+ ctrl |= WMC_WANR;
+ writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
+ break;
+ case KS8695_DTYPE_LAN:
+ return -EOPNOTSUPP;
+ }
+
+ } else {
+ switch (ksp->dtype) {
+ case KS8695_DTYPE_HPNA:
+ /* BUG: dtype_hpna implies no phy registers */
+ /*
+ ctrl = __raw_readl(KS8695_MISC_VA + KS8695_HMC);
+
+ ctrl &= ~(HMC_HSS | HMC_HDS);
+ if (cmd->speed == SPEED_100)
+ ctrl |= HMC_HSS;
+ if (cmd->duplex == DUPLEX_FULL)
+ ctrl |= HMC_HDS;
+
+ __raw_writel(ctrl, KS8695_MISC_VA + KS8695_HMC);
+ */
+ return -EOPNOTSUPP;
+ case KS8695_DTYPE_WAN:
+ ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
+
+ /* disable auto-negotiation */
+ ctrl |= WMC_WAND;
+ ctrl &= ~(WMC_WANF100 | WMC_WANFF);
+
+ if (cmd->speed == SPEED_100)
+ ctrl |= WMC_WANF100;
+ if (cmd->duplex == DUPLEX_FULL)
+ ctrl |= WMC_WANFF;
+
+ writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
+ break;
+ case KS8695_DTYPE_LAN:
+ return -EOPNOTSUPP;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * ks8695_nwayreset - Restart the autonegotiation on the port.
+ * @ndev: The network device to restart autoneotiation on
+ */
+static int
+ks8695_nwayreset(struct net_device *ndev)
+{
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ u32 ctrl;
+
+ switch (ksp->dtype) {
+ case KS8695_DTYPE_HPNA:
+ /* No phy means no autonegotiation on hpna */
+ return -EINVAL;
+ case KS8695_DTYPE_WAN:
+ ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
+
+ if ((ctrl & WMC_WAND) == 0)
+ writel(ctrl | WMC_WANR,
+ ksp->phyiface_regs + KS8695_WMC);
+ else
+ /* auto-negotiation not enabled */
+ return -EINVAL;
+ break;
+ case KS8695_DTYPE_LAN:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+/**
+ * ks8695_get_link - Retrieve link status of network interface
+ * @ndev: The network interface to retrive the link status of.
+ */
+static u32
+ks8695_get_link(struct net_device *ndev)
+{
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ u32 ctrl;
+
+ switch (ksp->dtype) {
+ case KS8695_DTYPE_HPNA:
+ /* HPNA always has link */
+ return 1;
+ case KS8695_DTYPE_WAN:
+ /* WAN we can read the PHY for */
+ ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
+ return ctrl & WMC_WLS;
+ case KS8695_DTYPE_LAN:
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+/**
+ * ks8695_get_pause - Retrieve network pause/flow-control advertising
+ * @ndev: The device to retrieve settings from
+ * @param: The structure to fill out with the information
+ */
+static void
+ks8695_get_pause(struct net_device *ndev, struct ethtool_pauseparam *param)
+{
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ u32 ctrl;
+
+ switch (ksp->dtype) {
+ case KS8695_DTYPE_HPNA:
+ /* No phy link on hpna to configure */
+ return;
+ case KS8695_DTYPE_WAN:
+ ctrl = readl(ksp->phyiface_regs + KS8695_WMC);
+
+ /* advertise Pause */
+ param->autoneg = (ctrl & WMC_WANAP);
+
+ /* current Rx Flow-control */
+ ctrl = ks8695_readreg(ksp, KS8695_DRXC);
+ param->rx_pause = (ctrl & DRXC_RFCE);
+
+ /* current Tx Flow-control */
+ ctrl = ks8695_readreg(ksp, KS8695_DTXC);
+ param->tx_pause = (ctrl & DTXC_TFCE);
+ break;
+ case KS8695_DTYPE_LAN:
+ /* The LAN's "phy" is a direct-attached switch */
+ return;
+ }
+}
+
+/**
+ * ks8695_set_pause - Configure pause/flow-control
+ * @ndev: The device to configure
+ * @param: The pause parameters to set
+ *
+ * TODO: Implement this
+ */
+static int
+ks8695_set_pause(struct net_device *ndev, struct ethtool_pauseparam *param)
+{
+ return -EOPNOTSUPP;
+}
+
+/**
+ * ks8695_get_drvinfo - Retrieve driver information
+ * @ndev: The network device to retrieve info about
+ * @info: The info structure to fill out.
+ */
+static void
+ks8695_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info)
+{
+ strlcpy(info->driver, MODULENAME, sizeof(info->driver));
+ strlcpy(info->version, MODULEVERSION, sizeof(info->version));
+ strlcpy(info->bus_info, ndev->dev.parent->bus_id,
+ sizeof(info->bus_info));
+}
+
+static struct ethtool_ops ks8695_ethtool_ops = {
+ .get_msglevel = ks8695_get_msglevel,
+ .set_msglevel = ks8695_set_msglevel,
+ .get_settings = ks8695_get_settings,
+ .set_settings = ks8695_set_settings,
+ .nway_reset = ks8695_nwayreset,
+ .get_link = ks8695_get_link,
+ .get_pauseparam = ks8695_get_pause,
+ .set_pauseparam = ks8695_set_pause,
+ .get_drvinfo = ks8695_get_drvinfo,
+};
+
+/* Network device interface functions */
+
+/**
+ * ks8695_set_mac - Update MAC in net dev and HW
+ * @ndev: The network device to update
+ * @addr: The new MAC address to set
+ */
+static int
+ks8695_set_mac(struct net_device *ndev, void *addr)
+{
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ struct sockaddr *address = addr;
+
+ if (!is_valid_ether_addr(address->sa_data))
+ return -EADDRNOTAVAIL;
+
+ memcpy(ndev->dev_addr, address->sa_data, ndev->addr_len);
+
+ ks8695_update_mac(ksp);
+
+ dev_dbg(ksp->dev, "%s: Updated MAC address to %pM\n",
+ ndev->name, ndev->dev_addr);
+
+ return 0;
+}
+
+/**
+ * ks8695_set_multicast - Set up the multicast behaviour of the interface
+ * @ndev: The net_device to configure
+ *
+ * This routine, called by the net layer, configures promiscuity
+ * and multicast reception behaviour for the interface.
+ */
+static void
+ks8695_set_multicast(struct net_device *ndev)
+{
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ u32 ctrl;
+
+ ctrl = ks8695_readreg(ksp, KS8695_DRXC);
+
+ if (ndev->flags & IFF_PROMISC) {
+ /* enable promiscuous mode */
+ ctrl |= DRXC_RA;
+ } else if (ndev->flags & ~IFF_PROMISC) {
+ /* disable promiscuous mode */
+ ctrl &= ~DRXC_RA;
+ }
+
+ if (ndev->flags & IFF_ALLMULTI) {
+ /* enable all multicast mode */
+ ctrl |= DRXC_RM;
+ } else if (ndev->mc_count > KS8695_NR_ADDRESSES) {
+ /* more specific multicast addresses than can be
+ * handled in hardware
+ */
+ ctrl |= DRXC_RM;
+ } else {
+ /* enable specific multicasts */
+ ctrl &= ~DRXC_RM;
+ ks8695_init_partial_multicast(ksp, ndev->mc_list,
+ ndev->mc_count);
+ }
+
+ ks8695_writereg(ksp, KS8695_DRXC, ctrl);
+}
+
+/**
+ * ks8695_timeout - Handle a network tx/rx timeout.
+ * @ndev: The net_device which timed out.
+ *
+ * A network transaction timed out, reset the device.
+ */
+static void
+ks8695_timeout(struct net_device *ndev)
+{
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+
+ netif_stop_queue(ndev);
+ ks8695_shutdown(ksp);
+
+ ks8695_reset(ksp);
+
+ ks8695_update_mac(ksp);
+
+ /* We ignore the return from this since it managed to init
+ * before it probably will be okay to init again.
+ */
+ ks8695_init_net(ksp);
+
+ /* Reconfigure promiscuity etc */
+ ks8695_set_multicast(ndev);
+
+ /* And start the TX queue once more */
+ netif_start_queue(ndev);
+}
+
+/**
+ * ks8695_start_xmit - Start a packet transmission
+ * @skb: The packet to transmit
+ * @ndev: The network device to send the packet on
+ *
+ * This routine, called by the net layer, takes ownership of the
+ * sk_buff and adds it to the TX ring. It then kicks the TX DMA
+ * engine to ensure transmission begins.
+ */
+static int
+ks8695_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ int buff_n;
+ dma_addr_t dmap;
+
+ spin_lock_irq(&ksp->txq_lock);
+
+ if (ksp->tx_ring_used == MAX_TX_DESC) {
+ /* Somehow we got entered when we have no room */
+ spin_unlock_irq(&ksp->txq_lock);
+ return NETDEV_TX_BUSY;
+ }
+
+ buff_n = ksp->tx_ring_next_slot;
+
+ BUG_ON(ksp->tx_buffers[buff_n].skb);
+
+ dmap = dma_map_single(ksp->dev, skb->data, skb->len, DMA_TO_DEVICE);
+ if (unlikely(dma_mapping_error(ksp->dev, dmap))) {
+ /* Failed to DMA map this SKB, give it back for now */
+ spin_unlock_irq(&ksp->txq_lock);
+ dev_dbg(ksp->dev, "%s: Could not map DMA memory for "\
+ "transmission, trying later\n", ndev->name);
+ return NETDEV_TX_BUSY;
+ }
+
+ ksp->tx_buffers[buff_n].dma_ptr = dmap;
+ /* Mapped okay, store the buffer pointer and length for later */
+ ksp->tx_buffers[buff_n].skb = skb;
+ ksp->tx_buffers[buff_n].length = skb->len;
+
+ /* Fill out the TX descriptor */
+ ksp->tx_ring[buff_n].data_ptr =
+ cpu_to_le32(ksp->tx_buffers[buff_n].dma_ptr);
+ ksp->tx_ring[buff_n].status =
+ cpu_to_le32(TDES_IC | TDES_FS | TDES_LS |
+ (skb->len & TDES_TBS));
+
+ wmb();
+
+ /* Hand it over to the hardware */
+ ksp->tx_ring[buff_n].owner = cpu_to_le32(TDES_OWN);
+
+ if (++ksp->tx_ring_used == MAX_TX_DESC)
+ netif_stop_queue(ndev);
+
+ ndev->trans_start = jiffies;
+
+ /* Kick the TX DMA in case it decided to go IDLE */
+ ks8695_writereg(ksp, KS8695_DTSC, 0);
+
+ /* And update the next ring slot */
+ ksp->tx_ring_next_slot = (buff_n + 1) & MAX_TX_DESC_MASK;
+
+ spin_unlock_irq(&ksp->txq_lock);
+ return NETDEV_TX_OK;
+}
+
+/**
+ * ks8695_stop - Stop (shutdown) a KS8695 ethernet interface
+ * @ndev: The net_device to stop
+ *
+ * This disables the TX queue and cleans up a KS8695 ethernet
+ * device.
+ */
+static int
+ks8695_stop(struct net_device *ndev)
+{
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+
+ netif_stop_queue(ndev);
+ netif_carrier_off(ndev);
+
+ ks8695_shutdown(ksp);
+
+ return 0;
+}
+
+/**
+ * ks8695_open - Open (bring up) a KS8695 ethernet interface
+ * @ndev: The net_device to open
+ *
+ * This resets, configures the MAC, initialises the RX ring and
+ * DMA engines and starts the TX queue for a KS8695 ethernet
+ * device.
+ */
+static int
+ks8695_open(struct net_device *ndev)
+{
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+ int ret;
+
+ if (!is_valid_ether_addr(ndev->dev_addr))
+ return -EADDRNOTAVAIL;
+
+ ks8695_reset(ksp);
+
+ ks8695_update_mac(ksp);
+
+ ret = ks8695_init_net(ksp);
+ if (ret) {
+ ks8695_shutdown(ksp);
+ return ret;
+ }
+
+ netif_start_queue(ndev);
+
+ return 0;
+}
+
+/* Platform device driver */
+
+/**
+ * ks8695_init_switch - Init LAN switch to known good defaults.
+ * @ksp: The device to initialise
+ *
+ * This initialises the LAN switch in the KS8695 to a known-good
+ * set of defaults.
+ */
+static void __devinit
+ks8695_init_switch(struct ks8695_priv *ksp)
+{
+ u32 ctrl;
+
+ /* Default value for SEC0 according to datasheet */
+ ctrl = 0x40819e00;
+
+ /* LED0 = Speed LED1 = Link/Activity */
+ ctrl &= ~(SEC0_LLED1S | SEC0_LLED0S);
+ ctrl |= (LLED0S_LINK | LLED1S_LINK_ACTIVITY);
+
+ /* Enable Switch */
+ ctrl |= SEC0_ENABLE;
+
+ writel(ctrl, ksp->phyiface_regs + KS8695_SEC0);
+
+ /* Defaults for SEC1 */
+ writel(0x9400100, ksp->phyiface_regs + KS8695_SEC1);
+}
+
+/**
+ * ks8695_init_wan_phy - Initialise the WAN PHY to sensible defaults
+ * @ksp: The device to initialise
+ *
+ * This initialises a KS8695's WAN phy to sensible values for
+ * autonegotiation etc.
+ */
+static void __devinit
+ks8695_init_wan_phy(struct ks8695_priv *ksp)
+{
+ u32 ctrl;
+
+ /* Support auto-negotiation */
+ ctrl = (WMC_WANAP | WMC_WANA100F | WMC_WANA100H |
+ WMC_WANA10F | WMC_WANA10H);
+
+ /* LED0 = Activity , LED1 = Link */
+ ctrl |= (WLED0S_ACTIVITY | WLED1S_LINK);
+
+ /* Restart Auto-negotiation */
+ ctrl |= WMC_WANR;
+
+ writel(ctrl, ksp->phyiface_regs + KS8695_WMC);
+
+ writel(0, ksp->phyiface_regs + KS8695_WPPM);
+ writel(0, ksp->phyiface_regs + KS8695_PPS);
+}
+
+static const struct net_device_ops ks8695_netdev_ops = {
+ .ndo_open = ks8695_open,
+ .ndo_stop = ks8695_stop,
+ .ndo_start_xmit = ks8695_start_xmit,
+ .ndo_tx_timeout = ks8695_timeout,
+ .ndo_set_mac_address = ks8695_set_mac,
+ .ndo_set_multicast_list = ks8695_set_multicast,
+};
+
+/**
+ * ks8695_probe - Probe and initialise a KS8695 ethernet interface
+ * @pdev: The platform device to probe
+ *
+ * Initialise a KS8695 ethernet device from platform data.
+ *
+ * This driver requires at least one IORESOURCE_MEM for the
+ * registers and two IORESOURCE_IRQ for the RX and TX IRQs
+ * respectively. It can optionally take an additional
+ * IORESOURCE_MEM for the switch or phy in the case of the lan or
+ * wan ports, and an IORESOURCE_IRQ for the link IRQ for the wan
+ * port.
+ */
+static int __devinit
+ks8695_probe(struct platform_device *pdev)
+{
+ struct ks8695_priv *ksp;
+ struct net_device *ndev;
+ struct resource *regs_res, *phyiface_res;
+ struct resource *rxirq_res, *txirq_res, *linkirq_res;
+ int ret = 0;
+ int buff_n;
+ u32 machigh, maclow;
+
+ /* Initialise a net_device */
+ ndev = alloc_etherdev(sizeof(struct ks8695_priv));
+ if (!ndev) {
+ dev_err(&pdev->dev, "could not allocate device.\n");
+ return -ENOMEM;
+ }
+
+ SET_NETDEV_DEV(ndev, &pdev->dev);
+
+ dev_dbg(&pdev->dev, "ks8695_probe() called\n");
+
+ /* Configure our private structure a little */
+ ksp = netdev_priv(ndev);
+ memset(ksp, 0, sizeof(struct ks8695_priv));
+
+ ksp->dev = &pdev->dev;
+ ksp->ndev = ndev;
+ ksp->msg_enable = NETIF_MSG_LINK;
+
+ /* Retrieve resources */
+ regs_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ phyiface_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+
+ rxirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ txirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
+ linkirq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 2);
+
+ if (!(regs_res && rxirq_res && txirq_res)) {
+ dev_err(ksp->dev, "insufficient resources\n");
+ ret = -ENOENT;
+ goto failure;
+ }
+
+ ksp->regs_req = request_mem_region(regs_res->start,
+ resource_size(regs_res),
+ pdev->name);
+
+ if (!ksp->regs_req) {
+ dev_err(ksp->dev, "cannot claim register space\n");
+ ret = -EIO;
+ goto failure;
+ }
+
+ ksp->io_regs = ioremap(regs_res->start, resource_size(regs_res));
+
+ if (!ksp->io_regs) {
+ dev_err(ksp->dev, "failed to ioremap registers\n");
+ ret = -EINVAL;
+ goto failure;
+ }
+
+ if (phyiface_res) {
+ ksp->phyiface_req =
+ request_mem_region(phyiface_res->start,
+ resource_size(phyiface_res),
+ phyiface_res->name);
+
+ if (!ksp->phyiface_req) {
+ dev_err(ksp->dev,
+ "cannot claim switch register space\n");
+ ret = -EIO;
+ goto failure;
+ }
+
+ ksp->phyiface_regs = ioremap(phyiface_res->start,
+ resource_size(phyiface_res));
+
+ if (!ksp->phyiface_regs) {
+ dev_err(ksp->dev,
+ "failed to ioremap switch registers\n");
+ ret = -EINVAL;
+ goto failure;
+ }
+ }
+
+ ksp->rx_irq = rxirq_res->start;
+ ksp->rx_irq_name = rxirq_res->name ? rxirq_res->name : "Ethernet RX";
+ ksp->tx_irq = txirq_res->start;
+ ksp->tx_irq_name = txirq_res->name ? txirq_res->name : "Ethernet TX";
+ ksp->link_irq = (linkirq_res ? linkirq_res->start : -1);
+ ksp->link_irq_name = (linkirq_res && linkirq_res->name) ?
+ linkirq_res->name : "Ethernet Link";
+
+ /* driver system setup */
+ ndev->netdev_ops = &ks8695_netdev_ops;
+ SET_ETHTOOL_OPS(ndev, &ks8695_ethtool_ops);
+ ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
+
+ /* Retrieve the default MAC addr from the chip. */
+ /* The bootloader should have left it in there for us. */
+
+ machigh = ks8695_readreg(ksp, KS8695_MAH);
+ maclow = ks8695_readreg(ksp, KS8695_MAL);
+
+ ndev->dev_addr[0] = (machigh >> 8) & 0xFF;
+ ndev->dev_addr[1] = machigh & 0xFF;
+ ndev->dev_addr[2] = (maclow >> 24) & 0xFF;
+ ndev->dev_addr[3] = (maclow >> 16) & 0xFF;
+ ndev->dev_addr[4] = (maclow >> 8) & 0xFF;
+ ndev->dev_addr[5] = maclow & 0xFF;
+
+ if (!is_valid_ether_addr(ndev->dev_addr))
+ dev_warn(ksp->dev, "%s: Invalid ethernet MAC address. Please "
+ "set using ifconfig\n", ndev->name);
+
+ /* In order to be efficient memory-wise, we allocate both
+ * rings in one go.
+ */
+ ksp->ring_base = dma_alloc_coherent(&pdev->dev, RING_DMA_SIZE,
+ &ksp->ring_base_dma, GFP_KERNEL);
+ if (!ksp->ring_base) {
+ ret = -ENOMEM;
+ goto failure;
+ }
+
+ /* Specify the TX DMA ring buffer */
+ ksp->tx_ring = ksp->ring_base;
+ ksp->tx_ring_dma = ksp->ring_base_dma;
+
+ /* And initialise the queue's lock */
+ spin_lock_init(&ksp->txq_lock);
+
+ /* Specify the RX DMA ring buffer */
+ ksp->rx_ring = ksp->ring_base + TX_RING_DMA_SIZE;
+ ksp->rx_ring_dma = ksp->ring_base_dma + TX_RING_DMA_SIZE;
+
+ /* Zero the descriptor rings */
+ memset(ksp->tx_ring, 0, TX_RING_DMA_SIZE);
+ memset(ksp->rx_ring, 0, RX_RING_DMA_SIZE);
+
+ /* Build the rings */
+ for (buff_n = 0; buff_n < MAX_TX_DESC; ++buff_n) {
+ ksp->tx_ring[buff_n].next_desc =
+ cpu_to_le32(ksp->tx_ring_dma +
+ (sizeof(struct tx_ring_desc) *
+ ((buff_n + 1) & MAX_TX_DESC_MASK)));
+ }
+
+ for (buff_n = 0; buff_n < MAX_RX_DESC; ++buff_n) {
+ ksp->rx_ring[buff_n].next_desc =
+ cpu_to_le32(ksp->rx_ring_dma +
+ (sizeof(struct rx_ring_desc) *
+ ((buff_n + 1) & MAX_RX_DESC_MASK)));
+ }
+
+ /* Initialise the port (physically) */
+ if (ksp->phyiface_regs && ksp->link_irq == -1) {
+ ks8695_init_switch(ksp);
+ ksp->dtype = KS8695_DTYPE_LAN;
+ } else if (ksp->phyiface_regs && ksp->link_irq != -1) {
+ ks8695_init_wan_phy(ksp);
+ ksp->dtype = KS8695_DTYPE_WAN;
+ } else {
+ /* No initialisation since HPNA does not have a PHY */
+ ksp->dtype = KS8695_DTYPE_HPNA;
+ }
+
+ /* And bring up the net_device with the net core */
+ platform_set_drvdata(pdev, ndev);
+ ret = register_netdev(ndev);
+
+ if (ret == 0) {
+ dev_info(ksp->dev, "ks8695 ethernet (%s) MAC: %pM\n",
+ ks8695_port_type(ksp), ndev->dev_addr);
+ } else {
+ /* Report the failure to register the net_device */
+ dev_err(ksp->dev, "ks8695net: failed to register netdev.\n");
+ goto failure;
+ }
+
+ /* All is well */
+ return 0;
+
+ /* Error exit path */
+failure:
+ ks8695_release_device(ksp);
+ free_netdev(ndev);
+
+ return ret;
+}
+
+/**
+ * ks8695_drv_suspend - Suspend a KS8695 ethernet platform device.
+ * @pdev: The device to suspend
+ * @state: The suspend state
+ *
+ * This routine detaches and shuts down a KS8695 ethernet device.
+ */
+static int
+ks8695_drv_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+
+ ksp->in_suspend = 1;
+
+ if (netif_running(ndev)) {
+ netif_device_detach(ndev);
+ ks8695_shutdown(ksp);
+ }
+
+ return 0;
+}
+
+/**
+ * ks8695_drv_resume - Resume a KS8695 ethernet platform device.
+ * @pdev: The device to resume
+ *
+ * This routine re-initialises and re-attaches a KS8695 ethernet
+ * device.
+ */
+static int
+ks8695_drv_resume(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+
+ if (netif_running(ndev)) {
+ ks8695_reset(ksp);
+ ks8695_init_net(ksp);
+ ks8695_set_multicast(ndev);
+ netif_device_attach(ndev);
+ }
+
+ ksp->in_suspend = 0;
+
+ return 0;
+}
+
+/**
+ * ks8695_drv_remove - Remove a KS8695 net device on driver unload.
+ * @pdev: The platform device to remove
+ *
+ * This unregisters and releases a KS8695 ethernet device.
+ */
+static int __devexit
+ks8695_drv_remove(struct platform_device *pdev)
+{
+ struct net_device *ndev = platform_get_drvdata(pdev);
+ struct ks8695_priv *ksp = netdev_priv(ndev);
+
+ platform_set_drvdata(pdev, NULL);
+
+ unregister_netdev(ndev);
+ ks8695_release_device(ksp);
+ free_netdev(ndev);
+
+ dev_dbg(&pdev->dev, "released and freed device\n");
+ return 0;
+}
+
+static struct platform_driver ks8695_driver = {
+ .driver = {
+ .name = MODULENAME,
+ .owner = THIS_MODULE,
+ },
+ .probe = ks8695_probe,
+ .remove = __devexit_p(ks8695_drv_remove),
+ .suspend = ks8695_drv_suspend,
+ .resume = ks8695_drv_resume,
+};
+
+/* Module interface */
+
+static int __init
+ks8695_init(void)
+{
+ printk(KERN_INFO "%s Ethernet driver, V%s\n",
+ MODULENAME, MODULEVERSION);
+
+ return platform_driver_register(&ks8695_driver);
+}
+
+static void __exit
+ks8695_cleanup(void)
+{
+ platform_driver_unregister(&ks8695_driver);
+}
+
+module_init(ks8695_init);
+module_exit(ks8695_cleanup);
+
+MODULE_AUTHOR("Simtec Electronics")
+MODULE_DESCRIPTION("Micrel KS8695 (Centaur) Ethernet driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" MODULENAME);
+
+module_param(watchdog, int, 0400);
+MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
diff --git a/drivers/net/arm/ks8695net.h b/drivers/net/arm/ks8695net.h
new file mode 100644
index 000000000000..80eff6ea5163
--- /dev/null
+++ b/drivers/net/arm/ks8695net.h
@@ -0,0 +1,107 @@
+/*
+ * Micrel KS8695 (Centaur) Ethernet.
+ *
+ * Copyright 2008 Simtec Electronics
+ * Daniel Silverstone <dsilvers@simtec.co.uk>
+ * Vincent Sanders <vince@simtec.co.uk>
+ */
+
+#ifndef KS8695NET_H
+#define KS8695NET_H
+
+/* Receive descriptor flags */
+#define RDES_OWN (1 << 31) /* Ownership */
+#define RDES_FS (1 << 30) /* First Descriptor */
+#define RDES_LS (1 << 29) /* Last Descriptor */
+#define RDES_IPE (1 << 28) /* IP Checksum error */
+#define RDES_TCPE (1 << 27) /* TCP Checksum error */
+#define RDES_UDPE (1 << 26) /* UDP Checksum error */
+#define RDES_ES (1 << 25) /* Error summary */
+#define RDES_MF (1 << 24) /* Multicast Frame */
+#define RDES_RE (1 << 19) /* MII Error reported */
+#define RDES_TL (1 << 18) /* Frame too Long */
+#define RDES_RF (1 << 17) /* Runt Frame */
+#define RDES_CE (1 << 16) /* CRC error */
+#define RDES_FT (1 << 15) /* Frame Type */
+#define RDES_FLEN (0x7ff) /* Frame Length */
+
+#define RDES_RER (1 << 25) /* Receive End of Ring */
+#define RDES_RBS (0x7ff) /* Receive Buffer Size */
+
+/* Transmit descriptor flags */
+
+#define TDES_OWN (1 << 31) /* Ownership */
+
+#define TDES_IC (1 << 31) /* Interrupt on Completion */
+#define TDES_FS (1 << 30) /* First Segment */
+#define TDES_LS (1 << 29) /* Last Segment */
+#define TDES_IPCKG (1 << 28) /* IP Checksum generate */
+#define TDES_TCPCKG (1 << 27) /* TCP Checksum generate */
+#define TDES_UDPCKG (1 << 26) /* UDP Checksum generate */
+#define TDES_TER (1 << 25) /* Transmit End of Ring */
+#define TDES_TBS (0x7ff) /* Transmit Buffer Size */
+
+/*
+ * Network controller register offsets
+ */
+#define KS8695_DTXC (0x00) /* DMA Transmit Control */
+#define KS8695_DRXC (0x04) /* DMA Receive Control */
+#define KS8695_DTSC (0x08) /* DMA Transmit Start Command */
+#define KS8695_DRSC (0x0c) /* DMA Receive Start Command */
+#define KS8695_TDLB (0x10) /* Transmit Descriptor List
+ * Base Address
+ */
+#define KS8695_RDLB (0x14) /* Receive Descriptor List
+ * Base Address
+ */
+#define KS8695_MAL (0x18) /* MAC Station Address Low */
+#define KS8695_MAH (0x1c) /* MAC Station Address High */
+#define KS8695_AAL_(n) (0x80 + ((n)*8)) /* MAC Additional
+ * Station Address
+ * (0..15) Low
+ */
+#define KS8695_AAH_(n) (0x84 + ((n)*8)) /* MAC Additional
+ * Station Address
+ * (0..15) High
+ */
+
+
+/* DMA Transmit Control Register */
+#define DTXC_TRST (1 << 31) /* Soft Reset */
+#define DTXC_TBS (0x3f << 24) /* Transmit Burst Size */
+#define DTXC_TUCG (1 << 18) /* Transmit UDP
+ * Checksum Generate
+ */
+#define DTXC_TTCG (1 << 17) /* Transmit TCP
+ * Checksum Generate
+ */
+#define DTXC_TICG (1 << 16) /* Transmit IP
+ * Checksum Generate
+ */
+#define DTXC_TFCE (1 << 9) /* Transmit Flow
+ * Control Enable
+ */
+#define DTXC_TLB (1 << 8) /* Loopback mode */
+#define DTXC_TEP (1 << 2) /* Transmit Enable Padding */
+#define DTXC_TAC (1 << 1) /* Transmit Add CRC */
+#define DTXC_TE (1 << 0) /* TX Enable */
+
+/* DMA Receive Control Register */
+#define DRXC_RBS (0x3f << 24) /* Receive Burst Size */
+#define DRXC_RUCC (1 << 18) /* Receive UDP Checksum check */
+#define DRXC_RTCG (1 << 17) /* Receive TCP Checksum check */
+#define DRXC_RICG (1 << 16) /* Receive IP Checksum check */
+#define DRXC_RFCE (1 << 9) /* Receive Flow Control
+ * Enable
+ */
+#define DRXC_RB (1 << 6) /* Receive Broadcast */
+#define DRXC_RM (1 << 5) /* Receive Multicast */
+#define DRXC_RU (1 << 4) /* Receive Unicast */
+#define DRXC_RERR (1 << 3) /* Receive Error Frame */
+#define DRXC_RA (1 << 2) /* Receive All */
+#define DRXC_RE (1 << 0) /* RX Enable */
+
+/* Additional Station Address High */
+#define AAH_E (1 << 31) /* Address Enabled */
+
+#endif /* KS8695NET_H */
diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c
index 7e874d485d24..72ea6e378f8d 100644
--- a/drivers/net/at1700.c
+++ b/drivers/net/at1700.c
@@ -265,7 +265,6 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr)
unsigned int i, irq, is_fmv18x = 0, is_at1700 = 0;
int slot, ret = -ENODEV;
struct net_local *lp = netdev_priv(dev);
- DECLARE_MAC_BUF(mac);
if (!request_region(ioaddr, AT1700_IO_EXTENT, DRV_NAME))
return -EBUSY;
@@ -397,7 +396,7 @@ found:
dev->dev_addr[i] = val;
}
}
- printk("%s", print_mac(mac, dev->dev_addr));
+ printk("%pM", dev->dev_addr);
/* The EEPROM word 12 bit 0x0400 means use regular 100 ohm 10baseT signals,
rather than 150 ohm shielded twisted pair compensation.
@@ -768,7 +767,6 @@ net_rx(struct net_device *dev)
insw(ioaddr + DATAPORT, skb_put(skb,pkt_len), (pkt_len + 1) >> 1);
skb->protocol=eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
}
@@ -901,15 +899,3 @@ module_init(at1700_module_init);
module_exit(at1700_module_exit);
#endif /* MODULE */
MODULE_LICENSE("GPL");
-
-
-/*
- * Local variables:
- * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c at1700.c"
- * alt-compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c at1700.c"
- * tab-width: 4
- * c-basic-offset: 4
- * c-indent-level: 4
- * End:
- */
-
diff --git a/drivers/net/atarilance.c b/drivers/net/atarilance.c
index 0860cc280b01..2d81f6afcb58 100644
--- a/drivers/net/atarilance.c
+++ b/drivers/net/atarilance.c
@@ -466,7 +466,6 @@ static unsigned long __init lance_probe1( struct net_device *dev,
int i;
static int did_version;
unsigned short save1, save2;
- DECLARE_MAC_BUF(mac);
PROBE_PRINT(( "Probing for Lance card at mem %#lx io %#lx\n",
(long)memaddr, (long)ioaddr ));
@@ -521,7 +520,7 @@ static unsigned long __init lance_probe1( struct net_device *dev,
return( 0 );
probe_ok:
- lp = (struct lance_private *)dev->priv;
+ lp = netdev_priv(dev);
MEM = (struct lance_memory *)memaddr;
IO = lp->iobase = (struct lance_ioreg *)ioaddr;
dev->base_addr = (unsigned long)ioaddr; /* informational only */
@@ -595,7 +594,7 @@ static unsigned long __init lance_probe1( struct net_device *dev,
i = IO->mem;
break;
}
- printk("%s\n", print_mac(mac, dev->dev_addr));
+ printk("%pM\n", dev->dev_addr);
if (lp->cardtype == OLD_RIEBL) {
printk( "%s: Warning: This is a default ethernet address!\n",
dev->name );
@@ -640,8 +639,8 @@ static unsigned long __init lance_probe1( struct net_device *dev,
static int lance_open( struct net_device *dev )
-
-{ struct lance_private *lp = (struct lance_private *)dev->priv;
+{
+ struct lance_private *lp = netdev_priv(dev);
struct lance_ioreg *IO = lp->iobase;
int i;
@@ -681,8 +680,8 @@ static int lance_open( struct net_device *dev )
/* Initialize the LANCE Rx and Tx rings. */
static void lance_init_ring( struct net_device *dev )
-
-{ struct lance_private *lp = (struct lance_private *)dev->priv;
+{
+ struct lance_private *lp = netdev_priv(dev);
int i;
unsigned offset;
@@ -730,7 +729,7 @@ static void lance_init_ring( struct net_device *dev )
static void lance_tx_timeout (struct net_device *dev)
{
- struct lance_private *lp = (struct lance_private *) dev->priv;
+ struct lance_private *lp = netdev_priv(dev);
struct lance_ioreg *IO = lp->iobase;
AREG = CSR0;
@@ -772,14 +771,12 @@ static void lance_tx_timeout (struct net_device *dev)
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
-
-{ struct lance_private *lp = (struct lance_private *)dev->priv;
+{
+ struct lance_private *lp = netdev_priv(dev);
struct lance_ioreg *IO = lp->iobase;
int entry, len;
struct lance_tx_head *head;
unsigned long flags;
- DECLARE_MAC_BUF(mac);
- DECLARE_MAC_BUF(mac2);
DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n",
dev->name, DREG ));
@@ -802,12 +799,10 @@ static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
/* Fill in a Tx ring entry */
if (lance_debug >= 3) {
- printk( "%s: TX pkt type 0x%04x from "
- "%s to %s"
+ printk( "%s: TX pkt type 0x%04x from %pM to %pM"
" data at 0x%08x len %d\n",
dev->name, ((u_short *)skb->data)[6],
- print_mac(mac, &skb->data[6]),
- print_mac(mac2, skb->data),
+ &skb->data[6], skb->data,
(int)skb->data, (int)skb->len );
}
@@ -865,7 +860,7 @@ static irqreturn_t lance_interrupt( int irq, void *dev_id )
return IRQ_NONE;
}
- lp = (struct lance_private *)dev->priv;
+ lp = netdev_priv(dev);
IO = lp->iobase;
spin_lock (&lp->devlock);
@@ -965,8 +960,8 @@ static irqreturn_t lance_interrupt( int irq, void *dev_id )
static int lance_rx( struct net_device *dev )
-
-{ struct lance_private *lp = (struct lance_private *)dev->priv;
+{
+ struct lance_private *lp = netdev_priv(dev);
int entry = lp->cur_rx & RX_RING_MOD_MASK;
int i;
@@ -1019,14 +1014,12 @@ static int lance_rx( struct net_device *dev )
if (lance_debug >= 3) {
u_char *data = PKTBUF_ADDR(head);
- DECLARE_MAC_BUF(mac);
- DECLARE_MAC_BUF(mac2);
- printk(KERN_DEBUG "%s: RX pkt type 0x%04x from %s to %s "
+ printk(KERN_DEBUG "%s: RX pkt type 0x%04x from %pM to %pM "
"data %02x %02x %02x %02x %02x %02x %02x %02x "
"len %d\n",
dev->name, ((u_short *)data)[6],
- print_mac(mac, &data[6]), print_mac(mac2, data),
+ &data[6], data,
data[15], data[16], data[17], data[18],
data[19], data[20], data[21], data[22],
pkt_len);
@@ -1037,7 +1030,6 @@ static int lance_rx( struct net_device *dev )
lp->memcpy_f( skb->data, PKTBUF_ADDR(head), pkt_len );
skb->protocol = eth_type_trans( skb, dev );
netif_rx( skb );
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
}
@@ -1057,8 +1049,8 @@ static int lance_rx( struct net_device *dev )
static int lance_close( struct net_device *dev )
-
-{ struct lance_private *lp = (struct lance_private *)dev->priv;
+{
+ struct lance_private *lp = netdev_priv(dev);
struct lance_ioreg *IO = lp->iobase;
netif_stop_queue (dev);
@@ -1084,8 +1076,8 @@ static int lance_close( struct net_device *dev )
*/
static void set_multicast_list( struct net_device *dev )
-
-{ struct lance_private *lp = (struct lance_private *)dev->priv;
+{
+ struct lance_private *lp = netdev_priv(dev);
struct lance_ioreg *IO = lp->iobase;
if (netif_running(dev))
@@ -1126,8 +1118,8 @@ static void set_multicast_list( struct net_device *dev )
/* This is needed for old RieblCards and possible for new RieblCards */
static int lance_set_mac_address( struct net_device *dev, void *addr )
-
-{ struct lance_private *lp = (struct lance_private *)dev->priv;
+{
+ struct lance_private *lp = netdev_priv(dev);
struct sockaddr *saddr = addr;
int i;
diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c
index 9b603528143d..bb9094d4cbc9 100644
--- a/drivers/net/atl1e/atl1e_main.c
+++ b/drivers/net/atl1e/atl1e_main.c
@@ -1326,9 +1326,9 @@ static irqreturn_t atl1e_intr(int irq, void *data)
AT_WRITE_REG(hw, REG_IMR,
IMR_NORMAL_MASK & ~ISR_RX_EVENT);
AT_WRITE_FLUSH(hw);
- if (likely(netif_rx_schedule_prep(netdev,
+ if (likely(netif_rx_schedule_prep(
&adapter->napi)))
- __netif_rx_schedule(netdev, &adapter->napi);
+ __netif_rx_schedule(&adapter->napi);
}
} while (--max_ints > 0);
/* re-enable Interrupt*/
@@ -1460,7 +1460,6 @@ static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que,
netif_receive_skb(skb);
}
- netdev->last_rx = jiffies;
skip_pkt:
/* skip current packet whether it's ok or not. */
rx_page->read_offset +=
@@ -1502,7 +1501,6 @@ static int atl1e_clean(struct napi_struct *napi, int budget)
{
struct atl1e_adapter *adapter =
container_of(napi, struct atl1e_adapter, napi);
- struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
u32 imr_data;
int work_done = 0;
@@ -1516,7 +1514,7 @@ static int atl1e_clean(struct napi_struct *napi, int budget)
/* If no Tx and not enough Rx work done, exit the polling mode */
if (work_done < budget) {
quit_polling:
- netif_rx_complete(netdev, napi);
+ netif_rx_complete(napi);
imr_data = AT_READ_REG(&adapter->hw, REG_IMR);
AT_WRITE_REG(&adapter->hw, REG_IMR, imr_data | ISR_RX_EVENT);
/* test debug */
@@ -2254,26 +2252,33 @@ static void atl1e_shutdown(struct pci_dev *pdev)
atl1e_suspend(pdev, PMSG_SUSPEND);
}
+static const struct net_device_ops atl1e_netdev_ops = {
+ .ndo_open = atl1e_open,
+ .ndo_stop = atl1e_close,
+ .ndo_start_xmit = atl1e_xmit_frame,
+ .ndo_get_stats = atl1e_get_stats,
+ .ndo_set_multicast_list = atl1e_set_multi,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = atl1e_set_mac_addr,
+ .ndo_change_mtu = atl1e_change_mtu,
+ .ndo_do_ioctl = atl1e_ioctl,
+ .ndo_tx_timeout = atl1e_tx_timeout,
+ .ndo_vlan_rx_register = atl1e_vlan_rx_register,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = atl1e_netpoll,
+#endif
+
+};
+
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->open = &atl1e_open;
- netdev->stop = &atl1e_close;
- netdev->hard_start_xmit = &atl1e_xmit_frame;
- netdev->get_stats = &atl1e_get_stats;
- netdev->set_multicast_list = &atl1e_set_multi;
- netdev->set_mac_address = &atl1e_set_mac_addr;
- netdev->change_mtu = &atl1e_change_mtu;
- netdev->do_ioctl = &atl1e_ioctl;
- netdev->tx_timeout = &atl1e_tx_timeout;
+ netdev->netdev_ops = &atl1e_netdev_ops;
+
netdev->watchdog_timeo = AT_TX_WATCHDOG;
- netdev->vlan_rx_register = atl1e_vlan_rx_register;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- netdev->poll_controller = atl1e_netpoll;
-#endif
atl1e_set_ethtool_ops(netdev);
netdev->features = NETIF_F_SG | NETIF_F_HW_CSUM |
@@ -2488,7 +2493,7 @@ static pci_ers_result_t
atl1e_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct atl1e_adapter *adapter = netdev->priv;
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
netif_device_detach(netdev);
@@ -2511,7 +2516,7 @@ atl1e_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
static pci_ers_result_t atl1e_io_slot_reset(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct atl1e_adapter *adapter = netdev->priv;
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
if (pci_enable_device(pdev)) {
dev_err(&pdev->dev,
@@ -2539,7 +2544,7 @@ static pci_ers_result_t atl1e_io_slot_reset(struct pci_dev *pdev)
static void atl1e_io_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct atl1e_adapter *adapter = netdev->priv;
+ struct atl1e_adapter *adapter = netdev_priv(netdev);
if (netif_running(netdev)) {
if (atl1e_up(adapter)) {
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c
index aef403d299ee..c0ceee0d7c80 100644
--- a/drivers/net/atlx/atl1.c
+++ b/drivers/net/atlx/atl1.c
@@ -195,7 +195,7 @@ static int __devinit atl1_validate_option(int *value, struct atl1_option *opt,
* value exists, a default value is used. The final value is stored
* in a variable in the adapter structure.
*/
-void __devinit atl1_check_options(struct atl1_adapter *adapter)
+static void __devinit atl1_check_options(struct atl1_adapter *adapter)
{
struct pci_dev *pdev = adapter->pdev;
int bd = adapter->bd_number;
@@ -523,7 +523,7 @@ static int atl1_get_permanent_address(struct atl1_hw *hw)
* Reads the adapter's MAC address from the EEPROM
* hw - Struct containing variables accessed by shared code
*/
-s32 atl1_read_mac_addr(struct atl1_hw *hw)
+static s32 atl1_read_mac_addr(struct atl1_hw *hw)
{
u16 i;
@@ -1390,7 +1390,8 @@ static u32 atl1_check_link(struct atl1_adapter *adapter)
/* auto-neg, insert timer to re-config phy */
if (!adapter->phy_timer_pending) {
adapter->phy_timer_pending = true;
- mod_timer(&adapter->phy_config_timer, jiffies + 3 * HZ);
+ mod_timer(&adapter->phy_config_timer,
+ round_jiffies(jiffies + 3 * HZ));
}
return 0;
@@ -1662,6 +1663,7 @@ static void atl1_via_workaround(struct atl1_adapter *adapter)
static void atl1_inc_smb(struct atl1_adapter *adapter)
{
+ struct net_device *netdev = adapter->netdev;
struct stats_msg_block *smb = adapter->smb.smb;
/* Fill out the OS statistics structure */
@@ -1704,30 +1706,30 @@ static void atl1_inc_smb(struct atl1_adapter *adapter)
adapter->soft_stats.tx_trunc += smb->tx_trunc;
adapter->soft_stats.tx_pause += smb->tx_pause;
- adapter->net_stats.rx_packets = adapter->soft_stats.rx_packets;
- adapter->net_stats.tx_packets = adapter->soft_stats.tx_packets;
- adapter->net_stats.rx_bytes = adapter->soft_stats.rx_bytes;
- adapter->net_stats.tx_bytes = adapter->soft_stats.tx_bytes;
- adapter->net_stats.multicast = adapter->soft_stats.multicast;
- adapter->net_stats.collisions = adapter->soft_stats.collisions;
- adapter->net_stats.rx_errors = adapter->soft_stats.rx_errors;
- adapter->net_stats.rx_over_errors =
+ netdev->stats.rx_packets = adapter->soft_stats.rx_packets;
+ netdev->stats.tx_packets = adapter->soft_stats.tx_packets;
+ netdev->stats.rx_bytes = adapter->soft_stats.rx_bytes;
+ netdev->stats.tx_bytes = adapter->soft_stats.tx_bytes;
+ netdev->stats.multicast = adapter->soft_stats.multicast;
+ netdev->stats.collisions = adapter->soft_stats.collisions;
+ netdev->stats.rx_errors = adapter->soft_stats.rx_errors;
+ netdev->stats.rx_over_errors =
adapter->soft_stats.rx_missed_errors;
- adapter->net_stats.rx_length_errors =
+ netdev->stats.rx_length_errors =
adapter->soft_stats.rx_length_errors;
- adapter->net_stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;
- adapter->net_stats.rx_frame_errors =
+ netdev->stats.rx_crc_errors = adapter->soft_stats.rx_crc_errors;
+ netdev->stats.rx_frame_errors =
adapter->soft_stats.rx_frame_errors;
- adapter->net_stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors;
- adapter->net_stats.rx_missed_errors =
+ netdev->stats.rx_fifo_errors = adapter->soft_stats.rx_fifo_errors;
+ netdev->stats.rx_missed_errors =
adapter->soft_stats.rx_missed_errors;
- adapter->net_stats.tx_errors = adapter->soft_stats.tx_errors;
- adapter->net_stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;
- adapter->net_stats.tx_aborted_errors =
+ netdev->stats.tx_errors = adapter->soft_stats.tx_errors;
+ netdev->stats.tx_fifo_errors = adapter->soft_stats.tx_fifo_errors;
+ netdev->stats.tx_aborted_errors =
adapter->soft_stats.tx_aborted_errors;
- adapter->net_stats.tx_window_errors =
+ netdev->stats.tx_window_errors =
adapter->soft_stats.tx_window_errors;
- adapter->net_stats.tx_carrier_errors =
+ netdev->stats.tx_carrier_errors =
adapter->soft_stats.tx_carrier_errors;
}
@@ -1860,7 +1862,7 @@ static u16 atl1_alloc_rx_buffers(struct atl1_adapter *adapter)
adapter->rx_buffer_len + NET_IP_ALIGN);
if (unlikely(!skb)) {
/* Better luck next round */
- adapter->net_stats.rx_dropped++;
+ adapter->netdev->stats.rx_dropped++;
break;
}
@@ -2026,8 +2028,6 @@ rrd_ok:
buffer_info->skb = NULL;
buffer_info->alloced = 0;
rrd->xsz.valid = 0;
-
- adapter->netdev->last_rx = jiffies;
}
atomic_set(&rrd_ring->next_to_clean, rrd_next_to_clean);
@@ -2524,17 +2524,6 @@ static irqreturn_t atl1_intr(int irq, void *data)
return IRQ_HANDLED;
}
-/*
- * atl1_watchdog - Timer Call-back
- * @data: pointer to netdev cast into an unsigned long
- */
-static void atl1_watchdog(unsigned long data)
-{
- struct atl1_adapter *adapter = (struct atl1_adapter *)data;
-
- /* Reset the timer */
- mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
-}
/*
* atl1_phy_config - Timer Call-back
@@ -2607,7 +2596,6 @@ static s32 atl1_up(struct atl1_adapter *adapter)
if (unlikely(err))
goto err_up;
- mod_timer(&adapter->watchdog_timer, jiffies);
atlx_irq_enable(adapter);
atl1_check_link(adapter);
netif_start_queue(netdev);
@@ -2625,7 +2613,6 @@ static void atl1_down(struct atl1_adapter *adapter)
struct net_device *netdev = adapter->netdev;
netif_stop_queue(netdev);
- del_timer_sync(&adapter->watchdog_timer);
del_timer_sync(&adapter->phy_config_timer);
adapter->phy_timer_pending = false;
@@ -2893,6 +2880,22 @@ static void atl1_poll_controller(struct net_device *netdev)
}
#endif
+static const struct net_device_ops atl1_netdev_ops = {
+ .ndo_open = atl1_open,
+ .ndo_stop = atl1_close,
+ .ndo_start_xmit = atl1_xmit_frame,
+ .ndo_set_multicast_list = atlx_set_multi,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = atl1_set_mac,
+ .ndo_change_mtu = atl1_change_mtu,
+ .ndo_do_ioctl = atlx_ioctl,
+ .ndo_tx_timeout = atlx_tx_timeout,
+ .ndo_vlan_rx_register = atlx_vlan_rx_register,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = atl1_poll_controller,
+#endif
+};
+
/*
* atl1_probe - Device Initialization Routine
* @pdev: PCI device information struct
@@ -2980,20 +2983,8 @@ static int __devinit atl1_probe(struct pci_dev *pdev,
adapter->mii.phy_id_mask = 0x1f;
adapter->mii.reg_num_mask = 0x1f;
- netdev->open = &atl1_open;
- netdev->stop = &atl1_close;
- netdev->hard_start_xmit = &atl1_xmit_frame;
- netdev->get_stats = &atlx_get_stats;
- netdev->set_multicast_list = &atlx_set_multi;
- netdev->set_mac_address = &atl1_set_mac;
- netdev->change_mtu = &atl1_change_mtu;
- netdev->do_ioctl = &atlx_ioctl;
- netdev->tx_timeout = &atlx_tx_timeout;
+ netdev->netdev_ops = &atl1_netdev_ops;
netdev->watchdog_timeo = 5 * HZ;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- netdev->poll_controller = atl1_poll_controller;
-#endif
- netdev->vlan_rx_register = atlx_vlan_rx_register;
netdev->ethtool_ops = &atl1_ethtool_ops;
adapter->bd_number = cards_found;
@@ -3049,13 +3040,8 @@ static int __devinit atl1_probe(struct pci_dev *pdev,
netif_carrier_off(netdev);
netif_stop_queue(netdev);
- init_timer(&adapter->watchdog_timer);
- adapter->watchdog_timer.function = &atl1_watchdog;
- adapter->watchdog_timer.data = (unsigned long)adapter;
-
- init_timer(&adapter->phy_config_timer);
- adapter->phy_config_timer.function = &atl1_phy_config;
- adapter->phy_config_timer.data = (unsigned long)adapter;
+ setup_timer(&adapter->phy_config_timer, &atl1_phy_config,
+ (unsigned long)adapter);
adapter->phy_timer_pending = false;
INIT_WORK(&adapter->tx_timeout_task, atl1_tx_timeout_task);
@@ -3173,8 +3159,6 @@ static struct atl1_stats atl1_gstrings_stats[] = {
{"tx_bytes", ATL1_STAT(soft_stats.tx_bytes)},
{"rx_errors", ATL1_STAT(soft_stats.rx_errors)},
{"tx_errors", ATL1_STAT(soft_stats.tx_errors)},
- {"rx_dropped", ATL1_STAT(net_stats.rx_dropped)},
- {"tx_dropped", ATL1_STAT(net_stats.tx_dropped)},
{"multicast", ATL1_STAT(soft_stats.multicast)},
{"collisions", ATL1_STAT(soft_stats.collisions)},
{"rx_length_errors", ATL1_STAT(soft_stats.rx_length_errors)},
diff --git a/drivers/net/atlx/atl1.h b/drivers/net/atlx/atl1.h
index ffa73fc8d95e..146372fd6683 100644
--- a/drivers/net/atlx/atl1.h
+++ b/drivers/net/atlx/atl1.h
@@ -754,7 +754,7 @@ struct atl1_hw {
struct atl1_adapter {
struct net_device *netdev;
struct pci_dev *pdev;
- struct net_device_stats net_stats;
+
struct atl1_sft_stats soft_stats;
struct vlan_group *vlgrp;
u32 rx_buffer_len;
@@ -765,7 +765,7 @@ struct atl1_adapter {
struct work_struct tx_timeout_task;
struct work_struct link_chg_task;
struct work_struct pcie_dma_to_rst_task;
- struct timer_list watchdog_timer;
+
struct timer_list phy_config_timer;
bool phy_timer_pending;
diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c
index 8571e8c0bc67..bc394491b63b 100644
--- a/drivers/net/atlx/atl2.c
+++ b/drivers/net/atlx/atl2.c
@@ -418,7 +418,7 @@ static void atl2_intr_rx(struct atl2_adapter *adapter)
* Check that some rx space is free. If not,
* free one and mark stats->rx_dropped++.
*/
- adapter->net_stats.rx_dropped++;
+ netdev->stats.rx_dropped++;
break;
}
skb_reserve(skb, NET_IP_ALIGN);
@@ -435,20 +435,19 @@ static void atl2_intr_rx(struct atl2_adapter *adapter)
} else
#endif
netif_rx(skb);
- adapter->net_stats.rx_bytes += rx_size;
- adapter->net_stats.rx_packets++;
- netdev->last_rx = jiffies;
+ netdev->stats.rx_bytes += rx_size;
+ netdev->stats.rx_packets++;
} else {
- adapter->net_stats.rx_errors++;
+ netdev->stats.rx_errors++;
if (rxd->status.ok && rxd->status.pkt_size <= 60)
- adapter->net_stats.rx_length_errors++;
+ netdev->stats.rx_length_errors++;
if (rxd->status.mcast)
- adapter->net_stats.multicast++;
+ netdev->stats.multicast++;
if (rxd->status.crc)
- adapter->net_stats.rx_crc_errors++;
+ netdev->stats.rx_crc_errors++;
if (rxd->status.align)
- adapter->net_stats.rx_frame_errors++;
+ netdev->stats.rx_frame_errors++;
}
/* advance write ptr */
@@ -463,6 +462,7 @@ static void atl2_intr_rx(struct atl2_adapter *adapter)
static void atl2_intr_tx(struct atl2_adapter *adapter)
{
+ struct net_device *netdev = adapter->netdev;
u32 txd_read_ptr;
u32 txs_write_ptr;
struct tx_pkt_status *txs;
@@ -522,20 +522,20 @@ static void atl2_intr_tx(struct atl2_adapter *adapter)
/* tx statistics: */
if (txs->ok) {
- adapter->net_stats.tx_bytes += txs->pkt_size;
- adapter->net_stats.tx_packets++;
+ netdev->stats.tx_bytes += txs->pkt_size;
+ netdev->stats.tx_packets++;
}
else
- adapter->net_stats.tx_errors++;
+ netdev->stats.tx_errors++;
if (txs->defer)
- adapter->net_stats.collisions++;
+ netdev->stats.collisions++;
if (txs->abort_col)
- adapter->net_stats.tx_aborted_errors++;
+ netdev->stats.tx_aborted_errors++;
if (txs->late_col)
- adapter->net_stats.tx_window_errors++;
+ netdev->stats.tx_window_errors++;
if (txs->underun)
- adapter->net_stats.tx_fifo_errors++;
+ netdev->stats.tx_fifo_errors++;
} while (1);
if (free_hole) {
@@ -621,7 +621,7 @@ static irqreturn_t atl2_intr(int irq, void *data)
/* link event */
if (status & (ISR_PHY | ISR_MANUAL)) {
- adapter->net_stats.tx_carrier_errors++;
+ adapter->netdev->stats.tx_carrier_errors++;
atl2_check_for_link(adapter);
}
@@ -644,7 +644,6 @@ static int atl2_request_irq(struct atl2_adapter *adapter)
int flags, err = 0;
flags = IRQF_SHARED;
-#ifdef CONFIG_PCI_MSI
adapter->have_msi = true;
err = pci_enable_msi(adapter->pdev);
if (err)
@@ -652,7 +651,6 @@ static int atl2_request_irq(struct atl2_adapter *adapter)
if (adapter->have_msi)
flags &= ~IRQF_SHARED;
-#endif
return request_irq(adapter->pdev->irq, &atl2_intr, flags, netdev->name,
netdev);
@@ -723,7 +721,7 @@ static int atl2_open(struct net_device *netdev)
clear_bit(__ATL2_DOWN, &adapter->flags);
- mod_timer(&adapter->watchdog_timer, jiffies + 4*HZ);
+ mod_timer(&adapter->watchdog_timer, round_jiffies(jiffies + 4*HZ));
val = ATL2_READ_REG(&adapter->hw, REG_MASTER_CTRL);
ATL2_WRITE_REG(&adapter->hw, REG_MASTER_CTRL,
@@ -900,19 +898,6 @@ static int atl2_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
}
/*
- * atl2_get_stats - Get System Network Statistics
- * @netdev: network interface device structure
- *
- * Returns the address of the device statistics structure.
- * The statistics are actually updated from the timer callback.
- */
-static struct net_device_stats *atl2_get_stats(struct net_device *netdev)
-{
- struct atl2_adapter *adapter = netdev_priv(netdev);
- return &adapter->net_stats;
-}
-
-/*
* atl2_change_mtu - Change the Maximum Transfer Unit
* @netdev: network interface device structure
* @new_mtu: new value for maximum frame size
@@ -1050,18 +1035,21 @@ static void atl2_tx_timeout(struct net_device *netdev)
static void atl2_watchdog(unsigned long data)
{
struct atl2_adapter *adapter = (struct atl2_adapter *) data;
- u32 drop_rxd, drop_rxs;
- unsigned long flags;
if (!test_bit(__ATL2_DOWN, &adapter->flags)) {
+ u32 drop_rxd, drop_rxs;
+ unsigned long flags;
+
spin_lock_irqsave(&adapter->stats_lock, flags);
drop_rxd = ATL2_READ_REG(&adapter->hw, REG_STS_RXD_OV);
drop_rxs = ATL2_READ_REG(&adapter->hw, REG_STS_RXS_OV);
- adapter->net_stats.rx_over_errors += (drop_rxd+drop_rxs);
spin_unlock_irqrestore(&adapter->stats_lock, flags);
+ adapter->netdev->stats.rx_over_errors += drop_rxd + drop_rxs;
+
/* Reset the timer */
- mod_timer(&adapter->watchdog_timer, jiffies + 4 * HZ);
+ mod_timer(&adapter->watchdog_timer,
+ round_jiffies(jiffies + 4 * HZ));
}
}
@@ -1265,7 +1253,8 @@ static int atl2_check_link(struct atl2_adapter *adapter)
* (if interval smaller than 5 seconds, something strange) */
if (!test_bit(__ATL2_DOWN, &adapter->flags)) {
if (!test_and_set_bit(0, &adapter->cfg_phy))
- mod_timer(&adapter->phy_config_timer, jiffies + 5 * HZ);
+ mod_timer(&adapter->phy_config_timer,
+ round_jiffies(jiffies + 5 * HZ));
}
return 0;
@@ -1320,6 +1309,23 @@ static void atl2_poll_controller(struct net_device *netdev)
}
#endif
+
+static const struct net_device_ops atl2_netdev_ops = {
+ .ndo_open = atl2_open,
+ .ndo_stop = atl2_close,
+ .ndo_start_xmit = atl2_xmit_frame,
+ .ndo_set_multicast_list = atl2_set_multi,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = atl2_set_mac,
+ .ndo_change_mtu = atl2_change_mtu,
+ .ndo_do_ioctl = atl2_ioctl,
+ .ndo_tx_timeout = atl2_tx_timeout,
+ .ndo_vlan_rx_register = atl2_vlan_rx_register,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = atl2_poll_controller,
+#endif
+};
+
/*
* atl2_probe - Device Initialization Routine
* @pdev: PCI device information struct
@@ -1393,26 +1399,9 @@ static int __devinit atl2_probe(struct pci_dev *pdev,
atl2_setup_pcicmd(pdev);
- netdev->open = &atl2_open;
- netdev->stop = &atl2_close;
- netdev->hard_start_xmit = &atl2_xmit_frame;
- netdev->get_stats = &atl2_get_stats;
- netdev->set_multicast_list = &atl2_set_multi;
- netdev->set_mac_address = &atl2_set_mac;
- netdev->change_mtu = &atl2_change_mtu;
- netdev->do_ioctl = &atl2_ioctl;
+ netdev->netdev_ops = &atl2_netdev_ops;
atl2_set_ethtool_ops(netdev);
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
- netdev->poll_controller = atl2_poll_controller;
-#endif
-#ifdef HAVE_TX_TIMEOUT
- netdev->tx_timeout = &atl2_tx_timeout;
netdev->watchdog_timeo = 5 * HZ;
-#endif
-#ifdef NETIF_F_HW_VLAN_TX
- netdev->vlan_rx_register = atl2_vlan_rx_register;
-#endif
strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
netdev->mem_start = mmio_start;
diff --git a/drivers/net/atlx/atl2.h b/drivers/net/atlx/atl2.h
index 09974df76b18..d918bbe621ea 100644
--- a/drivers/net/atlx/atl2.h
+++ b/drivers/net/atlx/atl2.h
@@ -453,7 +453,6 @@ struct atl2_adapter {
/* OS defined structs */
struct net_device *netdev;
struct pci_dev *pdev;
- struct net_device_stats net_stats;
#ifdef NETIF_F_HW_VLAN_TX
struct vlan_group *vlgrp;
#endif
diff --git a/drivers/net/atlx/atlx.c b/drivers/net/atlx/atlx.c
index 3cc9d1089ca1..3dc014215679 100644
--- a/drivers/net/atlx/atlx.c
+++ b/drivers/net/atlx/atlx.c
@@ -182,19 +182,6 @@ static void atlx_clear_phy_int(struct atlx_adapter *adapter)
}
/*
- * atlx_get_stats - Get System Network Statistics
- * @netdev: network interface device structure
- *
- * Returns the address of the device statistics structure.
- * The statistics are actually updated from the timer callback.
- */
-static struct net_device_stats *atlx_get_stats(struct net_device *netdev)
-{
- struct atlx_adapter *adapter = netdev_priv(netdev);
- return &adapter->net_stats;
-}
-
-/*
* atlx_tx_timeout - Respond to a Tx Hang
* @netdev: network interface device structure
*/
diff --git a/drivers/net/atp.c b/drivers/net/atp.c
index c10cd8058e23..ea493ce23982 100644
--- a/drivers/net/atp.c
+++ b/drivers/net/atp.c
@@ -248,7 +248,6 @@ static int __init atp_probe1(long ioaddr)
struct net_local *lp;
int saved_ctrl_reg, status, i;
int res;
- DECLARE_MAC_BUF(mac);
outb(0xff, ioaddr + PAR_DATA);
/* Save the original value of the Control register, in case we guessed
@@ -324,8 +323,8 @@ static int __init atp_probe1(long ioaddr)
#endif
printk(KERN_NOTICE "%s: Pocket adapter found at %#3lx, IRQ %d, "
- "SAPROM %s.\n",
- dev->name, dev->base_addr, dev->irq, print_mac(mac, dev->dev_addr));
+ "SAPROM %pM.\n",
+ dev->name, dev->base_addr, dev->irq, dev->dev_addr);
/* Reset the ethernet hardware and activate the printer pass-through. */
write_reg_high(ioaddr, CMR1, CMR1h_RESET | CMR1h_MUX);
@@ -421,7 +420,7 @@ static unsigned short __init eeprom_op(long ioaddr, u32 cmd)
registers that "should" only need to be set once at boot, so that
there is non-reboot way to recover if something goes wrong.
- This is an attachable device: if there is no dev->priv entry then it wasn't
+ This is an attachable device: if there is no private entry then it wasn't
probed for at boot-time, and we need to probe for it again.
*/
static int net_open(struct net_device *dev)
@@ -803,21 +802,22 @@ static void net_rx(struct net_device *dev)
static void read_block(long ioaddr, int length, unsigned char *p, int data_mode)
{
-
if (data_mode <= 3) { /* Mode 0 or 1 */
outb(Ctrl_LNibRead, ioaddr + PAR_CONTROL);
outb(length == 8 ? RdAddr | HNib | MAR : RdAddr | MAR,
ioaddr + PAR_DATA);
if (data_mode <= 1) { /* Mode 0 or 1 */
- do *p++ = read_byte_mode0(ioaddr); while (--length > 0);
- } else /* Mode 2 or 3 */
- do *p++ = read_byte_mode2(ioaddr); while (--length > 0);
- } else if (data_mode <= 5)
- do *p++ = read_byte_mode4(ioaddr); while (--length > 0);
- else
- do *p++ = read_byte_mode6(ioaddr); while (--length > 0);
+ do { *p++ = read_byte_mode0(ioaddr); } while (--length > 0);
+ } else { /* Mode 2 or 3 */
+ do { *p++ = read_byte_mode2(ioaddr); } while (--length > 0);
+ }
+ } else if (data_mode <= 5) {
+ do { *p++ = read_byte_mode4(ioaddr); } while (--length > 0);
+ } else {
+ do { *p++ = read_byte_mode6(ioaddr); } while (--length > 0);
+ }
- outb(EOC+HNib+MAR, ioaddr + PAR_DATA);
+ outb(EOC+HNib+MAR, ioaddr + PAR_DATA);
outb(Ctrl_SelData, ioaddr + PAR_CONTROL);
}
@@ -913,7 +913,8 @@ static void __exit atp_cleanup_module(void) {
struct net_device *next_dev;
while (root_atp_dev) {
- next_dev = ((struct net_local *)root_atp_dev->priv)->next_module;
+ struct net_local *atp_local = netdev_priv(root_atp_dev);
+ next_dev = atp_local->next_module;
unregister_netdev(root_atp_dev);
/* No need to release_region(), since we never snarf it. */
free_netdev(root_atp_dev);
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 019b13c08ae6..9c875bb3f76c 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -193,7 +193,7 @@ struct au1000_private *au_macs[NUM_ETH_INTERFACES];
*/
static int au1000_mdio_read(struct net_device *dev, int phy_addr, int reg)
{
- struct au1000_private *aup = (struct au1000_private *) dev->priv;
+ struct au1000_private *aup = netdev_priv(dev);
volatile u32 *const mii_control_reg = &aup->mac->mii_control;
volatile u32 *const mii_data_reg = &aup->mac->mii_data;
u32 timedout = 20;
@@ -228,7 +228,7 @@ static int au1000_mdio_read(struct net_device *dev, int phy_addr, int reg)
static void au1000_mdio_write(struct net_device *dev, int phy_addr,
int reg, u16 value)
{
- struct au1000_private *aup = (struct au1000_private *) dev->priv;
+ struct au1000_private *aup = netdev_priv(dev);
volatile u32 *const mii_control_reg = &aup->mac->mii_control;
volatile u32 *const mii_data_reg = &aup->mac->mii_data;
u32 timedout = 20;
@@ -283,7 +283,7 @@ static int au1000_mdiobus_reset(struct mii_bus *bus)
static int mii_probe (struct net_device *dev)
{
- struct au1000_private *const aup = (struct au1000_private *) dev->priv;
+ struct au1000_private *const aup = netdev_priv(dev);
struct phy_device *phydev = NULL;
#if defined(AU1XXX_PHY_STATIC_CONFIG)
@@ -353,7 +353,6 @@ static int mii_probe (struct net_device *dev)
}
/* now we are supposed to have a proper phydev, to attach to... */
- BUG_ON(!phydev);
BUG_ON(phydev->attached_dev);
phydev = phy_connect(dev, phydev->dev.bus_id, &au1000_adjust_link, 0,
@@ -415,7 +414,7 @@ void ReleaseDB(struct au1000_private *aup, db_dest_t *pDB)
static void enable_rx_tx(struct net_device *dev)
{
- struct au1000_private *aup = (struct au1000_private *) dev->priv;
+ struct au1000_private *aup = netdev_priv(dev);
if (au1000_debug > 4)
printk(KERN_INFO "%s: enable_rx_tx\n", dev->name);
@@ -426,7 +425,7 @@ static void enable_rx_tx(struct net_device *dev)
static void hard_stop(struct net_device *dev)
{
- struct au1000_private *aup = (struct au1000_private *) dev->priv;
+ struct au1000_private *aup = netdev_priv(dev);
if (au1000_debug > 4)
printk(KERN_INFO "%s: hard stop\n", dev->name);
@@ -438,7 +437,7 @@ static void hard_stop(struct net_device *dev)
static void enable_mac(struct net_device *dev, int force_reset)
{
unsigned long flags;
- struct au1000_private *aup = (struct au1000_private *) dev->priv;
+ struct au1000_private *aup = netdev_priv(dev);
spin_lock_irqsave(&aup->lock, flags);
@@ -457,7 +456,7 @@ static void enable_mac(struct net_device *dev, int force_reset)
static void reset_mac_unlocked(struct net_device *dev)
{
- struct au1000_private *const aup = (struct au1000_private *) dev->priv;
+ struct au1000_private *const aup = netdev_priv(dev);
int i;
hard_stop(dev);
@@ -483,7 +482,7 @@ static void reset_mac_unlocked(struct net_device *dev)
static void reset_mac(struct net_device *dev)
{
- struct au1000_private *const aup = (struct au1000_private *) dev->priv;
+ struct au1000_private *const aup = netdev_priv(dev);
unsigned long flags;
if (au1000_debug > 4)
@@ -572,7 +571,7 @@ static int __init au1000_init_module(void)
static int au1000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- struct au1000_private *aup = (struct au1000_private *)dev->priv;
+ struct au1000_private *aup = netdev_priv(dev);
if (aup->phy_dev)
return phy_ethtool_gset(aup->phy_dev, cmd);
@@ -582,7 +581,7 @@ static int au1000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static int au1000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- struct au1000_private *aup = (struct au1000_private *)dev->priv;
+ struct au1000_private *aup = netdev_priv(dev);
if (!capable(CAP_NET_ADMIN))
return -EPERM;
@@ -596,7 +595,7 @@ static int au1000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static void
au1000_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
- struct au1000_private *aup = (struct au1000_private *)dev->priv;
+ struct au1000_private *aup = netdev_priv(dev);
strcpy(info->driver, DRV_NAME);
strcpy(info->version, DRV_VERSION);
@@ -652,7 +651,7 @@ static struct net_device * au1000_probe(int port_num)
printk("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n",
dev->name, base, irq);
- aup = dev->priv;
+ aup = netdev_priv(dev);
spin_lock_init(&aup->lock);
@@ -817,7 +816,7 @@ err_out:
*/
static int au1000_init(struct net_device *dev)
{
- struct au1000_private *aup = (struct au1000_private *) dev->priv;
+ struct au1000_private *aup = netdev_priv(dev);
unsigned long flags;
int i;
u32 control;
@@ -868,7 +867,7 @@ static int au1000_init(struct net_device *dev)
static void
au1000_adjust_link(struct net_device *dev)
{
- struct au1000_private *aup = (struct au1000_private *) dev->priv;
+ struct au1000_private *aup = netdev_priv(dev);
struct phy_device *phydev = aup->phy_dev;
unsigned long flags;
@@ -947,7 +946,7 @@ au1000_adjust_link(struct net_device *dev)
static int au1000_open(struct net_device *dev)
{
int retval;
- struct au1000_private *aup = (struct au1000_private *) dev->priv;
+ struct au1000_private *aup = netdev_priv(dev);
if (au1000_debug > 4)
printk("%s: open: dev=%p\n", dev->name, dev);
@@ -982,7 +981,7 @@ static int au1000_open(struct net_device *dev)
static int au1000_close(struct net_device *dev)
{
unsigned long flags;
- struct au1000_private *const aup = (struct au1000_private *) dev->priv;
+ struct au1000_private *const aup = netdev_priv(dev);
if (au1000_debug > 4)
printk("%s: close: dev=%p\n", dev->name, dev);
@@ -1013,7 +1012,7 @@ static void __exit au1000_cleanup_module(void)
for (i = 0; i < num_ifs; i++) {
dev = iflist[i].dev;
if (dev) {
- aup = (struct au1000_private *) dev->priv;
+ aup = netdev_priv(dev);
unregister_netdev(dev);
mdiobus_unregister(aup->mii_bus);
mdiobus_free(aup->mii_bus);
@@ -1035,7 +1034,7 @@ static void __exit au1000_cleanup_module(void)
static void update_tx_stats(struct net_device *dev, u32 status)
{
- struct au1000_private *aup = (struct au1000_private *) dev->priv;
+ struct au1000_private *aup = netdev_priv(dev);
struct net_device_stats *ps = &dev->stats;
if (status & TX_FRAME_ABORTED) {
@@ -1064,7 +1063,7 @@ static void update_tx_stats(struct net_device *dev, u32 status)
*/
static void au1000_tx_ack(struct net_device *dev)
{
- struct au1000_private *aup = (struct au1000_private *) dev->priv;
+ struct au1000_private *aup = netdev_priv(dev);
volatile tx_dma_t *ptxd;
ptxd = aup->tx_dma_ring[aup->tx_tail];
@@ -1091,7 +1090,7 @@ static void au1000_tx_ack(struct net_device *dev)
*/
static int au1000_tx(struct sk_buff *skb, struct net_device *dev)
{
- struct au1000_private *aup = (struct au1000_private *) dev->priv;
+ struct au1000_private *aup = netdev_priv(dev);
struct net_device_stats *ps = &dev->stats;
volatile tx_dma_t *ptxd;
u32 buff_stat;
@@ -1145,7 +1144,7 @@ static int au1000_tx(struct sk_buff *skb, struct net_device *dev)
static inline void update_rx_stats(struct net_device *dev, u32 status)
{
- struct au1000_private *aup = (struct au1000_private *) dev->priv;
+ struct au1000_private *aup = netdev_priv(dev);
struct net_device_stats *ps = &dev->stats;
ps->rx_packets++;
@@ -1173,7 +1172,7 @@ static inline void update_rx_stats(struct net_device *dev, u32 status)
*/
static int au1000_rx(struct net_device *dev)
{
- struct au1000_private *aup = (struct au1000_private *) dev->priv;
+ struct au1000_private *aup = netdev_priv(dev);
struct sk_buff *skb;
volatile rx_dma_t *prxd;
u32 buff_stat, status;
@@ -1240,7 +1239,6 @@ static int au1000_rx(struct net_device *dev)
/* next descriptor */
prxd = aup->rx_dma_ring[aup->rx_head];
buff_stat = prxd->buff_stat;
- dev->last_rx = jiffies;
}
return 0;
}
@@ -1276,7 +1274,7 @@ static void au1000_tx_timeout(struct net_device *dev)
static void set_rx_mode(struct net_device *dev)
{
- struct au1000_private *aup = (struct au1000_private *) dev->priv;
+ struct au1000_private *aup = netdev_priv(dev);
if (au1000_debug > 4)
printk("%s: set_rx_mode: flags=%x\n", dev->name, dev->flags);
@@ -1308,7 +1306,7 @@ static void set_rx_mode(struct net_device *dev)
static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- struct au1000_private *aup = (struct au1000_private *)dev->priv;
+ struct au1000_private *aup = netdev_priv(dev);
if (!netif_running(dev)) return -EINVAL;
diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c
index 9a314d88e7b6..337488ec707c 100644
--- a/drivers/net/ax88796.c
+++ b/drivers/net/ax88796.c
@@ -758,13 +758,10 @@ static int ax_init_dev(struct net_device *dev, int first_init)
#endif
ax_NS8390_init(dev, 0);
- if (first_init) {
- DECLARE_MAC_BUF(mac);
-
- dev_info(&ax->dev->dev, "%dbit, irq %d, %lx, MAC: %s\n",
+ if (first_init)
+ dev_info(&ax->dev->dev, "%dbit, irq %d, %lx, MAC: %pM\n",
ei_status.word16 ? 16:8, dev->irq, dev->base_addr,
- print_mac(mac, dev->dev_addr));
- }
+ dev->dev_addr);
ret = register_netdev(dev);
if (ret)
diff --git a/drivers/net/b44.c b/drivers/net/b44.c
index c3bda5ce67c4..0e7470a201f0 100644
--- a/drivers/net/b44.c
+++ b/drivers/net/b44.c
@@ -829,7 +829,6 @@ static int b44_rx(struct b44 *bp, int budget)
skb->ip_summed = CHECKSUM_NONE;
skb->protocol = eth_type_trans(skb, bp->dev);
netif_receive_skb(skb);
- bp->dev->last_rx = jiffies;
received++;
budget--;
next_pkt:
@@ -847,7 +846,6 @@ static int b44_rx(struct b44 *bp, int budget)
static int b44_poll(struct napi_struct *napi, int budget)
{
struct b44 *bp = container_of(napi, struct b44, napi);
- struct net_device *netdev = bp->dev;
int work_done;
spin_lock_irq(&bp->lock);
@@ -876,7 +874,7 @@ static int b44_poll(struct napi_struct *napi, int budget)
}
if (work_done < budget) {
- netif_rx_complete(netdev, napi);
+ netif_rx_complete(napi);
b44_enable_ints(bp);
}
@@ -908,13 +906,13 @@ static irqreturn_t b44_interrupt(int irq, void *dev_id)
goto irq_ack;
}
- if (netif_rx_schedule_prep(dev, &bp->napi)) {
+ if (netif_rx_schedule_prep(&bp->napi)) {
/* NOTE: These writes are posted by the readback of
* the ISTAT register below.
*/
bp->istat = istat;
__b44_disable_ints(bp);
- __netif_rx_schedule(dev, &bp->napi);
+ __netif_rx_schedule(&bp->napi);
} else {
printk(KERN_ERR PFX "%s: Error, poll already scheduled\n",
dev->name);
@@ -2117,7 +2115,6 @@ static int __devinit b44_init_one(struct ssb_device *sdev,
struct net_device *dev;
struct b44 *bp;
int err;
- DECLARE_MAC_BUF(mac);
instance++;
@@ -2213,8 +2210,8 @@ static int __devinit b44_init_one(struct ssb_device *sdev,
*/
b44_chip_reset(bp, B44_CHIP_RESET_FULL);
- printk(KERN_INFO "%s: Broadcom 44xx/47xx 10/100BaseT Ethernet %s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "%s: Broadcom 44xx/47xx 10/100BaseT Ethernet %pM\n",
+ dev->name, dev->dev_addr);
return 0;
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c
index b458d607a9c6..78e31aa861e0 100644
--- a/drivers/net/bfin_mac.c
+++ b/drivers/net/bfin_mac.c
@@ -741,7 +741,6 @@ static void bfin_mac_rx(struct net_device *dev)
blackfin_dcache_invalidate_range((unsigned long)skb->head,
(unsigned long)skb->tail);
- dev->last_rx = jiffies;
skb->protocol = eth_type_trans(skb, dev);
#if defined(BFIN_MAC_CSUM_OFFLOAD)
skb->csum = current_rx_ptr->status.ip_payload_csum;
diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c
index a42bd19646d3..8a546a33d581 100644
--- a/drivers/net/bmac.c
+++ b/drivers/net/bmac.c
@@ -716,13 +716,11 @@ static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id)
skb_put(skb, nb);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
++dev->stats.rx_packets;
dev->stats.rx_bytes += nb;
} else {
++dev->stats.rx_dropped;
}
- dev->last_rx = jiffies;
if ((skb = bp->rx_bufs[i]) == NULL) {
bp->rx_bufs[i] = skb = dev_alloc_skb(RX_BUFLEN+2);
if (skb != NULL)
@@ -1258,7 +1256,6 @@ static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_device_i
unsigned char addr[6];
struct net_device *dev;
int is_bmac_plus = ((int)match->data) != 0;
- DECLARE_MAC_BUF(mac);
if (macio_resource_count(mdev) != 3 || macio_irq_count(mdev) != 3) {
printk(KERN_ERR "BMAC: can't use, need 3 addrs and 3 intrs\n");
@@ -1368,8 +1365,8 @@ static int __devinit bmac_probe(struct macio_dev *mdev, const struct of_device_i
goto err_out_irq2;
}
- printk(KERN_INFO "%s: BMAC%s at %s",
- dev->name, (is_bmac_plus ? "+" : ""), print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "%s: BMAC%s at %pM",
+ dev->name, (is_bmac_plus ? "+" : ""), dev->dev_addr);
XXDEBUG((", base_addr=%#0lx", dev->base_addr));
printk("\n");
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index a1a3d0e5d2b4..d4a3dac21dcf 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -57,8 +57,8 @@
#define DRV_MODULE_NAME "bnx2"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "1.8.1"
-#define DRV_MODULE_RELDATE "Oct 7, 2008"
+#define DRV_MODULE_VERSION "1.9.0"
+#define DRV_MODULE_RELDATE "Dec 16, 2008"
#define RUN_AT(x) (jiffies + (x))
@@ -89,6 +89,7 @@ typedef enum {
BCM5709,
BCM5709S,
BCM5716,
+ BCM5716S,
} board_t;
/* indexed by board_t, above */
@@ -105,6 +106,7 @@ static struct {
{ "Broadcom NetXtreme II BCM5709 1000Base-T" },
{ "Broadcom NetXtreme II BCM5709 1000Base-SX" },
{ "Broadcom NetXtreme II BCM5716 1000Base-T" },
+ { "Broadcom NetXtreme II BCM5716 1000Base-SX" },
};
static DEFINE_PCI_DEVICE_TABLE(bnx2_pci_tbl) = {
@@ -128,6 +130,8 @@ static DEFINE_PCI_DEVICE_TABLE(bnx2_pci_tbl) = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5709S },
{ PCI_VENDOR_ID_BROADCOM, 0x163b,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5716 },
+ { PCI_VENDOR_ID_BROADCOM, 0x163c,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5716S },
{ 0, }
};
@@ -543,9 +547,9 @@ bnx2_free_rx_mem(struct bnx2 *bp)
for (j = 0; j < bp->rx_max_pg_ring; j++) {
if (rxr->rx_pg_desc_ring[j])
pci_free_consistent(bp->pdev, RXBD_RING_SIZE,
- rxr->rx_pg_desc_ring[i],
- rxr->rx_pg_desc_mapping[i]);
- rxr->rx_pg_desc_ring[i] = NULL;
+ rxr->rx_pg_desc_ring[j],
+ rxr->rx_pg_desc_mapping[j]);
+ rxr->rx_pg_desc_ring[j] = NULL;
}
if (rxr->rx_pg_ring)
vfree(rxr->rx_pg_ring);
@@ -1652,7 +1656,7 @@ bnx2_setup_serdes_phy(struct bnx2 *bp, u8 port)
* exchanging base pages plus 3 next pages and
* normally completes in about 120 msec.
*/
- bp->current_interval = SERDES_AN_TIMEOUT;
+ bp->current_interval = BNX2_SERDES_AN_TIMEOUT;
bp->serdes_an_pending = 1;
mod_timer(&bp->timer, jiffies + bp->current_interval);
} else {
@@ -2274,7 +2278,7 @@ bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int ack, int silent)
return 0;
/* wait for an acknowledgement. */
- for (i = 0; i < (FW_ACK_TIME_OUT_MS / 10); i++) {
+ for (i = 0; i < (BNX2_FW_ACK_TIME_OUT_MS / 10); i++) {
msleep(10);
val = bnx2_shmem_rd(bp, BNX2_FW_MB);
@@ -3000,7 +3004,6 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget)
#endif
netif_receive_skb(skb);
- bp->dev->last_rx = jiffies;
rx_pkt++;
next_rx:
@@ -3040,7 +3043,6 @@ bnx2_msi(int irq, void *dev_instance)
{
struct bnx2_napi *bnapi = dev_instance;
struct bnx2 *bp = bnapi->bp;
- struct net_device *dev = bp->dev;
prefetch(bnapi->status_blk.msi);
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
@@ -3051,7 +3053,7 @@ bnx2_msi(int irq, void *dev_instance)
if (unlikely(atomic_read(&bp->intr_sem) != 0))
return IRQ_HANDLED;
- netif_rx_schedule(dev, &bnapi->napi);
+ netif_rx_schedule(&bnapi->napi);
return IRQ_HANDLED;
}
@@ -3061,7 +3063,6 @@ bnx2_msi_1shot(int irq, void *dev_instance)
{
struct bnx2_napi *bnapi = dev_instance;
struct bnx2 *bp = bnapi->bp;
- struct net_device *dev = bp->dev;
prefetch(bnapi->status_blk.msi);
@@ -3069,7 +3070,7 @@ bnx2_msi_1shot(int irq, void *dev_instance)
if (unlikely(atomic_read(&bp->intr_sem) != 0))
return IRQ_HANDLED;
- netif_rx_schedule(dev, &bnapi->napi);
+ netif_rx_schedule(&bnapi->napi);
return IRQ_HANDLED;
}
@@ -3079,7 +3080,6 @@ bnx2_interrupt(int irq, void *dev_instance)
{
struct bnx2_napi *bnapi = dev_instance;
struct bnx2 *bp = bnapi->bp;
- struct net_device *dev = bp->dev;
struct status_block *sblk = bnapi->status_blk.msi;
/* When using INTx, it is possible for the interrupt to arrive
@@ -3106,9 +3106,9 @@ bnx2_interrupt(int irq, void *dev_instance)
if (unlikely(atomic_read(&bp->intr_sem) != 0))
return IRQ_HANDLED;
- if (netif_rx_schedule_prep(dev, &bnapi->napi)) {
+ if (netif_rx_schedule_prep(&bnapi->napi)) {
bnapi->last_status_idx = sblk->status_idx;
- __netif_rx_schedule(dev, &bnapi->napi);
+ __netif_rx_schedule(&bnapi->napi);
}
return IRQ_HANDLED;
@@ -3218,7 +3218,7 @@ static int bnx2_poll_msix(struct napi_struct *napi, int budget)
rmb();
if (likely(!bnx2_has_fast_work(bnapi))) {
- netif_rx_complete(bp->dev, napi);
+ netif_rx_complete(napi);
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, bnapi->int_num |
BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
bnapi->last_status_idx);
@@ -3251,7 +3251,7 @@ static int bnx2_poll(struct napi_struct *napi, int budget)
rmb();
if (likely(!bnx2_has_work(bnapi))) {
- netif_rx_complete(bp->dev, napi);
+ netif_rx_complete(napi);
if (likely(bp->flags & BNX2_FLAG_USING_MSI_OR_MSIX)) {
REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
@@ -4493,7 +4493,7 @@ bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
static int
bnx2_init_chip(struct bnx2 *bp)
{
- u32 val;
+ u32 val, mtu;
int rc, i;
/* Make sure the interrupt is not active. */
@@ -4585,11 +4585,19 @@ bnx2_init_chip(struct bnx2 *bp)
REG_WR(bp, BNX2_EMAC_BACKOFF_SEED, val);
/* Program the MTU. Also include 4 bytes for CRC32. */
- val = bp->dev->mtu + ETH_HLEN + 4;
+ mtu = bp->dev->mtu;
+ val = mtu + ETH_HLEN + ETH_FCS_LEN;
if (val > (MAX_ETHERNET_PACKET_SIZE + 4))
val |= BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA;
REG_WR(bp, BNX2_EMAC_RX_MTU_SIZE, val);
+ if (mtu < 1500)
+ mtu = 1500;
+
+ bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG, BNX2_RBUF_CONFIG_VAL(mtu));
+ bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG2, BNX2_RBUF_CONFIG2_VAL(mtu));
+ bnx2_reg_wr_ind(bp, BNX2_RBUF_CONFIG3, BNX2_RBUF_CONFIG3_VAL(mtu));
+
for (i = 0; i < BNX2_MAX_MSIX_VEC; i++)
bp->bnx2_napi[i].last_status_idx = 0;
@@ -5719,7 +5727,7 @@ bnx2_5708_serdes_timer(struct bnx2 *bp)
bnx2_read_phy(bp, bp->mii_bmcr, &bmcr);
if (bmcr & BMCR_ANENABLE) {
bnx2_enable_forced_2g5(bp);
- bp->current_interval = SERDES_FORCED_TIMEOUT;
+ bp->current_interval = BNX2_SERDES_FORCED_TIMEOUT;
} else {
bnx2_disable_forced_2g5(bp);
bp->serdes_an_pending = 2;
@@ -5816,6 +5824,8 @@ bnx2_enable_msix(struct bnx2 *bp, int msix_vecs)
{
int i, rc;
struct msix_entry msix_ent[BNX2_MAX_MSIX_VEC];
+ struct net_device *dev = bp->dev;
+ const int len = sizeof(bp->irq_tbl[0].name);
bnx2_setup_msix_tbl(bp);
REG_WR(bp, BNX2_PCI_MSIX_CONTROL, BNX2_MAX_MSIX_HW_VEC - 1);
@@ -5826,7 +5836,7 @@ bnx2_enable_msix(struct bnx2 *bp, int msix_vecs)
msix_ent[i].entry = i;
msix_ent[i].vector = 0;
- strcpy(bp->irq_tbl[i].name, bp->dev->name);
+ snprintf(bp->irq_tbl[i].name, len, "%s-%d", dev->name, i);
bp->irq_tbl[i].handler = bnx2_msi_1shot;
}
@@ -6173,7 +6183,7 @@ bnx2_get_stats(struct net_device *dev)
{
struct bnx2 *bp = netdev_priv(dev);
struct statistics_block *stats_blk = bp->stats_blk;
- struct net_device_stats *net_stats = &bp->net_stats;
+ struct net_device_stats *net_stats = &dev->stats;
if (bp->stats_blk == NULL) {
return net_stats;
@@ -6540,7 +6550,7 @@ bnx2_nway_reset(struct net_device *dev)
spin_lock_bh(&bp->phy_lock);
- bp->current_interval = SERDES_AN_TIMEOUT;
+ bp->current_interval = BNX2_SERDES_AN_TIMEOUT;
bp->serdes_an_pending = 1;
mod_timer(&bp->timer, jiffies + bp->current_interval);
}
@@ -7615,7 +7625,8 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
(CHIP_ID(bp) == CHIP_ID_5708_B0) ||
- (CHIP_ID(bp) == CHIP_ID_5708_B1)) {
+ (CHIP_ID(bp) == CHIP_ID_5708_B1) ||
+ !(REG_RD(bp, BNX2_PCI_CONFIG_3) & BNX2_PCI_CONFIG_3_VAUX_PRESET)) {
bp->flags |= BNX2_FLAG_NO_WOL;
bp->wol = 0;
}
@@ -7724,6 +7735,25 @@ bnx2_init_napi(struct bnx2 *bp)
}
}
+static const struct net_device_ops bnx2_netdev_ops = {
+ .ndo_open = bnx2_open,
+ .ndo_start_xmit = bnx2_start_xmit,
+ .ndo_stop = bnx2_close,
+ .ndo_get_stats = bnx2_get_stats,
+ .ndo_set_rx_mode = bnx2_set_rx_mode,
+ .ndo_do_ioctl = bnx2_ioctl,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = bnx2_change_mac_addr,
+ .ndo_change_mtu = bnx2_change_mtu,
+ .ndo_tx_timeout = bnx2_tx_timeout,
+#ifdef BCM_VLAN
+ .ndo_vlan_rx_register = bnx2_vlan_rx_register,
+#endif
+#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
+ .ndo_poll_controller = poll_bnx2,
+#endif
+};
+
static int __devinit
bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
@@ -7732,7 +7762,6 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
struct bnx2 *bp;
int rc;
char str[40];
- DECLARE_MAC_BUF(mac);
if (version_printed++ == 0)
printk(KERN_INFO "%s", version);
@@ -7749,28 +7778,13 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return rc;
}
- dev->open = bnx2_open;
- dev->hard_start_xmit = bnx2_start_xmit;
- dev->stop = bnx2_close;
- dev->get_stats = bnx2_get_stats;
- dev->set_rx_mode = bnx2_set_rx_mode;
- dev->do_ioctl = bnx2_ioctl;
- dev->set_mac_address = bnx2_change_mac_addr;
- dev->change_mtu = bnx2_change_mtu;
- dev->tx_timeout = bnx2_tx_timeout;
+ dev->netdev_ops = &bnx2_netdev_ops;
dev->watchdog_timeo = TX_TIMEOUT;
-#ifdef BCM_VLAN
- dev->vlan_rx_register = bnx2_vlan_rx_register;
-#endif
dev->ethtool_ops = &bnx2_ethtool_ops;
bp = netdev_priv(dev);
bnx2_init_napi(bp);
-#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
- dev->poll_controller = poll_bnx2;
-#endif
-
pci_set_drvdata(pdev, dev);
memcpy(dev->dev_addr, bp->mac_addr, 6);
@@ -7799,14 +7813,14 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
printk(KERN_INFO "%s: %s (%c%d) %s found at mem %lx, "
- "IRQ %d, node addr %s\n",
+ "IRQ %d, node addr %pM\n",
dev->name,
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, print_mac(mac, dev->dev_addr));
+ bp->pdev->irq, dev->dev_addr);
return 0;
}
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 0b032c3c7b61..900641ac63e0 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -4202,7 +4202,14 @@ struct l2_fhdr {
#define BNX2_RBUF_CONFIG 0x0020000c
#define BNX2_RBUF_CONFIG_XOFF_TRIP (0x3ffL<<0)
+#define BNX2_RBUF_CONFIG_XOFF_TRIP_VAL(mtu) \
+ ((((mtu) - 1500) * 31 / 1000) + 54)
#define BNX2_RBUF_CONFIG_XON_TRIP (0x3ffL<<16)
+#define BNX2_RBUF_CONFIG_XON_TRIP_VAL(mtu) \
+ ((((mtu) - 1500) * 39 / 1000) + 66)
+#define BNX2_RBUF_CONFIG_VAL(mtu) \
+ (BNX2_RBUF_CONFIG_XOFF_TRIP_VAL(mtu) | \
+ (BNX2_RBUF_CONFIG_XON_TRIP_VAL(mtu) << 16))
#define BNX2_RBUF_FW_BUF_ALLOC 0x00200010
#define BNX2_RBUF_FW_BUF_ALLOC_VALUE (0x1ffL<<7)
@@ -4224,11 +4231,25 @@ struct l2_fhdr {
#define BNX2_RBUF_CONFIG2 0x0020001c
#define BNX2_RBUF_CONFIG2_MAC_DROP_TRIP (0x3ffL<<0)
+#define BNX2_RBUF_CONFIG2_MAC_DROP_TRIP_VAL(mtu) \
+ ((((mtu) - 1500) * 4 / 1000) + 5)
#define BNX2_RBUF_CONFIG2_MAC_KEEP_TRIP (0x3ffL<<16)
+#define BNX2_RBUF_CONFIG2_MAC_KEEP_TRIP_VAL(mtu) \
+ ((((mtu) - 1500) * 2 / 100) + 30)
+#define BNX2_RBUF_CONFIG2_VAL(mtu) \
+ (BNX2_RBUF_CONFIG2_MAC_DROP_TRIP_VAL(mtu) | \
+ (BNX2_RBUF_CONFIG2_MAC_KEEP_TRIP_VAL(mtu) << 16))
#define BNX2_RBUF_CONFIG3 0x00200020
#define BNX2_RBUF_CONFIG3_CU_DROP_TRIP (0x3ffL<<0)
+#define BNX2_RBUF_CONFIG3_CU_DROP_TRIP_VAL(mtu) \
+ ((((mtu) - 1500) * 12 / 1000) + 18)
#define BNX2_RBUF_CONFIG3_CU_KEEP_TRIP (0x3ffL<<16)
+#define BNX2_RBUF_CONFIG3_CU_KEEP_TRIP_VAL(mtu) \
+ ((((mtu) - 1500) * 2 / 100) + 30)
+#define BNX2_RBUF_CONFIG3_VAL(mtu) \
+ (BNX2_RBUF_CONFIG3_CU_DROP_TRIP_VAL(mtu) | \
+ (BNX2_RBUF_CONFIG3_CU_KEEP_TRIP_VAL(mtu) << 16))
#define BNX2_RBUF_PKT_DATA 0x00208000
#define BNX2_RBUF_CLIST_DATA 0x00210000
@@ -6606,7 +6627,7 @@ struct bnx2_irq {
irq_handler_t handler;
unsigned int vector;
u8 requested;
- char name[16];
+ char name[IFNAMSIZ + 2];
};
struct bnx2_tx_ring_info {
@@ -6661,8 +6682,6 @@ struct bnx2_napi {
struct bnx2_tx_ring_info tx_ring;
};
-#define BNX2_TIMER_INTERVAL HZ
-
struct bnx2 {
/* Fields used in the tx and intr/napi performance paths are grouped */
/* together in the beginning of the structure. */
@@ -6710,7 +6729,11 @@ struct bnx2 {
/* End of fields used in the performance code paths. */
- int current_interval;
+ unsigned int current_interval;
+#define BNX2_TIMER_INTERVAL HZ
+#define BNX2_SERDES_AN_TIMEOUT (HZ / 3)
+#define BNX2_SERDES_FORCED_TIMEOUT (HZ / 10)
+
struct timer_list timer;
struct work_struct reset_task;
@@ -6825,9 +6848,6 @@ struct bnx2 {
u8 flow_ctrl; /* actual flow ctrl settings */
/* may be different from */
/* req_flow_ctrl if autoneg */
-#define FLOW_CTRL_TX 1
-#define FLOW_CTRL_RX 2
-
u32 advertising;
u8 req_flow_ctrl; /* flow ctrl advertisement */
@@ -6842,8 +6862,6 @@ struct bnx2 {
#define PHY_LOOPBACK 2
u8 serdes_an_pending;
-#define SERDES_AN_TIMEOUT (HZ / 3)
-#define SERDES_FORCED_TIMEOUT (HZ / 10)
u8 mac_addr[8];
@@ -6854,8 +6872,6 @@ struct bnx2 {
int pm_cap;
int pcix_cap;
- struct net_device_stats net_stats;
-
struct flash_spec *flash_info;
u32 flash_size;
@@ -6944,14 +6960,14 @@ struct fw_info {
/* This value (in milliseconds) determines the frequency of the driver
* issuing the PULSE message code. The firmware monitors this periodic
* pulse to determine when to switch to an OS-absent mode. */
-#define DRV_PULSE_PERIOD_MS 250
+#define BNX2_DRV_PULSE_PERIOD_MS 250
/* This value (in milliseconds) determines how long the driver should
* wait for an acknowledgement from the firmware before timing out. Once
* the firmware has timed out, the driver will assume there is no firmware
* running and there won't be any firmware-driver synchronization during a
* driver reset. */
-#define FW_ACK_TIME_OUT_MS 1000
+#define BNX2_FW_ACK_TIME_OUT_MS 1000
#define BNX2_DRV_RESET_SIGNATURE 0x00000000
diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c
index 4ce7fe9c5251..67de94f1f30e 100644
--- a/drivers/net/bnx2x_link.c
+++ b/drivers/net/bnx2x_link.c
@@ -289,7 +289,7 @@ static u8 bnx2x_emac_enable(struct link_params *params,
/* pause enable/disable */
bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
EMAC_RX_MODE_FLOW_EN);
- if (vars->flow_ctrl & FLOW_CTRL_RX)
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
bnx2x_bits_en(bp, emac_base +
EMAC_REG_EMAC_RX_MODE,
EMAC_RX_MODE_FLOW_EN);
@@ -297,7 +297,7 @@ static u8 bnx2x_emac_enable(struct link_params *params,
bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
(EMAC_TX_MODE_EXT_PAUSE_EN |
EMAC_TX_MODE_FLOW_EN));
- if (vars->flow_ctrl & FLOW_CTRL_TX)
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
bnx2x_bits_en(bp, emac_base +
EMAC_REG_EMAC_TX_MODE,
(EMAC_TX_MODE_EXT_PAUSE_EN |
@@ -333,7 +333,7 @@ static u8 bnx2x_emac_enable(struct link_params *params,
/* enable the NIG in/out to the emac */
REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0x1);
val = 0;
- if (vars->flow_ctrl & FLOW_CTRL_TX)
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
val = 1;
REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, val);
@@ -396,7 +396,7 @@ static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars,
/* tx control */
val = 0xc0;
- if (vars->flow_ctrl & FLOW_CTRL_TX)
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
val |= 0x800000;
wb_data[0] = val;
wb_data[1] = 0;
@@ -423,7 +423,7 @@ static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars,
/* rx control set to don't strip crc */
val = 0x14;
- if (vars->flow_ctrl & FLOW_CTRL_RX)
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
val |= 0x20;
wb_data[0] = val;
wb_data[1] = 0;
@@ -460,7 +460,7 @@ static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars,
REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 0x0);
REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 0x0);
val = 0;
- if (vars->flow_ctrl & FLOW_CTRL_TX)
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
val = 1;
REG_WR(bp, NIG_REG_BMAC0_PAUSE_OUT_EN + port*4, val);
REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x0);
@@ -580,14 +580,14 @@ void bnx2x_link_status_update(struct link_params *params,
}
if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED)
- vars->flow_ctrl |= FLOW_CTRL_TX;
+ vars->flow_ctrl |= BNX2X_FLOW_CTRL_TX;
else
- vars->flow_ctrl &= ~FLOW_CTRL_TX;
+ vars->flow_ctrl &= ~BNX2X_FLOW_CTRL_TX;
if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED)
- vars->flow_ctrl |= FLOW_CTRL_RX;
+ vars->flow_ctrl |= BNX2X_FLOW_CTRL_RX;
else
- vars->flow_ctrl &= ~FLOW_CTRL_RX;
+ vars->flow_ctrl &= ~BNX2X_FLOW_CTRL_RX;
if (vars->phy_flags & PHY_XGXS_FLAG) {
if (vars->line_speed &&
@@ -618,7 +618,7 @@ void bnx2x_link_status_update(struct link_params *params,
vars->line_speed = 0;
vars->duplex = DUPLEX_FULL;
- vars->flow_ctrl = FLOW_CTRL_NONE;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
/* indicate no mac active */
vars->mac_type = MAC_TYPE_NONE;
@@ -691,7 +691,7 @@ static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
return -EINVAL;
}
- if (flow_ctrl & FLOW_CTRL_RX ||
+ if (flow_ctrl & BNX2X_FLOW_CTRL_RX ||
line_speed == SPEED_10 ||
line_speed == SPEED_100 ||
line_speed == SPEED_1000 ||
@@ -1300,8 +1300,8 @@ static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u32 *ieee_fc)
* Please refer to Table 28B-3 of the 802.3ab-1999 spec */
switch (params->req_flow_ctrl) {
- case FLOW_CTRL_AUTO:
- if (params->req_fc_auto_adv == FLOW_CTRL_BOTH) {
+ case BNX2X_FLOW_CTRL_AUTO:
+ if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH) {
*ieee_fc |=
MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
} else {
@@ -1309,17 +1309,17 @@ static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u32 *ieee_fc)
MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
}
break;
- case FLOW_CTRL_TX:
+ case BNX2X_FLOW_CTRL_TX:
*ieee_fc |=
MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
break;
- case FLOW_CTRL_RX:
- case FLOW_CTRL_BOTH:
+ case BNX2X_FLOW_CTRL_RX:
+ case BNX2X_FLOW_CTRL_BOTH:
*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
break;
- case FLOW_CTRL_NONE:
+ case BNX2X_FLOW_CTRL_NONE:
default:
*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_NONE;
break;
@@ -1463,18 +1463,18 @@ static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
{ /* LD LP */
switch (pause_result) { /* ASYM P ASYM P */
case 0xb: /* 1 0 1 1 */
- vars->flow_ctrl = FLOW_CTRL_TX;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_TX;
break;
case 0xe: /* 1 1 1 0 */
- vars->flow_ctrl = FLOW_CTRL_RX;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_RX;
break;
case 0x5: /* 0 1 0 1 */
case 0x7: /* 0 1 1 1 */
case 0xd: /* 1 1 0 1 */
case 0xf: /* 1 1 1 1 */
- vars->flow_ctrl = FLOW_CTRL_BOTH;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
break;
default:
@@ -1531,7 +1531,7 @@ static u8 bnx2x_ext_phy_resove_fc(struct link_params *params,
DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x \n",
pause_result);
bnx2x_pause_resolve(vars, pause_result);
- if (vars->flow_ctrl == FLOW_CTRL_NONE &&
+ if (vars->flow_ctrl == BNX2X_FLOW_CTRL_NONE &&
ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
bnx2x_cl45_read(bp, port,
ext_phy_type,
@@ -1567,10 +1567,10 @@ static void bnx2x_flow_ctrl_resolve(struct link_params *params,
u16 lp_pause; /* link partner */
u16 pause_result;
- vars->flow_ctrl = FLOW_CTRL_NONE;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
/* resolve from gp_status in case of AN complete and not sgmii */
- if ((params->req_flow_ctrl == FLOW_CTRL_AUTO) &&
+ if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
(gp_status & MDIO_AN_CL73_OR_37_COMPLETE) &&
(!(vars->phy_flags & PHY_SGMII_FLAG)) &&
(XGXS_EXT_PHY_TYPE(params->ext_phy_config) ==
@@ -1591,11 +1591,11 @@ static void bnx2x_flow_ctrl_resolve(struct link_params *params,
MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
DP(NETIF_MSG_LINK, "pause_result 0x%x\n", pause_result);
bnx2x_pause_resolve(vars, pause_result);
- } else if ((params->req_flow_ctrl == FLOW_CTRL_AUTO) &&
+ } else if ((params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
(bnx2x_ext_phy_resove_fc(params, vars))) {
return;
} else {
- if (params->req_flow_ctrl == FLOW_CTRL_AUTO)
+ if (params->req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO)
vars->flow_ctrl = params->req_fc_auto_adv;
else
vars->flow_ctrl = params->req_flow_ctrl;
@@ -1728,11 +1728,11 @@ static u8 bnx2x_link_settings_status(struct link_params *params,
LINK_STATUS_PARALLEL_DETECTION_USED;
}
- if (vars->flow_ctrl & FLOW_CTRL_TX)
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX)
vars->link_status |=
LINK_STATUS_TX_FLOW_CONTROL_ENABLED;
- if (vars->flow_ctrl & FLOW_CTRL_RX)
+ if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX)
vars->link_status |=
LINK_STATUS_RX_FLOW_CONTROL_ENABLED;
@@ -1742,7 +1742,7 @@ static u8 bnx2x_link_settings_status(struct link_params *params,
vars->phy_link_up = 0;
vars->duplex = DUPLEX_FULL;
- vars->flow_ctrl = FLOW_CTRL_NONE;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
vars->autoneg = AUTO_NEG_DISABLED;
vars->mac_type = MAC_TYPE_NONE;
}
@@ -3924,7 +3924,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
vars->link_up = 0;
vars->line_speed = 0;
vars->duplex = DUPLEX_FULL;
- vars->flow_ctrl = FLOW_CTRL_NONE;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
vars->mac_type = MAC_TYPE_NONE;
if (params->switch_cfg == SWITCH_CFG_1G)
@@ -3946,12 +3946,12 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
vars->link_up = 1;
vars->line_speed = SPEED_10000;
vars->duplex = DUPLEX_FULL;
- vars->flow_ctrl = FLOW_CTRL_NONE;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD);
/* enable on E1.5 FPGA */
if (CHIP_IS_E1H(bp)) {
vars->flow_ctrl |=
- (FLOW_CTRL_TX | FLOW_CTRL_RX);
+ (BNX2X_FLOW_CTRL_TX | BNX2X_FLOW_CTRL_RX);
vars->link_status |=
(LINK_STATUS_TX_FLOW_CONTROL_ENABLED |
LINK_STATUS_RX_FLOW_CONTROL_ENABLED);
@@ -3974,7 +3974,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
vars->link_up = 1;
vars->line_speed = SPEED_10000;
vars->duplex = DUPLEX_FULL;
- vars->flow_ctrl = FLOW_CTRL_NONE;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD);
bnx2x_bmac_enable(params, vars, 0);
@@ -3994,7 +3994,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
vars->link_up = 1;
vars->line_speed = SPEED_10000;
vars->duplex = DUPLEX_FULL;
- vars->flow_ctrl = FLOW_CTRL_NONE;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
vars->mac_type = MAC_TYPE_BMAC;
vars->phy_flags = PHY_XGXS_FLAG;
@@ -4009,7 +4009,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
vars->link_up = 1;
vars->line_speed = SPEED_1000;
vars->duplex = DUPLEX_FULL;
- vars->flow_ctrl = FLOW_CTRL_NONE;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
vars->mac_type = MAC_TYPE_EMAC;
vars->phy_flags = PHY_XGXS_FLAG;
@@ -4026,7 +4026,7 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
vars->link_up = 1;
vars->line_speed = SPEED_10000;
vars->duplex = DUPLEX_FULL;
- vars->flow_ctrl = FLOW_CTRL_NONE;
+ vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
vars->phy_flags = PHY_XGXS_FLAG;
diff --git a/drivers/net/bnx2x_link.h b/drivers/net/bnx2x_link.h
index 86d54a17b411..47cb585f4278 100644
--- a/drivers/net/bnx2x_link.h
+++ b/drivers/net/bnx2x_link.h
@@ -26,11 +26,11 @@
-#define FLOW_CTRL_AUTO PORT_FEATURE_FLOW_CONTROL_AUTO
-#define FLOW_CTRL_TX PORT_FEATURE_FLOW_CONTROL_TX
-#define FLOW_CTRL_RX PORT_FEATURE_FLOW_CONTROL_RX
-#define FLOW_CTRL_BOTH PORT_FEATURE_FLOW_CONTROL_BOTH
-#define FLOW_CTRL_NONE PORT_FEATURE_FLOW_CONTROL_NONE
+#define BNX2X_FLOW_CTRL_AUTO PORT_FEATURE_FLOW_CONTROL_AUTO
+#define BNX2X_FLOW_CTRL_TX PORT_FEATURE_FLOW_CONTROL_TX
+#define BNX2X_FLOW_CTRL_RX PORT_FEATURE_FLOW_CONTROL_RX
+#define BNX2X_FLOW_CTRL_BOTH PORT_FEATURE_FLOW_CONTROL_BOTH
+#define BNX2X_FLOW_CTRL_NONE PORT_FEATURE_FLOW_CONTROL_NONE
#define SPEED_AUTO_NEG 0
#define SPEED_12000 12000
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c
index 600210d7eff9..ef8103b3523e 100644
--- a/drivers/net/bnx2x_main.c
+++ b/drivers/net/bnx2x_main.c
@@ -1328,7 +1328,6 @@ static void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp,
dev_kfree_skb(skb);
}
- bp->dev->last_rx = jiffies;
/* put new skb in bin */
fp->tpa_pool[queue].skb = new_skb;
@@ -1557,7 +1556,6 @@ reuse_rx:
#endif
netif_receive_skb(skb);
- bp->dev->last_rx = jiffies;
next_rx:
rx_buf->skb = NULL;
@@ -1594,7 +1592,6 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie)
{
struct bnx2x_fastpath *fp = fp_cookie;
struct bnx2x *bp = fp->bp;
- struct net_device *dev = bp->dev;
int index = FP_IDX(fp);
/* Return here if interrupt is disabled */
@@ -1617,7 +1614,7 @@ static irqreturn_t bnx2x_msix_fp_int(int irq, void *fp_cookie)
prefetch(&fp->status_blk->c_status_block.status_block_index);
prefetch(&fp->status_blk->u_status_block.status_block_index);
- netif_rx_schedule(dev, &bnx2x_fp(bp, index, napi));
+ netif_rx_schedule(&bnx2x_fp(bp, index, napi));
return IRQ_HANDLED;
}
@@ -1656,7 +1653,7 @@ static irqreturn_t bnx2x_interrupt(int irq, void *dev_instance)
prefetch(&fp->status_blk->c_status_block.status_block_index);
prefetch(&fp->status_blk->u_status_block.status_block_index);
- netif_rx_schedule(dev, &bnx2x_fp(bp, 0, napi));
+ netif_rx_schedule(&bnx2x_fp(bp, 0, napi));
status &= ~mask;
}
@@ -1923,10 +1920,10 @@ static void bnx2x_link_report(struct bnx2x *bp)
else
printk("half duplex");
- if (bp->link_vars.flow_ctrl != FLOW_CTRL_NONE) {
- if (bp->link_vars.flow_ctrl & FLOW_CTRL_RX) {
+ if (bp->link_vars.flow_ctrl != BNX2X_FLOW_CTRL_NONE) {
+ if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) {
printk(", receive ");
- if (bp->link_vars.flow_ctrl & FLOW_CTRL_TX)
+ if (bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX)
printk("& transmit ");
} else {
printk(", transmit ");
@@ -1950,11 +1947,11 @@ static u8 bnx2x_initial_phy_init(struct bnx2x *bp)
/* It is recommended to turn off RX FC for jumbo frames
for better performance */
if (IS_E1HMF(bp))
- bp->link_params.req_fc_auto_adv = FLOW_CTRL_BOTH;
+ bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_BOTH;
else if (bp->dev->mtu > 5000)
- bp->link_params.req_fc_auto_adv = FLOW_CTRL_TX;
+ bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_TX;
else
- bp->link_params.req_fc_auto_adv = FLOW_CTRL_BOTH;
+ bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_BOTH;
bnx2x_acquire_phy_lock(bp);
rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars);
@@ -7364,9 +7361,9 @@ static void __devinit bnx2x_link_settings_requested(struct bnx2x *bp)
bp->link_params.req_flow_ctrl = (bp->port.link_config &
PORT_FEATURE_FLOW_CONTROL_MASK);
- if ((bp->link_params.req_flow_ctrl == FLOW_CTRL_AUTO) &&
+ if ((bp->link_params.req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
!(bp->port.supported & SUPPORTED_Autoneg))
- bp->link_params.req_flow_ctrl = FLOW_CTRL_NONE;
+ bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_NONE;
BNX2X_DEV_INFO("req_line_speed %d req_duplex %d req_flow_ctrl 0x%x"
" advertising 0x%x\n",
@@ -8355,13 +8352,13 @@ static void bnx2x_get_pauseparam(struct net_device *dev,
{
struct bnx2x *bp = netdev_priv(dev);
- epause->autoneg = (bp->link_params.req_flow_ctrl == FLOW_CTRL_AUTO) &&
+ epause->autoneg = (bp->link_params.req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO) &&
(bp->link_params.req_line_speed == SPEED_AUTO_NEG);
- epause->rx_pause = ((bp->link_vars.flow_ctrl & FLOW_CTRL_RX) ==
- FLOW_CTRL_RX);
- epause->tx_pause = ((bp->link_vars.flow_ctrl & FLOW_CTRL_TX) ==
- FLOW_CTRL_TX);
+ epause->rx_pause = ((bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_RX) ==
+ BNX2X_FLOW_CTRL_RX);
+ epause->tx_pause = ((bp->link_vars.flow_ctrl & BNX2X_FLOW_CTRL_TX) ==
+ BNX2X_FLOW_CTRL_TX);
DP(NETIF_MSG_LINK, "ethtool_pauseparam: cmd %d\n"
DP_LEVEL " autoneg %d rx_pause %d tx_pause %d\n",
@@ -8380,16 +8377,16 @@ static int bnx2x_set_pauseparam(struct net_device *dev,
DP_LEVEL " autoneg %d rx_pause %d tx_pause %d\n",
epause->cmd, epause->autoneg, epause->rx_pause, epause->tx_pause);
- bp->link_params.req_flow_ctrl = FLOW_CTRL_AUTO;
+ bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO;
if (epause->rx_pause)
- bp->link_params.req_flow_ctrl |= FLOW_CTRL_RX;
+ bp->link_params.req_flow_ctrl |= BNX2X_FLOW_CTRL_RX;
if (epause->tx_pause)
- bp->link_params.req_flow_ctrl |= FLOW_CTRL_TX;
+ bp->link_params.req_flow_ctrl |= BNX2X_FLOW_CTRL_TX;
- if (bp->link_params.req_flow_ctrl == FLOW_CTRL_AUTO)
- bp->link_params.req_flow_ctrl = FLOW_CTRL_NONE;
+ if (bp->link_params.req_flow_ctrl == BNX2X_FLOW_CTRL_AUTO)
+ bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_NONE;
if (epause->autoneg) {
if (!(bp->port.supported & SUPPORTED_Autoneg)) {
@@ -8398,7 +8395,7 @@ static int bnx2x_set_pauseparam(struct net_device *dev,
}
if (bp->link_params.req_line_speed == SPEED_AUTO_NEG)
- bp->link_params.req_flow_ctrl = FLOW_CTRL_AUTO;
+ bp->link_params.req_flow_ctrl = BNX2X_FLOW_CTRL_AUTO;
}
DP(NETIF_MSG_LINK,
@@ -8769,7 +8766,6 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up)
rc = 0;
test_loopback_rx_exit:
- bp->dev->last_rx = jiffies;
fp->rx_bd_cons = NEXT_RX_IDX(fp->rx_bd_cons);
fp->rx_bd_prod = NEXT_RX_IDX(fp->rx_bd_prod);
@@ -9287,7 +9283,7 @@ static int bnx2x_poll(struct napi_struct *napi, int budget)
#ifdef BNX2X_STOP_ON_ERROR
poll_panic:
#endif
- netif_rx_complete(bp->dev, napi);
+ netif_rx_complete(napi);
bnx2x_ack_sb(bp, FP_SB_ID(fp), USTORM_ID,
le16_to_cpu(fp->fp_u_idx), IGU_INT_NOP, 1);
@@ -9853,11 +9849,8 @@ static void bnx2x_set_rx_mode(struct net_device *dev)
mclist && (i < dev->mc_count);
i++, mclist = mclist->next) {
- DP(NETIF_MSG_IFUP, "Adding mcast MAC: "
- "%02x:%02x:%02x:%02x:%02x:%02x\n",
- mclist->dmi_addr[0], mclist->dmi_addr[1],
- mclist->dmi_addr[2], mclist->dmi_addr[3],
- mclist->dmi_addr[4], mclist->dmi_addr[5]);
+ DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n",
+ mclist->dmi_addr);
crc = crc32c_le(0, mclist->dmi_addr, ETH_ALEN);
bit = (crc >> 24) & 0xff;
@@ -10008,6 +10001,25 @@ static void poll_bnx2x(struct net_device *dev)
}
#endif
+static const struct net_device_ops bnx2x_netdev_ops = {
+ .ndo_open = bnx2x_open,
+ .ndo_stop = bnx2x_close,
+ .ndo_start_xmit = bnx2x_start_xmit,
+ .ndo_set_multicast_list = bnx2x_set_rx_mode,
+ .ndo_set_mac_address = bnx2x_change_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_do_ioctl = bnx2x_ioctl,
+ .ndo_change_mtu = bnx2x_change_mtu,
+ .ndo_tx_timeout = bnx2x_tx_timeout,
+#ifdef BCM_VLAN
+ .ndo_vlan_rx_register = bnx2x_vlan_rx_register,
+#endif
+#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
+ .ndo_poll_controller = poll_bnx2x,
+#endif
+};
+
+
static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
struct net_device *dev)
{
@@ -10092,8 +10104,7 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
dev->irq = pdev->irq;
- bp->regview = ioremap_nocache(dev->base_addr,
- pci_resource_len(pdev, 0));
+ bp->regview = pci_ioremap_bar(pdev, 0);
if (!bp->regview) {
printk(KERN_ERR PFX "Cannot map register space, aborting\n");
rc = -ENOMEM;
@@ -10119,23 +10130,10 @@ static int __devinit bnx2x_init_dev(struct pci_dev *pdev,
REG_WR(bp, PXP2_REG_PGL_ADDR_90_F0 + BP_PORT(bp)*16, 0);
REG_WR(bp, PXP2_REG_PGL_ADDR_94_F0 + BP_PORT(bp)*16, 0);
- dev->hard_start_xmit = bnx2x_start_xmit;
dev->watchdog_timeo = TX_TIMEOUT;
+ dev->netdev_ops = &bnx2x_netdev_ops;
dev->ethtool_ops = &bnx2x_ethtool_ops;
- dev->open = bnx2x_open;
- dev->stop = bnx2x_close;
- dev->set_multicast_list = bnx2x_set_rx_mode;
- dev->set_mac_address = bnx2x_change_mac_addr;
- dev->do_ioctl = bnx2x_ioctl;
- dev->change_mtu = bnx2x_change_mtu;
- dev->tx_timeout = bnx2x_tx_timeout;
-#ifdef BCM_VLAN
- dev->vlan_rx_register = bnx2x_vlan_rx_register;
-#endif
-#if defined(HAVE_POLL_CONTROLLER) || defined(CONFIG_NET_POLL_CONTROLLER)
- dev->poll_controller = poll_bnx2x;
-#endif
dev->features |= NETIF_F_SG;
dev->features |= NETIF_F_HW_CSUM;
if (bp->flags & USING_DAC_FLAG)
@@ -10194,7 +10192,6 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
struct net_device *dev = NULL;
struct bnx2x *bp;
int rc;
- DECLARE_MAC_BUF(mac);
if (version_printed++ == 0)
printk(KERN_INFO "%s", version);
@@ -10238,7 +10235,7 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
bnx2x_get_pcie_width(bp),
(bnx2x_get_pcie_speed(bp) == 2) ? "5GHz (Gen2)" : "2.5GHz",
dev->base_addr, bp->pdev->irq);
- printk(KERN_CONT "node addr %s\n", print_mac(mac, dev->dev_addr));
+ printk(KERN_CONT "node addr %pM\n", dev->dev_addr);
return 0;
init_one_exit:
diff --git a/drivers/net/bonding/Makefile b/drivers/net/bonding/Makefile
index 5cdae2bc055a..6f9c6faef24c 100644
--- a/drivers/net/bonding/Makefile
+++ b/drivers/net/bonding/Makefile
@@ -6,3 +6,6 @@ obj-$(CONFIG_BONDING) += bonding.o
bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o
+ipv6-$(subst m,y,$(CONFIG_IPV6)) += bond_ipv6.o
+bonding-objs += $(ipv6-y)
+
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
index 6106660a4a44..8c2e5ab51f08 100644
--- a/drivers/net/bonding/bond_3ad.c
+++ b/drivers/net/bonding/bond_3ad.c
@@ -20,13 +20,12 @@
*
*/
-//#define BONDING_DEBUG 1
-
#include <linux/skbuff.h>
#include <linux/if_ether.h>
#include <linux/netdevice.h>
#include <linux/spinlock.h>
#include <linux/ethtool.h>
+#include <linux/etherdevice.h>
#include <linux/if_bonding.h>
#include <linux/pkt_sched.h>
#include <net/net_namespace.h>
@@ -96,33 +95,7 @@ static struct mac_addr null_mac_addr = {{0, 0, 0, 0, 0, 0}};
static u16 ad_ticks_per_sec;
static const int ad_delta_in_ticks = (AD_TIMER_INTERVAL * HZ) / 1000;
-// ================= 3AD api to bonding and kernel code ==================
-static u16 __get_link_speed(struct port *port);
-static u8 __get_duplex(struct port *port);
-static inline void __initialize_port_locks(struct port *port);
-//conversions
-static u16 __ad_timer_to_ticks(u16 timer_type, u16 Par);
-
-
-// ================= ad code helper functions ==================
-//needed by ad_rx_machine(...)
-static void __record_pdu(struct lacpdu *lacpdu, struct port *port);
-static void __record_default(struct port *port);
-static void __update_selected(struct lacpdu *lacpdu, struct port *port);
-static void __update_default_selected(struct port *port);
-static void __choose_matched(struct lacpdu *lacpdu, struct port *port);
-static void __update_ntt(struct lacpdu *lacpdu, struct port *port);
-
-//needed for ad_mux_machine(..)
-static void __attach_bond_to_agg(struct port *port);
-static void __detach_bond_from_agg(struct port *port);
-static int __agg_ports_are_ready(struct aggregator *aggregator);
-static void __set_agg_ports_ready(struct aggregator *aggregator, int val);
-
-//needed for ad_agg_selection_logic(...)
-static u32 __get_agg_bandwidth(struct aggregator *aggregator);
-static struct aggregator *__get_active_agg(struct aggregator *aggregator);
-
+static const u8 lacpdu_mcast_addr[ETH_ALEN] = MULTICAST_LACPDU_ADDR;
// ================= main 802.3ad protocol functions ==================
static int ad_lacpdu_send(struct port *port);
@@ -136,7 +109,6 @@ static void ad_agg_selection_logic(struct aggregator *aggregator);
static void ad_clear_agg(struct aggregator *aggregator);
static void ad_initialize_agg(struct aggregator *aggregator);
static void ad_initialize_port(struct port *port, int lacp_fast);
-static void ad_initialize_lacpdu(struct lacpdu *Lacpdu);
static void ad_enable_collecting_distributing(struct port *port);
static void ad_disable_collecting_distributing(struct port *port);
static void ad_marker_info_received(struct bond_marker *marker_info, struct port *port);
@@ -236,6 +208,17 @@ static inline struct aggregator *__get_next_agg(struct aggregator *aggregator)
return &(SLAVE_AD_INFO(slave->next).aggregator);
}
+/*
+ * __agg_has_partner
+ *
+ * Return nonzero if aggregator has a partner (denoted by a non-zero ether
+ * address for the partner). Return 0 if not.
+ */
+static inline int __agg_has_partner(struct aggregator *agg)
+{
+ return !is_zero_ether_addr(agg->partner_system.mac_addr_value);
+}
+
/**
* __disable_port - disable the port's slave
* @port: the port we're looking at
@@ -274,14 +257,14 @@ static inline int __port_is_enabled(struct port *port)
* __get_agg_selection_mode - get the aggregator selection mode
* @port: the port we're looking at
*
- * Get the aggregator selection mode. Can be %BANDWIDTH or %COUNT.
+ * Get the aggregator selection mode. Can be %STABLE, %BANDWIDTH or %COUNT.
*/
static inline u32 __get_agg_selection_mode(struct port *port)
{
struct bonding *bond = __get_bond_by_port(port);
if (bond == NULL) {
- return AD_BANDWIDTH;
+ return BOND_AD_STABLE;
}
return BOND_AD_INFO(bond).agg_select_mode;
@@ -369,7 +352,7 @@ static u16 __get_link_speed(struct port *port)
}
}
- dprintk("Port %d Received link speed %d update from adapter\n", port->actor_port_number, speed);
+ pr_debug("Port %d Received link speed %d update from adapter\n", port->actor_port_number, speed);
return speed;
}
@@ -395,12 +378,12 @@ static u8 __get_duplex(struct port *port)
switch (slave->duplex) {
case DUPLEX_FULL:
retval=0x1;
- dprintk("Port %d Received status full duplex update from adapter\n", port->actor_port_number);
+ pr_debug("Port %d Received status full duplex update from adapter\n", port->actor_port_number);
break;
case DUPLEX_HALF:
default:
retval=0x0;
- dprintk("Port %d Received status NOT full duplex update from adapter\n", port->actor_port_number);
+ pr_debug("Port %d Received status NOT full duplex update from adapter\n", port->actor_port_number);
break;
}
}
@@ -473,33 +456,25 @@ static u16 __ad_timer_to_ticks(u16 timer_type, u16 par)
*/
static void __record_pdu(struct lacpdu *lacpdu, struct port *port)
{
- // validate lacpdu and port
if (lacpdu && port) {
+ struct port_params *partner = &port->partner_oper;
+
// record the new parameter values for the partner operational
- port->partner_oper_port_number = ntohs(lacpdu->actor_port);
- port->partner_oper_port_priority = ntohs(lacpdu->actor_port_priority);
- port->partner_oper_system = lacpdu->actor_system;
- port->partner_oper_system_priority = ntohs(lacpdu->actor_system_priority);
- port->partner_oper_key = ntohs(lacpdu->actor_key);
- // zero partener's lase states
- port->partner_oper_port_state = 0;
- port->partner_oper_port_state |= (lacpdu->actor_state & AD_STATE_LACP_ACTIVITY);
- port->partner_oper_port_state |= (lacpdu->actor_state & AD_STATE_LACP_TIMEOUT);
- port->partner_oper_port_state |= (lacpdu->actor_state & AD_STATE_AGGREGATION);
- port->partner_oper_port_state |= (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION);
- port->partner_oper_port_state |= (lacpdu->actor_state & AD_STATE_COLLECTING);
- port->partner_oper_port_state |= (lacpdu->actor_state & AD_STATE_DISTRIBUTING);
- port->partner_oper_port_state |= (lacpdu->actor_state & AD_STATE_DEFAULTED);
- port->partner_oper_port_state |= (lacpdu->actor_state & AD_STATE_EXPIRED);
+ partner->port_number = ntohs(lacpdu->actor_port);
+ partner->port_priority = ntohs(lacpdu->actor_port_priority);
+ partner->system = lacpdu->actor_system;
+ partner->system_priority = ntohs(lacpdu->actor_system_priority);
+ partner->key = ntohs(lacpdu->actor_key);
+ partner->port_state = lacpdu->actor_state;
// set actor_oper_port_state.defaulted to FALSE
port->actor_oper_port_state &= ~AD_STATE_DEFAULTED;
// set the partner sync. to on if the partner is sync. and the port is matched
if ((port->sm_vars & AD_PORT_MATCHED) && (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION)) {
- port->partner_oper_port_state |= AD_STATE_SYNCHRONIZATION;
+ partner->port_state |= AD_STATE_SYNCHRONIZATION;
} else {
- port->partner_oper_port_state &= ~AD_STATE_SYNCHRONIZATION;
+ partner->port_state &= ~AD_STATE_SYNCHRONIZATION;
}
}
}
@@ -514,15 +489,10 @@ static void __record_pdu(struct lacpdu *lacpdu, struct port *port)
*/
static void __record_default(struct port *port)
{
- // validate the port
if (port) {
// record the partner admin parameters
- port->partner_oper_port_number = port->partner_admin_port_number;
- port->partner_oper_port_priority = port->partner_admin_port_priority;
- port->partner_oper_system = port->partner_admin_system;
- port->partner_oper_system_priority = port->partner_admin_system_priority;
- port->partner_oper_key = port->partner_admin_key;
- port->partner_oper_port_state = port->partner_admin_port_state;
+ memcpy(&port->partner_oper, &port->partner_admin,
+ sizeof(struct port_params));
// set actor_oper_port_state.defaulted to true
port->actor_oper_port_state |= AD_STATE_DEFAULTED;
@@ -544,16 +514,16 @@ static void __record_default(struct port *port)
*/
static void __update_selected(struct lacpdu *lacpdu, struct port *port)
{
- // validate lacpdu and port
if (lacpdu && port) {
+ const struct port_params *partner = &port->partner_oper;
+
// check if any parameter is different
- if ((ntohs(lacpdu->actor_port) != port->partner_oper_port_number) ||
- (ntohs(lacpdu->actor_port_priority) != port->partner_oper_port_priority) ||
- MAC_ADDRESS_COMPARE(&(lacpdu->actor_system), &(port->partner_oper_system)) ||
- (ntohs(lacpdu->actor_system_priority) != port->partner_oper_system_priority) ||
- (ntohs(lacpdu->actor_key) != port->partner_oper_key) ||
- ((lacpdu->actor_state & AD_STATE_AGGREGATION) != (port->partner_oper_port_state & AD_STATE_AGGREGATION))
- ) {
+ if (ntohs(lacpdu->actor_port) != partner->port_number
+ || ntohs(lacpdu->actor_port_priority) != partner->port_priority
+ || MAC_ADDRESS_COMPARE(&lacpdu->actor_system, &partner->system)
+ || ntohs(lacpdu->actor_system_priority) != partner->system_priority
+ || ntohs(lacpdu->actor_key) != partner->key
+ || (lacpdu->actor_state & AD_STATE_AGGREGATION) != (partner->port_state & AD_STATE_AGGREGATION)) {
// update the state machine Selected variable
port->sm_vars &= ~AD_PORT_SELECTED;
}
@@ -574,16 +544,18 @@ static void __update_selected(struct lacpdu *lacpdu, struct port *port)
*/
static void __update_default_selected(struct port *port)
{
- // validate the port
if (port) {
+ const struct port_params *admin = &port->partner_admin;
+ const struct port_params *oper = &port->partner_oper;
+
// check if any parameter is different
- if ((port->partner_admin_port_number != port->partner_oper_port_number) ||
- (port->partner_admin_port_priority != port->partner_oper_port_priority) ||
- MAC_ADDRESS_COMPARE(&(port->partner_admin_system), &(port->partner_oper_system)) ||
- (port->partner_admin_system_priority != port->partner_oper_system_priority) ||
- (port->partner_admin_key != port->partner_oper_key) ||
- ((port->partner_admin_port_state & AD_STATE_AGGREGATION) != (port->partner_oper_port_state & AD_STATE_AGGREGATION))
- ) {
+ if (admin->port_number != oper->port_number
+ || admin->port_priority != oper->port_priority
+ || MAC_ADDRESS_COMPARE(&admin->system, &oper->system)
+ || admin->system_priority != oper->system_priority
+ || admin->key != oper->key
+ || (admin->port_state & AD_STATE_AGGREGATION)
+ != (oper->port_state & AD_STATE_AGGREGATION)) {
// update the state machine Selected variable
port->sm_vars &= ~AD_PORT_SELECTED;
}
@@ -658,8 +630,8 @@ static void __update_ntt(struct lacpdu *lacpdu, struct port *port)
((lacpdu->partner_state & AD_STATE_SYNCHRONIZATION) != (port->actor_oper_port_state & AD_STATE_SYNCHRONIZATION)) ||
((lacpdu->partner_state & AD_STATE_AGGREGATION) != (port->actor_oper_port_state & AD_STATE_AGGREGATION))
) {
- // set ntt to be TRUE
- port->ntt = 1;
+
+ port->ntt = true;
}
}
}
@@ -798,6 +770,7 @@ static struct aggregator *__get_active_agg(struct aggregator *aggregator)
static inline void __update_lacpdu_from_port(struct port *port)
{
struct lacpdu *lacpdu = &port->lacpdu;
+ const struct port_params *partner = &port->partner_oper;
/* update current actual Actor parameters */
/* lacpdu->subtype initialized
@@ -818,12 +791,12 @@ static inline void __update_lacpdu_from_port(struct port *port)
* lacpdu->partner_information_length initialized
*/
- lacpdu->partner_system_priority = htons(port->partner_oper_system_priority);
- lacpdu->partner_system = port->partner_oper_system;
- lacpdu->partner_key = htons(port->partner_oper_key);
- lacpdu->partner_port_priority = htons(port->partner_oper_port_priority);
- lacpdu->partner_port = htons(port->partner_oper_port_number);
- lacpdu->partner_state = port->partner_oper_port_state;
+ lacpdu->partner_system_priority = htons(partner->system_priority);
+ lacpdu->partner_system = partner->system;
+ lacpdu->partner_key = htons(partner->key);
+ lacpdu->partner_port_priority = htons(partner->port_priority);
+ lacpdu->partner_port = htons(partner->port_number);
+ lacpdu->partner_state = partner->port_state;
/* lacpdu->reserved_3_2 initialized
* lacpdu->tlv_type_collector_info initialized
@@ -853,7 +826,6 @@ static int ad_lacpdu_send(struct port *port)
struct sk_buff *skb;
struct lacpdu_header *lacpdu_header;
int length = sizeof(struct lacpdu_header);
- struct mac_addr lacpdu_multicast_address = AD_MULTICAST_LACPDU_ADDR;
skb = dev_alloc_skb(length);
if (!skb) {
@@ -868,11 +840,11 @@ static int ad_lacpdu_send(struct port *port)
lacpdu_header = (struct lacpdu_header *)skb_put(skb, length);
- lacpdu_header->ad_header.destination_address = lacpdu_multicast_address;
- /* Note: source addres is set to be the member's PERMANENT address, because we use it
- to identify loopback lacpdus in receive. */
- lacpdu_header->ad_header.source_address = *((struct mac_addr *)(slave->perm_hwaddr));
- lacpdu_header->ad_header.length_type = PKT_TYPE_LACPDU;
+ memcpy(lacpdu_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN);
+ /* Note: source addres is set to be the member's PERMANENT address,
+ because we use it to identify loopback lacpdus in receive. */
+ memcpy(lacpdu_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN);
+ lacpdu_header->hdr.h_proto = PKT_TYPE_LACPDU;
lacpdu_header->lacpdu = port->lacpdu; // struct copy
@@ -895,7 +867,6 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker)
struct sk_buff *skb;
struct bond_marker_header *marker_header;
int length = sizeof(struct bond_marker_header);
- struct mac_addr lacpdu_multicast_address = AD_MULTICAST_LACPDU_ADDR;
skb = dev_alloc_skb(length + 16);
if (!skb) {
@@ -911,11 +882,11 @@ static int ad_marker_send(struct port *port, struct bond_marker *marker)
marker_header = (struct bond_marker_header *)skb_put(skb, length);
- marker_header->ad_header.destination_address = lacpdu_multicast_address;
- /* Note: source addres is set to be the member's PERMANENT address, because we use it
- to identify loopback MARKERs in receive. */
- marker_header->ad_header.source_address = *((struct mac_addr *)(slave->perm_hwaddr));
- marker_header->ad_header.length_type = PKT_TYPE_LACPDU;
+ memcpy(marker_header->hdr.h_dest, lacpdu_mcast_addr, ETH_ALEN);
+ /* Note: source addres is set to be the member's PERMANENT address,
+ because we use it to identify loopback MARKERs in receive. */
+ memcpy(marker_header->hdr.h_source, slave->perm_hwaddr, ETH_ALEN);
+ marker_header->hdr.h_proto = PKT_TYPE_LACPDU;
marker_header->marker = *marker; // struct copy
@@ -972,7 +943,7 @@ static void ad_mux_machine(struct port *port)
break;
case AD_MUX_ATTACHED:
// check also if agg_select_timer expired(so the edable port will take place only after this timer)
- if ((port->sm_vars & AD_PORT_SELECTED) && (port->partner_oper_port_state & AD_STATE_SYNCHRONIZATION) && !__check_agg_selection_timer(port)) {
+ if ((port->sm_vars & AD_PORT_SELECTED) && (port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION) && !__check_agg_selection_timer(port)) {
port->sm_mux_state = AD_MUX_COLLECTING_DISTRIBUTING;// next state
} else if (!(port->sm_vars & AD_PORT_SELECTED) || (port->sm_vars & AD_PORT_STANDBY)) { // if UNSELECTED or STANDBY
port->sm_vars &= ~AD_PORT_READY_N;
@@ -984,7 +955,7 @@ static void ad_mux_machine(struct port *port)
break;
case AD_MUX_COLLECTING_DISTRIBUTING:
if (!(port->sm_vars & AD_PORT_SELECTED) || (port->sm_vars & AD_PORT_STANDBY) ||
- !(port->partner_oper_port_state & AD_STATE_SYNCHRONIZATION)
+ !(port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION)
) {
port->sm_mux_state = AD_MUX_ATTACHED;// next state
@@ -1007,7 +978,7 @@ static void ad_mux_machine(struct port *port)
// check if the state machine was changed
if (port->sm_mux_state != last_state) {
- dprintk("Mux Machine: Port=%d, Last State=%d, Curr State=%d\n", port->actor_port_number, last_state, port->sm_mux_state);
+ pr_debug("Mux Machine: Port=%d, Last State=%d, Curr State=%d\n", port->actor_port_number, last_state, port->sm_mux_state);
switch (port->sm_mux_state) {
case AD_MUX_DETACHED:
__detach_bond_from_agg(port);
@@ -1015,7 +986,7 @@ static void ad_mux_machine(struct port *port)
ad_disable_collecting_distributing(port);
port->actor_oper_port_state &= ~AD_STATE_COLLECTING;
port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING;
- port->ntt = 1;
+ port->ntt = true;
break;
case AD_MUX_WAITING:
port->sm_mux_timer_counter = __ad_timer_to_ticks(AD_WAIT_WHILE_TIMER, 0);
@@ -1026,13 +997,13 @@ static void ad_mux_machine(struct port *port)
port->actor_oper_port_state &= ~AD_STATE_COLLECTING;
port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING;
ad_disable_collecting_distributing(port);
- port->ntt = 1;
+ port->ntt = true;
break;
case AD_MUX_COLLECTING_DISTRIBUTING:
port->actor_oper_port_state |= AD_STATE_COLLECTING;
port->actor_oper_port_state |= AD_STATE_DISTRIBUTING;
ad_enable_collecting_distributing(port);
- port->ntt = 1;
+ port->ntt = true;
break;
default: //to silence the compiler
break;
@@ -1106,7 +1077,7 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
// check if the State machine was changed or new lacpdu arrived
if ((port->sm_rx_state != last_state) || (lacpdu)) {
- dprintk("Rx Machine: Port=%d, Last State=%d, Curr State=%d\n", port->actor_port_number, last_state, port->sm_rx_state);
+ pr_debug("Rx Machine: Port=%d, Last State=%d, Curr State=%d\n", port->actor_port_number, last_state, port->sm_rx_state);
switch (port->sm_rx_state) {
case AD_RX_INITIALIZE:
if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_BITS)) {
@@ -1128,7 +1099,7 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
case AD_RX_LACP_DISABLED:
port->sm_vars &= ~AD_PORT_SELECTED;
__record_default(port);
- port->partner_oper_port_state &= ~AD_STATE_AGGREGATION;
+ port->partner_oper.port_state &= ~AD_STATE_AGGREGATION;
port->sm_vars |= AD_PORT_MATCHED;
port->actor_oper_port_state &= ~AD_STATE_EXPIRED;
break;
@@ -1136,9 +1107,9 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port)
//Reset of the Synchronization flag. (Standard 43.4.12)
//This reset cause to disable this port in the COLLECTING_DISTRIBUTING state of the
//mux machine in case of EXPIRED even if LINK_DOWN didn't arrive for the port.
- port->partner_oper_port_state &= ~AD_STATE_SYNCHRONIZATION;
+ port->partner_oper.port_state &= ~AD_STATE_SYNCHRONIZATION;
port->sm_vars &= ~AD_PORT_MATCHED;
- port->partner_oper_port_state |= AD_SHORT_TIMEOUT;
+ port->partner_oper.port_state |= AD_SHORT_TIMEOUT;
port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(AD_SHORT_TIMEOUT));
port->actor_oper_port_state |= AD_STATE_EXPIRED;
break;
@@ -1191,11 +1162,13 @@ static void ad_tx_machine(struct port *port)
// check if there is something to send
if (port->ntt && (port->sm_vars & AD_PORT_LACP_ENABLED)) {
__update_lacpdu_from_port(port);
- // send the lacpdu
+
if (ad_lacpdu_send(port) >= 0) {
- dprintk("Sent LACPDU on port %d\n", port->actor_port_number);
- // mark ntt as false, so it will not be sent again until demanded
- port->ntt = 0;
+ pr_debug("Sent LACPDU on port %d\n", port->actor_port_number);
+
+ /* mark ntt as false, so it will not be sent again until
+ demanded */
+ port->ntt = false;
}
}
// restart tx timer(to verify that we will not exceed AD_MAX_TX_IN_SECOND
@@ -1218,7 +1191,7 @@ static void ad_periodic_machine(struct port *port)
// check if port was reinitialized
if (((port->sm_vars & AD_PORT_BEGIN) || !(port->sm_vars & AD_PORT_LACP_ENABLED) || !port->is_enabled) ||
- (!(port->actor_oper_port_state & AD_STATE_LACP_ACTIVITY) && !(port->partner_oper_port_state & AD_STATE_LACP_ACTIVITY))
+ (!(port->actor_oper_port_state & AD_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & AD_STATE_LACP_ACTIVITY))
) {
port->sm_periodic_state = AD_NO_PERIODIC; // next state
}
@@ -1232,12 +1205,12 @@ static void ad_periodic_machine(struct port *port)
// If not expired, check if there is some new timeout parameter from the partner state
switch (port->sm_periodic_state) {
case AD_FAST_PERIODIC:
- if (!(port->partner_oper_port_state & AD_STATE_LACP_TIMEOUT)) {
+ if (!(port->partner_oper.port_state & AD_STATE_LACP_TIMEOUT)) {
port->sm_periodic_state = AD_SLOW_PERIODIC; // next state
}
break;
case AD_SLOW_PERIODIC:
- if ((port->partner_oper_port_state & AD_STATE_LACP_TIMEOUT)) {
+ if ((port->partner_oper.port_state & AD_STATE_LACP_TIMEOUT)) {
// stop current timer
port->sm_periodic_timer_counter = 0;
port->sm_periodic_state = AD_PERIODIC_TX; // next state
@@ -1253,7 +1226,7 @@ static void ad_periodic_machine(struct port *port)
port->sm_periodic_state = AD_FAST_PERIODIC; // next state
break;
case AD_PERIODIC_TX:
- if (!(port->partner_oper_port_state & AD_STATE_LACP_TIMEOUT)) {
+ if (!(port->partner_oper.port_state & AD_STATE_LACP_TIMEOUT)) {
port->sm_periodic_state = AD_SLOW_PERIODIC; // next state
} else {
port->sm_periodic_state = AD_FAST_PERIODIC; // next state
@@ -1266,7 +1239,7 @@ static void ad_periodic_machine(struct port *port)
// check if the state machine was changed
if (port->sm_periodic_state != last_state) {
- dprintk("Periodic Machine: Port=%d, Last State=%d, Curr State=%d\n", port->actor_port_number, last_state, port->sm_periodic_state);
+ pr_debug("Periodic Machine: Port=%d, Last State=%d, Curr State=%d\n", port->actor_port_number, last_state, port->sm_periodic_state);
switch (port->sm_periodic_state) {
case AD_NO_PERIODIC:
port->sm_periodic_timer_counter = 0; // zero timer
@@ -1278,7 +1251,7 @@ static void ad_periodic_machine(struct port *port)
port->sm_periodic_timer_counter = __ad_timer_to_ticks(AD_PERIODIC_TIMER, (u16)(AD_SLOW_PERIODIC_TIME))-1; // decrement 1 tick we lost in the PERIODIC_TX cycle
break;
case AD_PERIODIC_TX:
- port->ntt = 1;
+ port->ntt = true;
break;
default: //to silence the compiler
break;
@@ -1323,7 +1296,7 @@ static void ad_port_selection_logic(struct port *port)
port->next_port_in_aggregator=NULL;
port->actor_port_aggregator_identifier=0;
- dprintk("Port %d left LAG %d\n", port->actor_port_number, temp_aggregator->aggregator_identifier);
+ pr_debug("Port %d left LAG %d\n", port->actor_port_number, temp_aggregator->aggregator_identifier);
// if the aggregator is empty, clear its parameters, and set it ready to be attached
if (!temp_aggregator->lag_ports) {
ad_clear_agg(temp_aggregator);
@@ -1352,11 +1325,11 @@ static void ad_port_selection_logic(struct port *port)
}
// check if current aggregator suits us
if (((aggregator->actor_oper_aggregator_key == port->actor_oper_port_key) && // if all parameters match AND
- !MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(port->partner_oper_system)) &&
- (aggregator->partner_system_priority == port->partner_oper_system_priority) &&
- (aggregator->partner_oper_aggregator_key == port->partner_oper_key)
+ !MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(port->partner_oper.system)) &&
+ (aggregator->partner_system_priority == port->partner_oper.system_priority) &&
+ (aggregator->partner_oper_aggregator_key == port->partner_oper.key)
) &&
- ((MAC_ADDRESS_COMPARE(&(port->partner_oper_system), &(null_mac_addr)) && // partner answers
+ ((MAC_ADDRESS_COMPARE(&(port->partner_oper.system), &(null_mac_addr)) && // partner answers
!aggregator->is_individual) // but is not individual OR
)
) {
@@ -1366,7 +1339,7 @@ static void ad_port_selection_logic(struct port *port)
port->next_port_in_aggregator=aggregator->lag_ports;
port->aggregator->num_of_ports++;
aggregator->lag_ports=port;
- dprintk("Port %d joined LAG %d(existing LAG)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
+ pr_debug("Port %d joined LAG %d(existing LAG)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
// mark this port as selected
port->sm_vars |= AD_PORT_SELECTED;
@@ -1385,16 +1358,16 @@ static void ad_port_selection_logic(struct port *port)
// update the new aggregator's parameters
// if port was responsed from the end-user
if (port->actor_oper_port_key & AD_DUPLEX_KEY_BITS) {// if port is full duplex
- port->aggregator->is_individual = 0;
+ port->aggregator->is_individual = false;
} else {
- port->aggregator->is_individual = 1;
+ port->aggregator->is_individual = true;
}
port->aggregator->actor_admin_aggregator_key = port->actor_admin_port_key;
port->aggregator->actor_oper_aggregator_key = port->actor_oper_port_key;
- port->aggregator->partner_system=port->partner_oper_system;
- port->aggregator->partner_system_priority = port->partner_oper_system_priority;
- port->aggregator->partner_oper_aggregator_key = port->partner_oper_key;
+ port->aggregator->partner_system=port->partner_oper.system;
+ port->aggregator->partner_system_priority = port->partner_oper.system_priority;
+ port->aggregator->partner_oper_aggregator_key = port->partner_oper.key;
port->aggregator->receive_state = 1;
port->aggregator->transmit_state = 1;
port->aggregator->lag_ports = port;
@@ -1403,7 +1376,7 @@ static void ad_port_selection_logic(struct port *port)
// mark this port as selected
port->sm_vars |= AD_PORT_SELECTED;
- dprintk("Port %d joined LAG %d(new LAG)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
+ pr_debug("Port %d joined LAG %d(new LAG)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
} else {
printk(KERN_ERR DRV_NAME ": %s: Port %d (on %s) did not find a suitable aggregator\n",
port->slave->dev->master->name,
@@ -1414,9 +1387,82 @@ static void ad_port_selection_logic(struct port *port)
// else set ready=FALSE in all aggregator's ports
__set_agg_ports_ready(port->aggregator, __agg_ports_are_ready(port->aggregator));
- if (!__check_agg_selection_timer(port) && (aggregator = __get_first_agg(port))) {
- ad_agg_selection_logic(aggregator);
+ aggregator = __get_first_agg(port);
+ ad_agg_selection_logic(aggregator);
+}
+
+/*
+ * Decide if "agg" is a better choice for the new active aggregator that
+ * the current best, according to the ad_select policy.
+ */
+static struct aggregator *ad_agg_selection_test(struct aggregator *best,
+ struct aggregator *curr)
+{
+ /*
+ * 0. If no best, select current.
+ *
+ * 1. If the current agg is not individual, and the best is
+ * individual, select current.
+ *
+ * 2. If current agg is individual and the best is not, keep best.
+ *
+ * 3. Therefore, current and best are both individual or both not
+ * individual, so:
+ *
+ * 3a. If current agg partner replied, and best agg partner did not,
+ * select current.
+ *
+ * 3b. If current agg partner did not reply and best agg partner
+ * did reply, keep best.
+ *
+ * 4. Therefore, current and best both have partner replies or
+ * both do not, so perform selection policy:
+ *
+ * BOND_AD_COUNT: Select by count of ports. If count is equal,
+ * select by bandwidth.
+ *
+ * BOND_AD_STABLE, BOND_AD_BANDWIDTH: Select by bandwidth.
+ */
+ if (!best)
+ return curr;
+
+ if (!curr->is_individual && best->is_individual)
+ return curr;
+
+ if (curr->is_individual && !best->is_individual)
+ return best;
+
+ if (__agg_has_partner(curr) && !__agg_has_partner(best))
+ return curr;
+
+ if (!__agg_has_partner(curr) && __agg_has_partner(best))
+ return best;
+
+ switch (__get_agg_selection_mode(curr->lag_ports)) {
+ case BOND_AD_COUNT:
+ if (curr->num_of_ports > best->num_of_ports)
+ return curr;
+
+ if (curr->num_of_ports < best->num_of_ports)
+ return best;
+
+ /*FALLTHROUGH*/
+ case BOND_AD_STABLE:
+ case BOND_AD_BANDWIDTH:
+ if (__get_agg_bandwidth(curr) > __get_agg_bandwidth(best))
+ return curr;
+
+ break;
+
+ default:
+ printk(KERN_WARNING DRV_NAME
+ ": %s: Impossible agg select mode %d\n",
+ curr->slave->dev->master->name,
+ __get_agg_selection_mode(curr->lag_ports));
+ break;
}
+
+ return best;
}
/**
@@ -1424,156 +1470,138 @@ static void ad_port_selection_logic(struct port *port)
* @aggregator: the aggregator we're looking at
*
* It is assumed that only one aggregator may be selected for a team.
- * The logic of this function is to select (at first time) the aggregator with
- * the most ports attached to it, and to reselect the active aggregator only if
- * the previous aggregator has no more ports related to it.
+ *
+ * The logic of this function is to select the aggregator according to
+ * the ad_select policy:
+ *
+ * BOND_AD_STABLE: select the aggregator with the most ports attached to
+ * it, and to reselect the active aggregator only if the previous
+ * aggregator has no more ports related to it.
+ *
+ * BOND_AD_BANDWIDTH: select the aggregator with the highest total
+ * bandwidth, and reselect whenever a link state change takes place or the
+ * set of slaves in the bond changes.
+ *
+ * BOND_AD_COUNT: select the aggregator with largest number of ports
+ * (slaves), and reselect whenever a link state change takes place or the
+ * set of slaves in the bond changes.
*
* FIXME: this function MUST be called with the first agg in the bond, or
* __get_active_agg() won't work correctly. This function should be better
* called with the bond itself, and retrieve the first agg from it.
*/
-static void ad_agg_selection_logic(struct aggregator *aggregator)
+static void ad_agg_selection_logic(struct aggregator *agg)
{
- struct aggregator *best_aggregator = NULL, *active_aggregator = NULL;
- struct aggregator *last_active_aggregator = NULL, *origin_aggregator;
+ struct aggregator *best, *active, *origin;
struct port *port;
- u16 num_of_aggs=0;
- origin_aggregator = aggregator;
+ origin = agg;
- //get current active aggregator
- last_active_aggregator = __get_active_agg(aggregator);
+ active = __get_active_agg(agg);
+ best = active;
- // search for the aggregator with the most ports attached to it.
do {
- // count how many candidate lag's we have
- if (aggregator->lag_ports) {
- num_of_aggs++;
- }
- if (aggregator->is_active && !aggregator->is_individual && // if current aggregator is the active aggregator
- MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(null_mac_addr))) { // and partner answers to 802.3ad PDUs
- if (aggregator->num_of_ports) { // if any ports attached to the current aggregator
- best_aggregator=NULL; // disregard the best aggregator that was chosen by now
- break; // stop the selection of other aggregator if there are any ports attached to this active aggregator
- } else { // no ports attached to this active aggregator
- aggregator->is_active = 0; // mark this aggregator as not active anymore
- }
- }
- if (aggregator->num_of_ports) { // if any ports attached
- if (best_aggregator) { // if there is a candidte aggregator
- //The reasons for choosing new best aggregator:
- // 1. if current agg is NOT individual and the best agg chosen so far is individual OR
- // current and best aggs are both individual or both not individual, AND
- // 2a. current agg partner reply but best agg partner do not reply OR
- // 2b. current agg partner reply OR current agg partner do not reply AND best agg partner also do not reply AND
- // current has more ports/bandwidth, or same amount of ports but current has faster ports, THEN
- // current agg become best agg so far
-
- //if current agg is NOT individual and the best agg chosen so far is individual change best_aggregator
- if (!aggregator->is_individual && best_aggregator->is_individual) {
- best_aggregator=aggregator;
- }
- // current and best aggs are both individual or both not individual
- else if ((aggregator->is_individual && best_aggregator->is_individual) ||
- (!aggregator->is_individual && !best_aggregator->is_individual)) {
- // current and best aggs are both individual or both not individual AND
- // current agg partner reply but best agg partner do not reply
- if ((MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(null_mac_addr)) &&
- !MAC_ADDRESS_COMPARE(&(best_aggregator->partner_system), &(null_mac_addr)))) {
- best_aggregator=aggregator;
- }
- // current agg partner reply OR current agg partner do not reply AND best agg partner also do not reply
- else if (! (!MAC_ADDRESS_COMPARE(&(aggregator->partner_system), &(null_mac_addr)) &&
- MAC_ADDRESS_COMPARE(&(best_aggregator->partner_system), &(null_mac_addr)))) {
- if ((__get_agg_selection_mode(aggregator->lag_ports) == AD_BANDWIDTH)&&
- (__get_agg_bandwidth(aggregator) > __get_agg_bandwidth(best_aggregator))) {
- best_aggregator=aggregator;
- } else if (__get_agg_selection_mode(aggregator->lag_ports) == AD_COUNT) {
- if (((aggregator->num_of_ports > best_aggregator->num_of_ports) &&
- (aggregator->actor_oper_aggregator_key & AD_SPEED_KEY_BITS))||
- ((aggregator->num_of_ports == best_aggregator->num_of_ports) &&
- ((u16)(aggregator->actor_oper_aggregator_key & AD_SPEED_KEY_BITS) >
- (u16)(best_aggregator->actor_oper_aggregator_key & AD_SPEED_KEY_BITS)))) {
- best_aggregator=aggregator;
- }
- }
- }
- }
- } else {
- best_aggregator=aggregator;
+ agg->is_active = 0;
+
+ if (agg->num_of_ports)
+ best = ad_agg_selection_test(best, agg);
+
+ } while ((agg = __get_next_agg(agg)));
+
+ if (best &&
+ __get_agg_selection_mode(best->lag_ports) == BOND_AD_STABLE) {
+ /*
+ * For the STABLE policy, don't replace the old active
+ * aggregator if it's still active (it has an answering
+ * partner) or if both the best and active don't have an
+ * answering partner.
+ */
+ if (active && active->lag_ports &&
+ active->lag_ports->is_enabled &&
+ (__agg_has_partner(active) ||
+ (!__agg_has_partner(active) && !__agg_has_partner(best)))) {
+ if (!(!active->actor_oper_aggregator_key &&
+ best->actor_oper_aggregator_key)) {
+ best = NULL;
+ active->is_active = 1;
}
}
- aggregator->is_active = 0; // mark all aggregators as not active anymore
- } while ((aggregator = __get_next_agg(aggregator)));
-
- // if we have new aggregator selected, don't replace the old aggregator if it has an answering partner,
- // or if both old aggregator and new aggregator don't have answering partner
- if (best_aggregator) {
- if (last_active_aggregator && last_active_aggregator->lag_ports && last_active_aggregator->lag_ports->is_enabled &&
- (MAC_ADDRESS_COMPARE(&(last_active_aggregator->partner_system), &(null_mac_addr)) || // partner answers OR
- (!MAC_ADDRESS_COMPARE(&(last_active_aggregator->partner_system), &(null_mac_addr)) && // both old and new
- !MAC_ADDRESS_COMPARE(&(best_aggregator->partner_system), &(null_mac_addr)))) // partner do not answer
- ) {
- // if new aggregator has link, and old aggregator does not, replace old aggregator.(do nothing)
- // -> don't replace otherwise.
- if (!(!last_active_aggregator->actor_oper_aggregator_key && best_aggregator->actor_oper_aggregator_key)) {
- best_aggregator=NULL;
- last_active_aggregator->is_active = 1; // don't replace good old aggregator
+ }
- }
- }
+ if (best && (best == active)) {
+ best = NULL;
+ active->is_active = 1;
}
// if there is new best aggregator, activate it
- if (best_aggregator) {
- for (aggregator = __get_first_agg(best_aggregator->lag_ports);
- aggregator;
- aggregator = __get_next_agg(aggregator)) {
-
- dprintk("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d\n",
- aggregator->aggregator_identifier, aggregator->num_of_ports,
- aggregator->actor_oper_aggregator_key, aggregator->partner_oper_aggregator_key,
- aggregator->is_individual, aggregator->is_active);
+ if (best) {
+ pr_debug("best Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
+ best->aggregator_identifier, best->num_of_ports,
+ best->actor_oper_aggregator_key,
+ best->partner_oper_aggregator_key,
+ best->is_individual, best->is_active);
+ pr_debug("best ports %p slave %p %s\n",
+ best->lag_ports, best->slave,
+ best->slave ? best->slave->dev->name : "NULL");
+
+ for (agg = __get_first_agg(best->lag_ports); agg;
+ agg = __get_next_agg(agg)) {
+
+ pr_debug("Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
+ agg->aggregator_identifier, agg->num_of_ports,
+ agg->actor_oper_aggregator_key,
+ agg->partner_oper_aggregator_key,
+ agg->is_individual, agg->is_active);
}
// check if any partner replys
- if (best_aggregator->is_individual) {
- printk(KERN_WARNING DRV_NAME ": %s: Warning: No 802.3ad response from "
- "the link partner for any adapters in the bond\n",
- best_aggregator->slave->dev->master->name);
+ if (best->is_individual) {
+ printk(KERN_WARNING DRV_NAME ": %s: Warning: No 802.3ad"
+ " response from the link partner for any"
+ " adapters in the bond\n",
+ best->slave->dev->master->name);
}
- // check if there are more than one aggregator
- if (num_of_aggs > 1) {
- dprintk("Warning: More than one Link Aggregation Group was "
- "found in the bond. Only one group will function in the bond\n");
- }
-
- best_aggregator->is_active = 1;
- dprintk("LAG %d choosed as the active LAG\n", best_aggregator->aggregator_identifier);
- dprintk("Agg=%d; Ports=%d; a key=%d; p key=%d; Indiv=%d; Active=%d\n",
- best_aggregator->aggregator_identifier, best_aggregator->num_of_ports,
- best_aggregator->actor_oper_aggregator_key, best_aggregator->partner_oper_aggregator_key,
- best_aggregator->is_individual, best_aggregator->is_active);
+ best->is_active = 1;
+ pr_debug("LAG %d chosen as the active LAG\n",
+ best->aggregator_identifier);
+ pr_debug("Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n",
+ best->aggregator_identifier, best->num_of_ports,
+ best->actor_oper_aggregator_key,
+ best->partner_oper_aggregator_key,
+ best->is_individual, best->is_active);
// disable the ports that were related to the former active_aggregator
- if (last_active_aggregator) {
- for (port=last_active_aggregator->lag_ports; port; port=port->next_port_in_aggregator) {
+ if (active) {
+ for (port = active->lag_ports; port;
+ port = port->next_port_in_aggregator) {
__disable_port(port);
}
}
}
- // if the selected aggregator is of join individuals(partner_system is NULL), enable their ports
- active_aggregator = __get_active_agg(origin_aggregator);
+ /*
+ * if the selected aggregator is of join individuals
+ * (partner_system is NULL), enable their ports
+ */
+ active = __get_active_agg(origin);
- if (active_aggregator) {
- if (!MAC_ADDRESS_COMPARE(&(active_aggregator->partner_system), &(null_mac_addr))) {
- for (port=active_aggregator->lag_ports; port; port=port->next_port_in_aggregator) {
+ if (active) {
+ if (!__agg_has_partner(active)) {
+ for (port = active->lag_ports; port;
+ port = port->next_port_in_aggregator) {
__enable_port(port);
}
}
}
+
+ if (origin->slave) {
+ struct bonding *bond;
+
+ bond = bond_get_bond_by_slave(origin->slave);
+ if (bond)
+ bond_3ad_set_carrier(bond);
+ }
}
/**
@@ -1584,7 +1612,7 @@ static void ad_agg_selection_logic(struct aggregator *aggregator)
static void ad_clear_agg(struct aggregator *aggregator)
{
if (aggregator) {
- aggregator->is_individual = 0;
+ aggregator->is_individual = false;
aggregator->actor_admin_aggregator_key = 0;
aggregator->actor_oper_aggregator_key = 0;
aggregator->partner_system = null_mac_addr;
@@ -1595,7 +1623,7 @@ static void ad_clear_agg(struct aggregator *aggregator)
aggregator->lag_ports = NULL;
aggregator->is_active = 0;
aggregator->num_of_ports = 0;
- dprintk("LAG %d was cleared\n", aggregator->aggregator_identifier);
+ pr_debug("LAG %d was cleared\n", aggregator->aggregator_identifier);
}
}
@@ -1623,13 +1651,32 @@ static void ad_initialize_agg(struct aggregator *aggregator)
*/
static void ad_initialize_port(struct port *port, int lacp_fast)
{
+ static const struct port_params tmpl = {
+ .system_priority = 0xffff,
+ .key = 1,
+ .port_number = 1,
+ .port_priority = 0xff,
+ .port_state = 1,
+ };
+ static const struct lacpdu lacpdu = {
+ .subtype = 0x01,
+ .version_number = 0x01,
+ .tlv_type_actor_info = 0x01,
+ .actor_information_length = 0x14,
+ .tlv_type_partner_info = 0x02,
+ .partner_information_length = 0x14,
+ .tlv_type_collector_info = 0x03,
+ .collector_information_length = 0x10,
+ .collector_max_delay = htons(AD_COLLECTOR_MAX_DELAY),
+ };
+
if (port) {
port->actor_port_number = 1;
port->actor_port_priority = 0xff;
port->actor_system = null_mac_addr;
port->actor_system_priority = 0xffff;
port->actor_port_aggregator_identifier = 0;
- port->ntt = 0;
+ port->ntt = false;
port->actor_admin_port_key = 1;
port->actor_oper_port_key = 1;
port->actor_admin_port_state = AD_STATE_AGGREGATION | AD_STATE_LACP_ACTIVITY;
@@ -1639,19 +1686,10 @@ static void ad_initialize_port(struct port *port, int lacp_fast)
port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT;
}
- port->partner_admin_system = null_mac_addr;
- port->partner_oper_system = null_mac_addr;
- port->partner_admin_system_priority = 0xffff;
- port->partner_oper_system_priority = 0xffff;
- port->partner_admin_key = 1;
- port->partner_oper_key = 1;
- port->partner_admin_port_number = 1;
- port->partner_oper_port_number = 1;
- port->partner_admin_port_priority = 0xff;
- port->partner_oper_port_priority = 0xff;
- port->partner_admin_port_state = 1;
- port->partner_oper_port_state = 1;
- port->is_enabled = 1;
+ memcpy(&port->partner_admin, &tmpl, sizeof(tmpl));
+ memcpy(&port->partner_oper, &tmpl, sizeof(tmpl));
+
+ port->is_enabled = true;
// ****** private parameters ******
port->sm_vars = 0x3;
port->sm_rx_state = 0;
@@ -1667,7 +1705,7 @@ static void ad_initialize_port(struct port *port, int lacp_fast)
port->next_port_in_aggregator = NULL;
port->transaction_id = 0;
- ad_initialize_lacpdu(&(port->lacpdu));
+ memcpy(&port->lacpdu, &lacpdu, sizeof(lacpdu));
}
}
@@ -1680,7 +1718,7 @@ static void ad_initialize_port(struct port *port, int lacp_fast)
static void ad_enable_collecting_distributing(struct port *port)
{
if (port->aggregator->is_active) {
- dprintk("Enabling port %d(LAG %d)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
+ pr_debug("Enabling port %d(LAG %d)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
__enable_port(port);
}
}
@@ -1693,7 +1731,7 @@ static void ad_enable_collecting_distributing(struct port *port)
static void ad_disable_collecting_distributing(struct port *port)
{
if (port->aggregator && MAC_ADDRESS_COMPARE(&(port->aggregator->partner_system), &(null_mac_addr))) {
- dprintk("Disabling port %d(LAG %d)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
+ pr_debug("Disabling port %d(LAG %d)\n", port->actor_port_number, port->aggregator->aggregator_identifier);
__disable_port(port);
}
}
@@ -1731,7 +1769,7 @@ static void ad_marker_info_send(struct port *port)
// send the marker information
if (ad_marker_send(port, &marker) >= 0) {
- dprintk("Sent Marker Information on port %d\n", port->actor_port_number);
+ pr_debug("Sent Marker Information on port %d\n", port->actor_port_number);
}
}
#endif
@@ -1755,7 +1793,7 @@ static void ad_marker_info_received(struct bond_marker *marker_info,
// send the marker response
if (ad_marker_send(port, &marker) >= 0) {
- dprintk("Sent Marker Response on port %d\n", port->actor_port_number);
+ pr_debug("Sent Marker Response on port %d\n", port->actor_port_number);
}
}
@@ -1776,53 +1814,6 @@ static void ad_marker_response_received(struct bond_marker *marker,
// DO NOTHING, SINCE WE DECIDED NOT TO IMPLEMENT THIS FEATURE FOR NOW
}
-/**
- * ad_initialize_lacpdu - initialize a given lacpdu structure
- * @lacpdu: lacpdu structure to initialize
- *
- */
-static void ad_initialize_lacpdu(struct lacpdu *lacpdu)
-{
- u16 index;
-
- // initialize lacpdu data
- lacpdu->subtype = 0x01;
- lacpdu->version_number = 0x01;
- lacpdu->tlv_type_actor_info = 0x01;
- lacpdu->actor_information_length = 0x14;
- // lacpdu->actor_system_priority updated on send
- // lacpdu->actor_system updated on send
- // lacpdu->actor_key updated on send
- // lacpdu->actor_port_priority updated on send
- // lacpdu->actor_port updated on send
- // lacpdu->actor_state updated on send
- lacpdu->tlv_type_partner_info = 0x02;
- lacpdu->partner_information_length = 0x14;
- for (index=0; index<=2; index++) {
- lacpdu->reserved_3_1[index]=0;
- }
- // lacpdu->partner_system_priority updated on send
- // lacpdu->partner_system updated on send
- // lacpdu->partner_key updated on send
- // lacpdu->partner_port_priority updated on send
- // lacpdu->partner_port updated on send
- // lacpdu->partner_state updated on send
- for (index=0; index<=2; index++) {
- lacpdu->reserved_3_2[index]=0;
- }
- lacpdu->tlv_type_collector_info = 0x03;
- lacpdu->collector_information_length= 0x10;
- lacpdu->collector_max_delay = htons(AD_COLLECTOR_MAX_DELAY);
- for (index=0; index<=11; index++) {
- lacpdu->reserved_12[index]=0;
- }
- lacpdu->tlv_type_terminator = 0x00;
- lacpdu->terminator_length = 0;
- for (index=0; index<=49; index++) {
- lacpdu->reserved_50[index]=0;
- }
-}
-
//////////////////////////////////////////////////////////////////////////////////////
// ================= AD exported functions to the main bonding code ==================
//////////////////////////////////////////////////////////////////////////////////////
@@ -1830,6 +1821,19 @@ static void ad_initialize_lacpdu(struct lacpdu *lacpdu)
// Check aggregators status in team every T seconds
#define AD_AGGREGATOR_SELECTION_TIMER 8
+/*
+ * bond_3ad_initiate_agg_selection(struct bonding *bond)
+ *
+ * Set the aggregation selection timer, to initiate an agg selection in
+ * the very near future. Called during first initialization, and during
+ * any down to up transitions of the bond.
+ */
+void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout)
+{
+ BOND_AD_INFO(bond).agg_select_timer = timeout;
+ BOND_AD_INFO(bond).agg_select_mode = bond->params.ad_select;
+}
+
static u16 aggregator_identifier;
/**
@@ -1854,9 +1858,9 @@ void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fas
// initialize how many times this module is called in one second(should be about every 100ms)
ad_ticks_per_sec = tick_resolution;
- // initialize the aggregator selection timer(to activate an aggregation selection after initialize)
- BOND_AD_INFO(bond).agg_select_timer = (AD_AGGREGATOR_SELECTION_TIMER * ad_ticks_per_sec);
- BOND_AD_INFO(bond).agg_select_mode = AD_BANDWIDTH;
+ bond_3ad_initiate_agg_selection(bond,
+ AD_AGGREGATOR_SELECTION_TIMER *
+ ad_ticks_per_sec);
}
}
@@ -1956,7 +1960,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
return;
}
- dprintk("Unbinding Link Aggregation Group %d\n", aggregator->aggregator_identifier);
+ pr_debug("Unbinding Link Aggregation Group %d\n", aggregator->aggregator_identifier);
/* Tell the partner that this port is not suitable for aggregation */
port->actor_oper_port_state &= ~AD_STATE_AGGREGATION;
@@ -1980,7 +1984,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
// if new aggregator found, copy the aggregator's parameters
// and connect the related lag_ports to the new aggregator
if ((new_aggregator) && ((!new_aggregator->lag_ports) || ((new_aggregator->lag_ports == port) && !new_aggregator->lag_ports->next_port_in_aggregator))) {
- dprintk("Some port(s) related to LAG %d - replaceing with LAG %d\n", aggregator->aggregator_identifier, new_aggregator->aggregator_identifier);
+ pr_debug("Some port(s) related to LAG %d - replaceing with LAG %d\n", aggregator->aggregator_identifier, new_aggregator->aggregator_identifier);
if ((new_aggregator->lag_ports == port) && new_aggregator->is_active) {
printk(KERN_INFO DRV_NAME ": %s: Removing an active aggregator\n",
@@ -2031,7 +2035,7 @@ void bond_3ad_unbind_slave(struct slave *slave)
}
}
- dprintk("Unbinding port %d\n", port->actor_port_number);
+ pr_debug("Unbinding port %d\n", port->actor_port_number);
// find the aggregator that this port is connected to
temp_aggregator = __get_first_agg(port);
for (; temp_aggregator; temp_aggregator = __get_next_agg(temp_aggregator)) {
@@ -2162,7 +2166,7 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
switch (lacpdu->subtype) {
case AD_TYPE_LACPDU:
- dprintk("Received LACPDU on port %d\n", port->actor_port_number);
+ pr_debug("Received LACPDU on port %d\n", port->actor_port_number);
ad_rx_machine(lacpdu, port);
break;
@@ -2171,17 +2175,17 @@ static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u
switch (((struct bond_marker *)lacpdu)->tlv_type) {
case AD_MARKER_INFORMATION_SUBTYPE:
- dprintk("Received Marker Information on port %d\n", port->actor_port_number);
+ pr_debug("Received Marker Information on port %d\n", port->actor_port_number);
ad_marker_info_received((struct bond_marker *)lacpdu, port);
break;
case AD_MARKER_RESPONSE_SUBTYPE:
- dprintk("Received Marker Response on port %d\n", port->actor_port_number);
+ pr_debug("Received Marker Response on port %d\n", port->actor_port_number);
ad_marker_response_received((struct bond_marker *)lacpdu, port);
break;
default:
- dprintk("Received an unknown Marker subtype on slot %d\n", port->actor_port_number);
+ pr_debug("Received an unknown Marker subtype on slot %d\n", port->actor_port_number);
}
}
}
@@ -2209,7 +2213,7 @@ void bond_3ad_adapter_speed_changed(struct slave *slave)
port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
port->actor_oper_port_key=port->actor_admin_port_key |= (__get_link_speed(port) << 1);
- dprintk("Port %d changed speed\n", port->actor_port_number);
+ pr_debug("Port %d changed speed\n", port->actor_port_number);
// there is no need to reselect a new aggregator, just signal the
// state machines to reinitialize
port->sm_vars |= AD_PORT_BEGIN;
@@ -2237,7 +2241,7 @@ void bond_3ad_adapter_duplex_changed(struct slave *slave)
port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
port->actor_oper_port_key=port->actor_admin_port_key |= __get_duplex(port);
- dprintk("Port %d changed duplex\n", port->actor_port_number);
+ pr_debug("Port %d changed duplex\n", port->actor_port_number);
// there is no need to reselect a new aggregator, just signal the
// state machines to reinitialize
port->sm_vars |= AD_PORT_BEGIN;
@@ -2267,14 +2271,14 @@ void bond_3ad_handle_link_change(struct slave *slave, char link)
// on link down we are zeroing duplex and speed since some of the adaptors(ce1000.lan) report full duplex/speed instead of N/A(duplex) / 0(speed)
// on link up we are forcing recheck on the duplex and speed since some of he adaptors(ce1000.lan) report
if (link == BOND_LINK_UP) {
- port->is_enabled = 1;
+ port->is_enabled = true;
port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
port->actor_oper_port_key=port->actor_admin_port_key |= __get_duplex(port);
port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS;
port->actor_oper_port_key=port->actor_admin_port_key |= (__get_link_speed(port) << 1);
} else {
/* link has failed */
- port->is_enabled = 0;
+ port->is_enabled = false;
port->actor_admin_port_key &= ~AD_DUPLEX_KEY_BITS;
port->actor_oper_port_key= (port->actor_admin_port_key &= ~AD_SPEED_KEY_BITS);
}
@@ -2346,7 +2350,7 @@ int bond_3ad_get_active_agg_info(struct bonding *bond, struct ad_info *ad_info)
int bond_3ad_xmit_xor(struct sk_buff *skb, struct net_device *dev)
{
struct slave *slave, *start_at;
- struct bonding *bond = dev->priv;
+ struct bonding *bond = netdev_priv(dev);
int slave_agg_no;
int slaves_in_agg;
int agg_id;
@@ -2426,7 +2430,7 @@ out:
int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type* ptype, struct net_device *orig_dev)
{
- struct bonding *bond = dev->priv;
+ struct bonding *bond = netdev_priv(dev);
struct slave *slave = NULL;
int ret = NET_RX_DROP;
@@ -2437,7 +2441,8 @@ int bond_3ad_lacpdu_recv(struct sk_buff *skb, struct net_device *dev, struct pac
goto out;
read_lock(&bond->lock);
- slave = bond_get_slave_by_dev((struct bonding *)dev->priv, orig_dev);
+ slave = bond_get_slave_by_dev((struct bonding *)netdev_priv(dev),
+ orig_dev);
if (!slave)
goto out_unlock;
diff --git a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
index b5ee45f6d55a..8a83eb283c21 100644
--- a/drivers/net/bonding/bond_3ad.h
+++ b/drivers/net/bonding/bond_3ad.h
@@ -33,7 +33,6 @@
#define AD_TIMER_INTERVAL 100 /*msec*/
#define MULTICAST_LACPDU_ADDR {0x01, 0x80, 0xC2, 0x00, 0x00, 0x02}
-#define AD_MULTICAST_LACPDU_ADDR {MULTICAST_LACPDU_ADDR}
#define AD_LACP_SLOW 0
#define AD_LACP_FAST 1
@@ -42,10 +41,11 @@ typedef struct mac_addr {
u8 mac_addr_value[ETH_ALEN];
} mac_addr_t;
-typedef enum {
- AD_BANDWIDTH = 0,
- AD_COUNT
-} agg_selection_t;
+enum {
+ BOND_AD_STABLE = 0,
+ BOND_AD_BANDWIDTH = 1,
+ BOND_AD_COUNT = 2,
+};
// rx machine states(43.4.11 in the 802.3ad standard)
typedef enum {
@@ -105,12 +105,6 @@ typedef enum {
#pragma pack(1)
-typedef struct ad_header {
- struct mac_addr destination_address;
- struct mac_addr source_address;
- __be16 length_type;
-} ad_header_t;
-
// Link Aggregation Control Protocol(LACP) data unit structure(43.4.2.2 in the 802.3ad standard)
typedef struct lacpdu {
u8 subtype; // = LACP(= 0x01)
@@ -143,7 +137,7 @@ typedef struct lacpdu {
} lacpdu_t;
typedef struct lacpdu_header {
- struct ad_header ad_header;
+ struct ethhdr hdr;
struct lacpdu lacpdu;
} lacpdu_header_t;
@@ -164,7 +158,7 @@ typedef struct bond_marker {
} bond_marker_t;
typedef struct bond_marker_header {
- struct ad_header ad_header;
+ struct ethhdr hdr;
struct bond_marker marker;
} bond_marker_header_t;
@@ -183,7 +177,7 @@ struct port;
typedef struct aggregator {
struct mac_addr aggregator_mac_address;
u16 aggregator_identifier;
- u16 is_individual; // BOOLEAN
+ bool is_individual;
u16 actor_admin_aggregator_key;
u16 actor_oper_aggregator_key;
struct mac_addr partner_system;
@@ -198,6 +192,15 @@ typedef struct aggregator {
u16 num_of_ports;
} aggregator_t;
+struct port_params {
+ struct mac_addr system;
+ u16 system_priority;
+ u16 key;
+ u16 port_number;
+ u16 port_priority;
+ u16 port_state;
+};
+
// port structure(43.4.6 in the 802.3ad standard)
typedef struct port {
u16 actor_port_number;
@@ -205,24 +208,17 @@ typedef struct port {
struct mac_addr actor_system; // This parameter is added here although it is not specified in the standard, just for simplification
u16 actor_system_priority; // This parameter is added here although it is not specified in the standard, just for simplification
u16 actor_port_aggregator_identifier;
- u16 ntt; // BOOLEAN
+ bool ntt;
u16 actor_admin_port_key;
u16 actor_oper_port_key;
u8 actor_admin_port_state;
u8 actor_oper_port_state;
- struct mac_addr partner_admin_system;
- struct mac_addr partner_oper_system;
- u16 partner_admin_system_priority;
- u16 partner_oper_system_priority;
- u16 partner_admin_key;
- u16 partner_oper_key;
- u16 partner_admin_port_number;
- u16 partner_oper_port_number;
- u16 partner_admin_port_priority;
- u16 partner_oper_port_priority;
- u8 partner_admin_port_state;
- u8 partner_oper_port_state;
- u16 is_enabled; // BOOLEAN
+
+ struct port_params partner_admin;
+ struct port_params partner_oper;
+
+ bool is_enabled;
+
// ****** PRIVATE PARAMETERS ******
u16 sm_vars; // all state machines variables for this port
rx_states_t sm_rx_state; // state machine rx state
@@ -241,10 +237,10 @@ typedef struct port {
} port_t;
// system structure
-typedef struct ad_system {
+struct ad_system {
u16 sys_priority;
struct mac_addr sys_mac_addr;
-} ad_system_t;
+};
#ifdef __ia64__
#pragma pack()
@@ -255,7 +251,7 @@ typedef struct ad_system {
#define SLAVE_AD_INFO(slave) ((slave)->ad_info)
struct ad_bond_info {
- ad_system_t system; // 802.3ad system structure
+ struct ad_system system; /* 802.3ad system structure */
u32 agg_select_timer; // Timer to select aggregator after all adapter's hand shakes
u32 agg_select_mode; // Mode of selection of active aggregator(bandwidth/count)
int lacp_fast; /* whether fast periodic tx should be
@@ -277,6 +273,7 @@ void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution, int lacp_fas
int bond_3ad_bind_slave(struct slave *slave);
void bond_3ad_unbind_slave(struct slave *slave);
void bond_3ad_state_machine_handler(struct work_struct *);
+void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout);
void bond_3ad_adapter_speed_changed(struct slave *slave);
void bond_3ad_adapter_duplex_changed(struct slave *slave);
void bond_3ad_handle_link_change(struct slave *slave, char link);
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
index 87437c788476..27fb7f5c21cf 100644
--- a/drivers/net/bonding/bond_alb.c
+++ b/drivers/net/bonding/bond_alb.c
@@ -20,8 +20,6 @@
*
*/
-//#define BONDING_DEBUG 1
-
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
@@ -346,30 +344,37 @@ static void rlb_update_entry_from_arp(struct bonding *bond, struct arp_pkt *arp)
static int rlb_arp_recv(struct sk_buff *skb, struct net_device *bond_dev, struct packet_type *ptype, struct net_device *orig_dev)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond;
struct arp_pkt *arp = (struct arp_pkt *)skb->data;
int res = NET_RX_DROP;
if (dev_net(bond_dev) != &init_net)
goto out;
- if (!(bond_dev->flags & IFF_MASTER))
+ while (bond_dev->priv_flags & IFF_802_1Q_VLAN)
+ bond_dev = vlan_dev_real_dev(bond_dev);
+
+ if (!(bond_dev->priv_flags & IFF_BONDING) ||
+ !(bond_dev->flags & IFF_MASTER))
goto out;
if (!arp) {
- dprintk("Packet has no ARP data\n");
+ pr_debug("Packet has no ARP data\n");
goto out;
}
if (skb->len < sizeof(struct arp_pkt)) {
- dprintk("Packet is too small to be an ARP\n");
+ pr_debug("Packet is too small to be an ARP\n");
goto out;
}
if (arp->op_code == htons(ARPOP_REPLY)) {
/* update rx hash table for this ARP */
+ printk("rar: update orig %s bond_dev %s\n", orig_dev->name,
+ bond_dev->name);
+ bond = netdev_priv(bond_dev);
rlb_update_entry_from_arp(bond, arp);
- dprintk("Server received an ARP Reply from client\n");
+ pr_debug("Server received an ARP Reply from client\n");
}
res = NET_RX_SUCCESS;
@@ -723,7 +728,7 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
if (tx_slave) {
memcpy(arp->mac_src,tx_slave->dev->dev_addr, ETH_ALEN);
}
- dprintk("Server sent ARP Reply packet\n");
+ pr_debug("Server sent ARP Reply packet\n");
} else if (arp->op_code == htons(ARPOP_REQUEST)) {
/* Create an entry in the rx_hashtbl for this client as a
* place holder.
@@ -743,7 +748,7 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
* updated with their assigned mac.
*/
rlb_req_update_subnet_clients(bond, arp->ip_src);
- dprintk("Server sent ARP Request packet\n");
+ pr_debug("Server sent ARP Request packet\n");
}
return tx_slave;
@@ -818,7 +823,7 @@ static int rlb_initialize(struct bonding *bond)
/*initialize packet type*/
pk_type->type = __constant_htons(ETH_P_ARP);
- pk_type->dev = bond->dev;
+ pk_type->dev = NULL;
pk_type->func = rlb_arp_recv;
/* register to receive ARPs */
@@ -1211,11 +1216,6 @@ static int alb_set_mac_address(struct bonding *bond, void *addr)
}
bond_for_each_slave(bond, slave, i) {
- if (slave->dev->set_mac_address == NULL) {
- res = -EOPNOTSUPP;
- goto unwind;
- }
-
/* save net_device's current hw address */
memcpy(tmp_addr, slave->dev->dev_addr, ETH_ALEN);
@@ -1224,9 +1224,8 @@ static int alb_set_mac_address(struct bonding *bond, void *addr)
/* restore net_device's hw address */
memcpy(slave->dev->dev_addr, tmp_addr, ETH_ALEN);
- if (res) {
+ if (res)
goto unwind;
- }
}
return 0;
@@ -1285,7 +1284,7 @@ void bond_alb_deinitialize(struct bonding *bond)
int bond_alb_xmit(struct sk_buff *skb, struct net_device *bond_dev)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
struct ethhdr *eth_data;
struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
struct slave *tx_slave = NULL;
@@ -1706,7 +1705,7 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
*/
int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
struct sockaddr *sa = addr;
struct slave *slave, *swap_slave;
int res;
diff --git a/drivers/net/bonding/bond_ipv6.c b/drivers/net/bonding/bond_ipv6.c
new file mode 100644
index 000000000000..0d73bf5ac5a5
--- /dev/null
+++ b/drivers/net/bonding/bond_ipv6.c
@@ -0,0 +1,216 @@
+/*
+ * Copyright(c) 2008 Hewlett-Packard Development Company, L.P.
+ *
+ * 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.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/if_vlan.h>
+#include <net/ipv6.h>
+#include <net/ndisc.h>
+#include <net/addrconf.h>
+#include "bonding.h"
+
+/*
+ * Assign bond->master_ipv6 to the next IPv6 address in the list, or
+ * zero it out if there are none.
+ */
+static void bond_glean_dev_ipv6(struct net_device *dev, struct in6_addr *addr)
+{
+ struct inet6_dev *idev;
+ struct inet6_ifaddr *ifa;
+
+ if (!dev)
+ return;
+
+ idev = in6_dev_get(dev);
+ if (!idev)
+ return;
+
+ read_lock_bh(&idev->lock);
+ ifa = idev->addr_list;
+ if (ifa)
+ ipv6_addr_copy(addr, &ifa->addr);
+ else
+ ipv6_addr_set(addr, 0, 0, 0, 0);
+
+ read_unlock_bh(&idev->lock);
+
+ in6_dev_put(idev);
+}
+
+static void bond_na_send(struct net_device *slave_dev,
+ struct in6_addr *daddr,
+ int router,
+ unsigned short vlan_id)
+{
+ struct in6_addr mcaddr;
+ struct icmp6hdr icmp6h = {
+ .icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT,
+ };
+ struct sk_buff *skb;
+
+ icmp6h.icmp6_router = router;
+ icmp6h.icmp6_solicited = 0;
+ icmp6h.icmp6_override = 1;
+
+ addrconf_addr_solict_mult(daddr, &mcaddr);
+
+ pr_debug("ipv6 na on slave %s: dest %pI6, src %pI6\n",
+ slave_dev->name, &mcaddr, daddr);
+
+ skb = ndisc_build_skb(slave_dev, &mcaddr, daddr, &icmp6h, daddr,
+ ND_OPT_TARGET_LL_ADDR);
+
+ if (!skb) {
+ printk(KERN_ERR DRV_NAME ": NA packet allocation failed\n");
+ return;
+ }
+
+ if (vlan_id) {
+ skb = vlan_put_tag(skb, vlan_id);
+ if (!skb) {
+ printk(KERN_ERR DRV_NAME ": failed to insert VLAN tag\n");
+ return;
+ }
+ }
+
+ ndisc_send_skb(skb, slave_dev, NULL, &mcaddr, daddr, &icmp6h);
+}
+
+/*
+ * Kick out an unsolicited Neighbor Advertisement for an IPv6 address on
+ * the bonding master. This will help the switch learn our address
+ * if in active-backup mode.
+ *
+ * Caller must hold curr_slave_lock for read or better
+ */
+void bond_send_unsolicited_na(struct bonding *bond)
+{
+ struct slave *slave = bond->curr_active_slave;
+ struct vlan_entry *vlan;
+ struct inet6_dev *idev;
+ int is_router;
+
+ pr_debug("bond_send_unsol_na: bond %s slave %s\n", bond->dev->name,
+ slave ? slave->dev->name : "NULL");
+
+ if (!slave || !bond->send_unsol_na ||
+ test_bit(__LINK_STATE_LINKWATCH_PENDING, &slave->dev->state))
+ return;
+
+ bond->send_unsol_na--;
+
+ idev = in6_dev_get(bond->dev);
+ if (!idev)
+ return;
+
+ is_router = !!idev->cnf.forwarding;
+
+ in6_dev_put(idev);
+
+ if (!ipv6_addr_any(&bond->master_ipv6))
+ bond_na_send(slave->dev, &bond->master_ipv6, is_router, 0);
+
+ list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
+ if (!ipv6_addr_any(&vlan->vlan_ipv6)) {
+ bond_na_send(slave->dev, &vlan->vlan_ipv6, is_router,
+ vlan->vlan_id);
+ }
+ }
+}
+
+/*
+ * bond_inet6addr_event: handle inet6addr notifier chain events.
+ *
+ * We keep track of device IPv6 addresses primarily to use as source
+ * addresses in NS probes.
+ *
+ * We track one IPv6 for the main device (if it has one).
+ */
+static int bond_inet6addr_event(struct notifier_block *this,
+ unsigned long event,
+ void *ptr)
+{
+ struct inet6_ifaddr *ifa = ptr;
+ struct net_device *vlan_dev, *event_dev = ifa->idev->dev;
+ struct bonding *bond;
+ struct vlan_entry *vlan;
+
+ if (dev_net(event_dev) != &init_net)
+ return NOTIFY_DONE;
+
+ list_for_each_entry(bond, &bond_dev_list, bond_list) {
+ if (bond->dev == event_dev) {
+ switch (event) {
+ case NETDEV_UP:
+ if (ipv6_addr_any(&bond->master_ipv6))
+ ipv6_addr_copy(&bond->master_ipv6,
+ &ifa->addr);
+ return NOTIFY_OK;
+ case NETDEV_DOWN:
+ if (ipv6_addr_equal(&bond->master_ipv6,
+ &ifa->addr))
+ bond_glean_dev_ipv6(bond->dev,
+ &bond->master_ipv6);
+ return NOTIFY_OK;
+ default:
+ return NOTIFY_DONE;
+ }
+ }
+
+ list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
+ vlan_dev = vlan_group_get_device(bond->vlgrp,
+ vlan->vlan_id);
+ if (vlan_dev == event_dev) {
+ switch (event) {
+ case NETDEV_UP:
+ if (ipv6_addr_any(&vlan->vlan_ipv6))
+ ipv6_addr_copy(&vlan->vlan_ipv6,
+ &ifa->addr);
+ return NOTIFY_OK;
+ case NETDEV_DOWN:
+ if (ipv6_addr_equal(&vlan->vlan_ipv6,
+ &ifa->addr))
+ bond_glean_dev_ipv6(vlan_dev,
+ &vlan->vlan_ipv6);
+ return NOTIFY_OK;
+ default:
+ return NOTIFY_DONE;
+ }
+ }
+ }
+ }
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block bond_inet6addr_notifier = {
+ .notifier_call = bond_inet6addr_event,
+};
+
+void bond_register_ipv6_notifier(void)
+{
+ register_inet6addr_notifier(&bond_inet6addr_notifier);
+}
+
+void bond_unregister_ipv6_notifier(void)
+{
+ unregister_inet6addr_notifier(&bond_inet6addr_notifier);
+}
+
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index a3efba59eee9..460c2cad2755 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -31,8 +31,6 @@
*
*/
-//#define BONDING_DEBUG 1
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
@@ -89,6 +87,7 @@
static int max_bonds = BOND_DEFAULT_MAX_BONDS;
static int num_grat_arp = 1;
+static int num_unsol_na = 1;
static int miimon = BOND_LINK_MON_INTERV;
static int updelay = 0;
static int downdelay = 0;
@@ -96,6 +95,7 @@ static int use_carrier = 1;
static char *mode = NULL;
static char *primary = NULL;
static char *lacp_rate = NULL;
+static char *ad_select = NULL;
static char *xmit_hash_policy = NULL;
static int arp_interval = BOND_LINK_ARP_INTERV;
static char *arp_ip_target[BOND_MAX_ARP_TARGETS] = { NULL, };
@@ -107,6 +107,8 @@ module_param(max_bonds, int, 0);
MODULE_PARM_DESC(max_bonds, "Max number of bonded devices");
module_param(num_grat_arp, int, 0644);
MODULE_PARM_DESC(num_grat_arp, "Number of gratuitous ARP packets to send on failover event");
+module_param(num_unsol_na, int, 0644);
+MODULE_PARM_DESC(num_unsol_na, "Number of unsolicited IPv6 Neighbor Advertisements packets to send on failover event");
module_param(miimon, int, 0);
MODULE_PARM_DESC(miimon, "Link check interval in milliseconds");
module_param(updelay, int, 0);
@@ -127,6 +129,8 @@ MODULE_PARM_DESC(primary, "Primary network device to use");
module_param(lacp_rate, charp, 0);
MODULE_PARM_DESC(lacp_rate, "LACPDU tx rate to request from 802.3ad partner "
"(slow/fast)");
+module_param(ad_select, charp, 0);
+MODULE_PARM_DESC(ad_select, "803.ad aggregation selection logic: stable (0, default), bandwidth (1), count (2)");
module_param(xmit_hash_policy, charp, 0);
MODULE_PARM_DESC(xmit_hash_policy, "XOR hashing method: 0 for layer 2 (default)"
", 1 for layer 3+4");
@@ -150,7 +154,6 @@ LIST_HEAD(bond_dev_list);
static struct proc_dir_entry *bond_proc_dir = NULL;
#endif
-extern struct rw_semaphore bonding_rwsem;
static __be32 arp_target[BOND_MAX_ARP_TARGETS] = { 0, } ;
static int arp_ip_count = 0;
static int bond_mode = BOND_MODE_ROUNDROBIN;
@@ -158,13 +161,13 @@ static int xmit_hashtype= BOND_XMIT_POLICY_LAYER2;
static int lacp_fast = 0;
-struct bond_parm_tbl bond_lacp_tbl[] = {
+const struct bond_parm_tbl bond_lacp_tbl[] = {
{ "slow", AD_LACP_SLOW},
{ "fast", AD_LACP_FAST},
{ NULL, -1},
};
-struct bond_parm_tbl bond_mode_tbl[] = {
+const struct bond_parm_tbl bond_mode_tbl[] = {
{ "balance-rr", BOND_MODE_ROUNDROBIN},
{ "active-backup", BOND_MODE_ACTIVEBACKUP},
{ "balance-xor", BOND_MODE_XOR},
@@ -175,14 +178,14 @@ struct bond_parm_tbl bond_mode_tbl[] = {
{ NULL, -1},
};
-struct bond_parm_tbl xmit_hashtype_tbl[] = {
+const struct bond_parm_tbl xmit_hashtype_tbl[] = {
{ "layer2", BOND_XMIT_POLICY_LAYER2},
{ "layer3+4", BOND_XMIT_POLICY_LAYER34},
{ "layer2+3", BOND_XMIT_POLICY_LAYER23},
{ NULL, -1},
};
-struct bond_parm_tbl arp_validate_tbl[] = {
+const struct bond_parm_tbl arp_validate_tbl[] = {
{ "none", BOND_ARP_VALIDATE_NONE},
{ "active", BOND_ARP_VALIDATE_ACTIVE},
{ "backup", BOND_ARP_VALIDATE_BACKUP},
@@ -190,13 +193,20 @@ struct bond_parm_tbl arp_validate_tbl[] = {
{ NULL, -1},
};
-struct bond_parm_tbl fail_over_mac_tbl[] = {
+const struct bond_parm_tbl fail_over_mac_tbl[] = {
{ "none", BOND_FOM_NONE},
{ "active", BOND_FOM_ACTIVE},
{ "follow", BOND_FOM_FOLLOW},
{ NULL, -1},
};
+struct bond_parm_tbl ad_select_tbl[] = {
+{ "stable", BOND_AD_STABLE},
+{ "bandwidth", BOND_AD_BANDWIDTH},
+{ "count", BOND_AD_COUNT},
+{ NULL, -1},
+};
+
/*-------------------------- Forward declarations ---------------------------*/
static void bond_send_gratuitous_arp(struct bonding *bond);
@@ -206,24 +216,20 @@ static void bond_deinit(struct net_device *bond_dev);
static const char *bond_mode_name(int mode)
{
- switch (mode) {
- case BOND_MODE_ROUNDROBIN :
- return "load balancing (round-robin)";
- case BOND_MODE_ACTIVEBACKUP :
- return "fault-tolerance (active-backup)";
- case BOND_MODE_XOR :
- return "load balancing (xor)";
- case BOND_MODE_BROADCAST :
- return "fault-tolerance (broadcast)";
- case BOND_MODE_8023AD:
- return "IEEE 802.3ad Dynamic link aggregation";
- case BOND_MODE_TLB:
- return "transmit load balancing";
- case BOND_MODE_ALB:
- return "adaptive load balancing";
- default:
+ static const char *names[] = {
+ [BOND_MODE_ROUNDROBIN] = "load balancing (round-robin)",
+ [BOND_MODE_ACTIVEBACKUP] = "fault-tolerance (active-backup)",
+ [BOND_MODE_XOR] = "load balancing (xor)",
+ [BOND_MODE_BROADCAST] = "fault-tolerance (broadcast)",
+ [BOND_MODE_8023AD]= "IEEE 802.3ad Dynamic link aggregation",
+ [BOND_MODE_TLB] = "transmit load balancing",
+ [BOND_MODE_ALB] = "adaptive load balancing",
+ };
+
+ if (mode < 0 || mode > BOND_MODE_ALB)
return "unknown";
- }
+
+ return names[mode];
}
/*---------------------------------- VLAN -----------------------------------*/
@@ -239,17 +245,16 @@ static int bond_add_vlan(struct bonding *bond, unsigned short vlan_id)
{
struct vlan_entry *vlan;
- dprintk("bond: %s, vlan id %d\n",
+ pr_debug("bond: %s, vlan id %d\n",
(bond ? bond->dev->name: "None"), vlan_id);
- vlan = kmalloc(sizeof(struct vlan_entry), GFP_KERNEL);
+ vlan = kzalloc(sizeof(struct vlan_entry), GFP_KERNEL);
if (!vlan) {
return -ENOMEM;
}
INIT_LIST_HEAD(&vlan->vlan_list);
vlan->vlan_id = vlan_id;
- vlan->vlan_ip = 0;
write_lock_bh(&bond->lock);
@@ -257,7 +262,7 @@ static int bond_add_vlan(struct bonding *bond, unsigned short vlan_id)
write_unlock_bh(&bond->lock);
- dprintk("added VLAN ID %d on bond %s\n", vlan_id, bond->dev->name);
+ pr_debug("added VLAN ID %d on bond %s\n", vlan_id, bond->dev->name);
return 0;
}
@@ -274,7 +279,7 @@ static int bond_del_vlan(struct bonding *bond, unsigned short vlan_id)
struct vlan_entry *vlan;
int res = -ENODEV;
- dprintk("bond: %s, vlan id %d\n", bond->dev->name, vlan_id);
+ pr_debug("bond: %s, vlan id %d\n", bond->dev->name, vlan_id);
write_lock_bh(&bond->lock);
@@ -282,12 +287,10 @@ static int bond_del_vlan(struct bonding *bond, unsigned short vlan_id)
if (vlan->vlan_id == vlan_id) {
list_del(&vlan->vlan_list);
- if ((bond->params.mode == BOND_MODE_TLB) ||
- (bond->params.mode == BOND_MODE_ALB)) {
+ if (bond_is_lb(bond))
bond_alb_clear_vlan(bond, vlan_id);
- }
- dprintk("removed VLAN ID %d from bond %s\n", vlan_id,
+ pr_debug("removed VLAN ID %d from bond %s\n", vlan_id,
bond->dev->name);
kfree(vlan);
@@ -307,7 +310,7 @@ static int bond_del_vlan(struct bonding *bond, unsigned short vlan_id)
}
}
- dprintk("couldn't find VLAN ID %d in bond %s\n", vlan_id,
+ pr_debug("couldn't find VLAN ID %d in bond %s\n", vlan_id,
bond->dev->name);
out:
@@ -331,13 +334,13 @@ static int bond_has_challenged_slaves(struct bonding *bond)
bond_for_each_slave(bond, slave, i) {
if (slave->dev->features & NETIF_F_VLAN_CHALLENGED) {
- dprintk("found VLAN challenged slave - %s\n",
+ pr_debug("found VLAN challenged slave - %s\n",
slave->dev->name);
return 1;
}
}
- dprintk("no VLAN challenged slaves found\n");
+ pr_debug("no VLAN challenged slaves found\n");
return 0;
}
@@ -442,7 +445,7 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_de
*/
static void bond_vlan_rx_register(struct net_device *bond_dev, struct vlan_group *grp)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave;
int i;
@@ -450,10 +453,11 @@ static void bond_vlan_rx_register(struct net_device *bond_dev, struct vlan_group
bond_for_each_slave(bond, slave, i) {
struct net_device *slave_dev = slave->dev;
+ const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
- slave_dev->vlan_rx_register) {
- slave_dev->vlan_rx_register(slave_dev, grp);
+ slave_ops->ndo_vlan_rx_register) {
+ slave_ops->ndo_vlan_rx_register(slave_dev, grp);
}
}
}
@@ -465,16 +469,17 @@ static void bond_vlan_rx_register(struct net_device *bond_dev, struct vlan_group
*/
static void bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave;
int i, res;
bond_for_each_slave(bond, slave, i) {
struct net_device *slave_dev = slave->dev;
+ const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) &&
- slave_dev->vlan_rx_add_vid) {
- slave_dev->vlan_rx_add_vid(slave_dev, vid);
+ slave_ops->ndo_vlan_rx_add_vid) {
+ slave_ops->ndo_vlan_rx_add_vid(slave_dev, vid);
}
}
@@ -493,21 +498,22 @@ static void bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid)
*/
static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave;
struct net_device *vlan_dev;
int i, res;
bond_for_each_slave(bond, slave, i) {
struct net_device *slave_dev = slave->dev;
+ const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) &&
- slave_dev->vlan_rx_kill_vid) {
+ slave_ops->ndo_vlan_rx_kill_vid) {
/* Save and then restore vlan_dev in the grp array,
* since the slave's driver might clear it.
*/
vlan_dev = vlan_group_get_device(bond->vlgrp, vid);
- slave_dev->vlan_rx_kill_vid(slave_dev, vid);
+ slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vid);
vlan_group_set_device(bond->vlgrp, vid, vlan_dev);
}
}
@@ -523,26 +529,23 @@ static void bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)
static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *slave_dev)
{
struct vlan_entry *vlan;
+ const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
write_lock_bh(&bond->lock);
- if (list_empty(&bond->vlan_list)) {
+ if (list_empty(&bond->vlan_list))
goto out;
- }
if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
- slave_dev->vlan_rx_register) {
- slave_dev->vlan_rx_register(slave_dev, bond->vlgrp);
- }
+ slave_ops->ndo_vlan_rx_register)
+ slave_ops->ndo_vlan_rx_register(slave_dev, bond->vlgrp);
if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
- !(slave_dev->vlan_rx_add_vid)) {
+ !(slave_ops->ndo_vlan_rx_add_vid))
goto out;
- }
- list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
- slave_dev->vlan_rx_add_vid(slave_dev, vlan->vlan_id);
- }
+ list_for_each_entry(vlan, &bond->vlan_list, vlan_list)
+ slave_ops->ndo_vlan_rx_add_vid(slave_dev, vlan->vlan_id);
out:
write_unlock_bh(&bond->lock);
@@ -550,34 +553,32 @@ out:
static void bond_del_vlans_from_slave(struct bonding *bond, struct net_device *slave_dev)
{
+ const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
struct vlan_entry *vlan;
struct net_device *vlan_dev;
write_lock_bh(&bond->lock);
- if (list_empty(&bond->vlan_list)) {
+ if (list_empty(&bond->vlan_list))
goto out;
- }
if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
- !(slave_dev->vlan_rx_kill_vid)) {
+ !(slave_ops->ndo_vlan_rx_kill_vid))
goto unreg;
- }
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
/* Save and then restore vlan_dev in the grp array,
* since the slave's driver might clear it.
*/
vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
- slave_dev->vlan_rx_kill_vid(slave_dev, vlan->vlan_id);
+ slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vlan->vlan_id);
vlan_group_set_device(bond->vlgrp, vlan->vlan_id, vlan_dev);
}
unreg:
if ((slave_dev->features & NETIF_F_HW_VLAN_RX) &&
- slave_dev->vlan_rx_register) {
- slave_dev->vlan_rx_register(slave_dev, NULL);
- }
+ slave_ops->ndo_vlan_rx_register)
+ slave_ops->ndo_vlan_rx_register(slave_dev, NULL);
out:
write_unlock_bh(&bond->lock);
@@ -686,15 +687,15 @@ static int bond_update_speed_duplex(struct slave *slave)
*/
static int bond_check_dev_link(struct bonding *bond, struct net_device *slave_dev, int reporting)
{
+ const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
static int (* ioctl)(struct net_device *, struct ifreq *, int);
struct ifreq ifr;
struct mii_ioctl_data *mii;
- if (bond->params.use_carrier) {
+ if (bond->params.use_carrier)
return netif_carrier_ok(slave_dev) ? BMSR_LSTATUS : 0;
- }
- ioctl = slave_dev->do_ioctl;
+ ioctl = slave_ops->ndo_do_ioctl;
if (ioctl) {
/* TODO: set pointer to correct ioctl on a per team member */
/* bases to make this more efficient. that is, once */
@@ -927,7 +928,7 @@ static int bond_mc_list_copy(struct dev_mc_list *mc_list, struct bonding *bond,
*/
static void bond_mc_list_flush(struct net_device *bond_dev, struct net_device *slave_dev)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
struct dev_mc_list *dmi;
for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) {
@@ -1164,10 +1165,8 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
bond_3ad_handle_link_change(new_active, BOND_LINK_UP);
}
- if ((bond->params.mode == BOND_MODE_TLB) ||
- (bond->params.mode == BOND_MODE_ALB)) {
+ if (bond_is_lb(bond))
bond_alb_handle_link_change(bond, new_active, BOND_LINK_UP);
- }
} else {
if (USES_PRIMARY(bond->params.mode)) {
printk(KERN_INFO DRV_NAME
@@ -1182,8 +1181,7 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
bond_mc_swap(bond, new_active, old_active);
}
- if ((bond->params.mode == BOND_MODE_TLB) ||
- (bond->params.mode == BOND_MODE_ALB)) {
+ if (bond_is_lb(bond)) {
bond_alb_handle_active_change(bond, new_active);
if (old_active)
bond_set_slave_inactive_flags(old_active);
@@ -1208,6 +1206,9 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
bond->send_grat_arp = bond->params.num_grat_arp;
bond_send_gratuitous_arp(bond);
+ bond->send_unsol_na = bond->params.num_unsol_na;
+ bond_send_unsolicited_na(bond);
+
write_unlock_bh(&bond->curr_slave_lock);
read_unlock(&bond->lock);
@@ -1315,9 +1316,9 @@ static void bond_detach_slave(struct bonding *bond, struct slave *slave)
static int bond_sethwaddr(struct net_device *bond_dev,
struct net_device *slave_dev)
{
- dprintk("bond_dev=%p\n", bond_dev);
- dprintk("slave_dev=%p\n", slave_dev);
- dprintk("slave_dev->addr_len=%d\n", slave_dev->addr_len);
+ pr_debug("bond_dev=%p\n", bond_dev);
+ pr_debug("slave_dev=%p\n", slave_dev);
+ pr_debug("slave_dev->addr_len=%d\n", slave_dev->addr_len);
memcpy(bond_dev->dev_addr, slave_dev->dev_addr, slave_dev->addr_len);
return 0;
}
@@ -1364,14 +1365,12 @@ done:
return 0;
}
-
static void bond_setup_by_slave(struct net_device *bond_dev,
struct net_device *slave_dev)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
- bond_dev->neigh_setup = slave_dev->neigh_setup;
- bond_dev->header_ops = slave_dev->header_ops;
+ bond_dev->header_ops = slave_dev->header_ops;
bond_dev->type = slave_dev->type;
bond_dev->hard_header_len = slave_dev->hard_header_len;
@@ -1385,7 +1384,8 @@ static void bond_setup_by_slave(struct net_device *bond_dev,
/* enslave device <slave> to bond device <master> */
int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
+ const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
struct slave *new_slave = NULL;
struct dev_mc_list *dmi;
struct sockaddr addr;
@@ -1394,7 +1394,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
int res = 0;
if (!bond->params.use_carrier && slave_dev->ethtool_ops == NULL &&
- slave_dev->do_ioctl == NULL) {
+ slave_ops->ndo_do_ioctl == NULL) {
printk(KERN_WARNING DRV_NAME
": %s: Warning: no link monitoring support for %s\n",
bond_dev->name, slave_dev->name);
@@ -1409,14 +1409,14 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
/* already enslaved */
if (slave_dev->flags & IFF_SLAVE) {
- dprintk("Error, Device was already enslaved\n");
+ pr_debug("Error, Device was already enslaved\n");
return -EBUSY;
}
/* vlan challenged mutual exclusion */
/* no need to lock since we're protected by rtnl_lock */
if (slave_dev->features & NETIF_F_VLAN_CHALLENGED) {
- dprintk("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
+ pr_debug("%s: NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
if (!list_empty(&bond->vlan_list)) {
printk(KERN_ERR DRV_NAME
": %s: Error: cannot enslave VLAN "
@@ -1434,7 +1434,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
bond_dev->features |= NETIF_F_VLAN_CHALLENGED;
}
} else {
- dprintk("%s: ! NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
+ pr_debug("%s: ! NETIF_F_VLAN_CHALLENGED\n", slave_dev->name);
if (bond->slave_cnt == 0) {
/* First slave, and it is not VLAN challenged,
* so remove the block of adding VLANs over the bond.
@@ -1476,7 +1476,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
goto err_undo_flags;
}
- if (slave_dev->set_mac_address == NULL) {
+ if (slave_ops->ndo_set_mac_address == NULL) {
if (bond->slave_cnt == 0) {
printk(KERN_WARNING DRV_NAME
": %s: Warning: The first slave device "
@@ -1522,28 +1522,27 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
addr.sa_family = slave_dev->type;
res = dev_set_mac_address(slave_dev, &addr);
if (res) {
- dprintk("Error %d calling set_mac_address\n", res);
+ pr_debug("Error %d calling set_mac_address\n", res);
goto err_free;
}
}
res = netdev_set_master(slave_dev, bond_dev);
if (res) {
- dprintk("Error %d calling netdev_set_master\n", res);
+ pr_debug("Error %d calling netdev_set_master\n", res);
goto err_restore_mac;
}
/* open the slave since the application closed it */
res = dev_open(slave_dev);
if (res) {
- dprintk("Openning slave %s failed\n", slave_dev->name);
+ pr_debug("Openning slave %s failed\n", slave_dev->name);
goto err_unset_master;
}
new_slave->dev = slave_dev;
slave_dev->priv_flags |= IFF_BONDING;
- if ((bond->params.mode == BOND_MODE_TLB) ||
- (bond->params.mode == BOND_MODE_ALB)) {
+ if (bond_is_lb(bond)) {
/* bond_alb_init_slave() must be called before all other stages since
* it might fail and we do not want to have to undo everything
*/
@@ -1641,18 +1640,18 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
if (!bond->params.miimon ||
(bond_check_dev_link(bond, slave_dev, 0) == BMSR_LSTATUS)) {
if (bond->params.updelay) {
- dprintk("Initial state of slave_dev is "
+ pr_debug("Initial state of slave_dev is "
"BOND_LINK_BACK\n");
new_slave->link = BOND_LINK_BACK;
new_slave->delay = bond->params.updelay;
} else {
- dprintk("Initial state of slave_dev is "
+ pr_debug("Initial state of slave_dev is "
"BOND_LINK_UP\n");
new_slave->link = BOND_LINK_UP;
}
new_slave->jiffies = jiffies;
} else {
- dprintk("Initial state of slave_dev is "
+ pr_debug("Initial state of slave_dev is "
"BOND_LINK_DOWN\n");
new_slave->link = BOND_LINK_DOWN;
}
@@ -1713,7 +1712,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
bond_set_slave_inactive_flags(new_slave);
break;
default:
- dprintk("This slave is always active in trunk mode\n");
+ pr_debug("This slave is always active in trunk mode\n");
/* always active in trunk mode */
new_slave->state = BOND_STATE_ACTIVE;
@@ -1787,11 +1786,10 @@ err_undo_flags:
*/
int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave, *oldcurrent;
struct sockaddr addr;
int mac_addr_differ;
- DECLARE_MAC_BUF(mac);
/* slave is not a slave or master is not master of this slave */
if (!(slave_dev->flags & IFF_SLAVE) ||
@@ -1820,11 +1818,11 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
if (!mac_addr_differ && (bond->slave_cnt > 1))
printk(KERN_WARNING DRV_NAME
": %s: Warning: the permanent HWaddr of %s - "
- "%s - is still in use by %s. "
+ "%pM - is still in use by %s. "
"Set the HWaddr of %s to a different address "
"to avoid conflicts.\n",
bond_dev->name, slave_dev->name,
- print_mac(mac, slave->perm_hwaddr),
+ slave->perm_hwaddr,
bond_dev->name, slave_dev->name);
}
@@ -1860,8 +1858,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
bond_change_active_slave(bond, NULL);
}
- if ((bond->params.mode == BOND_MODE_TLB) ||
- (bond->params.mode == BOND_MODE_ALB)) {
+ if (bond_is_lb(bond)) {
/* Must be called only after the slave has been
* detached from the list and the curr_active_slave
* has been cleared (if our_slave == old_current),
@@ -1981,7 +1978,7 @@ void bond_destroy(struct bonding *bond)
static void bond_destructor(struct net_device *bond_dev)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
if (bond->wq)
destroy_workqueue(bond->wq);
@@ -1999,7 +1996,7 @@ static void bond_destructor(struct net_device *bond_dev)
*/
int bond_release_and_destroy(struct net_device *bond_dev, struct net_device *slave_dev)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
int ret;
ret = bond_release(bond_dev, slave_dev);
@@ -2016,7 +2013,7 @@ int bond_release_and_destroy(struct net_device *bond_dev, struct net_device *sl
*/
static int bond_release_all(struct net_device *bond_dev)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave;
struct net_device *slave_dev;
struct sockaddr addr;
@@ -2050,8 +2047,7 @@ static int bond_release_all(struct net_device *bond_dev)
*/
write_unlock_bh(&bond->lock);
- if ((bond->params.mode == BOND_MODE_TLB) ||
- (bond->params.mode == BOND_MODE_ALB)) {
+ if (bond_is_lb(bond)) {
/* must be called only after the slave
* has been detached from the list
*/
@@ -2147,7 +2143,7 @@ out:
*/
static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_device *slave_dev)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
struct slave *old_active = NULL;
struct slave *new_active = NULL;
int res = 0;
@@ -2196,7 +2192,7 @@ static int bond_ioctl_change_active(struct net_device *bond_dev, struct net_devi
static int bond_info_query(struct net_device *bond_dev, struct ifbond *info)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
info->bond_mode = bond->params.mode;
info->miimon = bond->params.miimon;
@@ -2210,7 +2206,7 @@ static int bond_info_query(struct net_device *bond_dev, struct ifbond *info)
static int bond_slave_info_query(struct net_device *bond_dev, struct ifslave *info)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave;
int i, found = 0;
@@ -2378,8 +2374,7 @@ static void bond_miimon_commit(struct bonding *bond)
if (bond->params.mode == BOND_MODE_8023AD)
bond_3ad_handle_link_change(slave, BOND_LINK_UP);
- if ((bond->params.mode == BOND_MODE_TLB) ||
- (bond->params.mode == BOND_MODE_ALB))
+ if (bond_is_lb(bond))
bond_alb_handle_link_change(bond, slave,
BOND_LINK_UP);
@@ -2464,6 +2459,12 @@ void bond_mii_monitor(struct work_struct *work)
read_unlock(&bond->curr_slave_lock);
}
+ if (bond->send_unsol_na) {
+ read_lock(&bond->curr_slave_lock);
+ bond_send_unsolicited_na(bond);
+ read_unlock(&bond->curr_slave_lock);
+ }
+
if (bond_miimon_inspect(bond)) {
read_unlock(&bond->lock);
rtnl_lock();
@@ -2532,7 +2533,7 @@ static void bond_arp_send(struct net_device *slave_dev, int arp_op, __be32 dest_
{
struct sk_buff *skb;
- dprintk("arp %d on slave %s: dst %x src %x vid %d\n", arp_op,
+ pr_debug("arp %d on slave %s: dst %x src %x vid %d\n", arp_op,
slave_dev->name, dest_ip, src_ip, vlan_id);
skb = arp_create(arp_op, ETH_P_ARP, dest_ip, slave_dev, src_ip,
@@ -2565,9 +2566,9 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
if (!targets[i])
continue;
- dprintk("basa: target %x\n", targets[i]);
+ pr_debug("basa: target %x\n", targets[i]);
if (list_empty(&bond->vlan_list)) {
- dprintk("basa: empty vlan: arp_send\n");
+ pr_debug("basa: empty vlan: arp_send\n");
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
bond->master_ip, 0);
continue;
@@ -2586,8 +2587,8 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
if (rv) {
if (net_ratelimit()) {
printk(KERN_WARNING DRV_NAME
- ": %s: no route to arp_ip_target %u.%u.%u.%u\n",
- bond->dev->name, NIPQUAD(fl.fl4_dst));
+ ": %s: no route to arp_ip_target %pI4\n",
+ bond->dev->name, &fl.fl4_dst);
}
continue;
}
@@ -2597,7 +2598,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
*/
if (rt->u.dst.dev == bond->dev) {
ip_rt_put(rt);
- dprintk("basa: rtdev == bond->dev: arp_send\n");
+ pr_debug("basa: rtdev == bond->dev: arp_send\n");
bond_arp_send(slave->dev, ARPOP_REQUEST, targets[i],
bond->master_ip, 0);
continue;
@@ -2608,7 +2609,7 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
vlan_dev = vlan_group_get_device(bond->vlgrp, vlan->vlan_id);
if (vlan_dev == rt->u.dst.dev) {
vlan_id = vlan->vlan_id;
- dprintk("basa: vlan match on %s %d\n",
+ pr_debug("basa: vlan match on %s %d\n",
vlan_dev->name, vlan_id);
break;
}
@@ -2623,8 +2624,8 @@ static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
if (net_ratelimit()) {
printk(KERN_WARNING DRV_NAME
- ": %s: no path to arp_ip_target %u.%u.%u.%u via rt.dev %s\n",
- bond->dev->name, NIPQUAD(fl.fl4_dst),
+ ": %s: no path to arp_ip_target %pI4 via rt.dev %s\n",
+ bond->dev->name, &fl.fl4_dst,
rt->u.dst.dev ? rt->u.dst.dev->name : "NULL");
}
ip_rt_put(rt);
@@ -2643,7 +2644,7 @@ static void bond_send_gratuitous_arp(struct bonding *bond)
struct vlan_entry *vlan;
struct net_device *vlan_dev;
- dprintk("bond_send_grat_arp: bond %s slave %s\n", bond->dev->name,
+ pr_debug("bond_send_grat_arp: bond %s slave %s\n", bond->dev->name,
slave ? slave->dev->name : "NULL");
if (!slave || !bond->send_grat_arp ||
@@ -2673,10 +2674,8 @@ static void bond_validate_arp(struct bonding *bond, struct slave *slave, __be32
targets = bond->params.arp_targets;
for (i = 0; (i < BOND_MAX_ARP_TARGETS) && targets[i]; i++) {
- dprintk("bva: sip %u.%u.%u.%u tip %u.%u.%u.%u t[%d] "
- "%u.%u.%u.%u bhti(tip) %d\n",
- NIPQUAD(sip), NIPQUAD(tip), i, NIPQUAD(targets[i]),
- bond_has_this_ip(bond, tip));
+ pr_debug("bva: sip %pI4 tip %pI4 t[%d] %pI4 bhti(tip) %d\n",
+ &sip, &tip, i, &targets[i], bond_has_this_ip(bond, tip));
if (sip == targets[i]) {
if (bond_has_this_ip(bond, tip))
slave->last_arp_rx = jiffies;
@@ -2699,10 +2698,10 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack
if (!(dev->priv_flags & IFF_BONDING) || !(dev->flags & IFF_MASTER))
goto out;
- bond = dev->priv;
+ bond = netdev_priv(dev);
read_lock(&bond->lock);
- dprintk("bond_arp_rcv: bond %s skb->dev %s orig_dev %s\n",
+ pr_debug("bond_arp_rcv: bond %s skb->dev %s orig_dev %s\n",
bond->dev->name, skb->dev ? skb->dev->name : "NULL",
orig_dev ? orig_dev->name : "NULL");
@@ -2728,10 +2727,10 @@ static int bond_arp_rcv(struct sk_buff *skb, struct net_device *dev, struct pack
arp_ptr += 4 + dev->addr_len;
memcpy(&tip, arp_ptr, 4);
- dprintk("bond_arp_rcv: %s %s/%d av %d sv %d sip %u.%u.%u.%u"
- " tip %u.%u.%u.%u\n", bond->dev->name, slave->dev->name,
- slave->state, bond->params.arp_validate,
- slave_do_arp_validate(bond, slave), NIPQUAD(sip), NIPQUAD(tip));
+ pr_debug("bond_arp_rcv: %s %s/%d av %d sv %d sip %pI4 tip %pI4\n",
+ bond->dev->name, slave->dev->name, slave->state,
+ bond->params.arp_validate, slave_do_arp_validate(bond, slave),
+ &sip, &tip);
/*
* Backup slaves won't see the ARP reply, but do come through
@@ -3161,6 +3160,12 @@ void bond_activebackup_arp_mon(struct work_struct *work)
read_unlock(&bond->curr_slave_lock);
}
+ if (bond->send_unsol_na) {
+ read_lock(&bond->curr_slave_lock);
+ bond_send_unsolicited_na(bond);
+ read_unlock(&bond->curr_slave_lock);
+ }
+
if (bond_ab_arp_inspect(bond, delta_in_ticks)) {
read_unlock(&bond->lock);
rtnl_lock();
@@ -3239,7 +3244,6 @@ static void bond_info_show_master(struct seq_file *seq)
struct bonding *bond = seq->private;
struct slave *curr;
int i;
- u32 target;
read_lock(&bond->curr_slave_lock);
curr = bond->curr_active_slave;
@@ -3293,8 +3297,7 @@ static void bond_info_show_master(struct seq_file *seq)
continue;
if (printed)
seq_printf(seq, ",");
- target = ntohl(bond->params.arp_targets[i]);
- seq_printf(seq, " %d.%d.%d.%d", HIPQUAD(target));
+ seq_printf(seq, " %pI4", &bond->params.arp_targets[i]);
printed = 1;
}
seq_printf(seq, "\n");
@@ -3302,11 +3305,12 @@ static void bond_info_show_master(struct seq_file *seq)
if (bond->params.mode == BOND_MODE_8023AD) {
struct ad_info ad_info;
- DECLARE_MAC_BUF(mac);
seq_puts(seq, "\n802.3ad info\n");
seq_printf(seq, "LACP rate: %s\n",
(bond->params.lacp_fast) ? "fast" : "slow");
+ seq_printf(seq, "Aggregator selection policy (ad_select): %s\n",
+ ad_select_tbl[bond->params.ad_select].modename);
if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
seq_printf(seq, "bond %s has no active aggregator\n",
@@ -3322,8 +3326,8 @@ static void bond_info_show_master(struct seq_file *seq)
ad_info.actor_key);
seq_printf(seq, "\tPartner Key: %d\n",
ad_info.partner_key);
- seq_printf(seq, "\tPartner Mac Address: %s\n",
- print_mac(mac, ad_info.partner_system));
+ seq_printf(seq, "\tPartner Mac Address: %pM\n",
+ ad_info.partner_system);
}
}
}
@@ -3331,7 +3335,6 @@ static void bond_info_show_master(struct seq_file *seq)
static void bond_info_show_slave(struct seq_file *seq, const struct slave *slave)
{
struct bonding *bond = seq->private;
- DECLARE_MAC_BUF(mac);
seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
seq_printf(seq, "MII Status: %s\n",
@@ -3339,9 +3342,7 @@ static void bond_info_show_slave(struct seq_file *seq, const struct slave *slave
seq_printf(seq, "Link Failure Count: %u\n",
slave->link_failure_count);
- seq_printf(seq,
- "Permanent HW addr: %s\n",
- print_mac(mac, slave->perm_hwaddr));
+ seq_printf(seq, "Permanent HW addr: %pM\n", slave->perm_hwaddr);
if (bond->params.mode == BOND_MODE_8023AD) {
const struct aggregator *agg
@@ -3506,7 +3507,7 @@ static int bond_event_changename(struct bonding *bond)
static int bond_master_netdev_event(unsigned long event, struct net_device *bond_dev)
{
- struct bonding *event_bond = bond_dev->priv;
+ struct bonding *event_bond = netdev_priv(bond_dev);
switch (event) {
case NETDEV_CHANGENAME:
@@ -3524,7 +3525,7 @@ static int bond_master_netdev_event(unsigned long event, struct net_device *bond
static int bond_slave_netdev_event(unsigned long event, struct net_device *slave_dev)
{
struct net_device *bond_dev = slave_dev->master;
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
switch (event) {
case NETDEV_UNREGISTER:
@@ -3591,7 +3592,7 @@ static int bond_netdev_event(struct notifier_block *this, unsigned long event, v
if (dev_net(event_dev) != &init_net)
return NOTIFY_DONE;
- dprintk("event_dev: %s, event: %lx\n",
+ pr_debug("event_dev: %s, event: %lx\n",
(event_dev ? event_dev->name : "None"),
event);
@@ -3599,12 +3600,12 @@ static int bond_netdev_event(struct notifier_block *this, unsigned long event, v
return NOTIFY_DONE;
if (event_dev->flags & IFF_MASTER) {
- dprintk("IFF_MASTER\n");
+ pr_debug("IFF_MASTER\n");
return bond_master_netdev_event(event, event_dev);
}
if (event_dev->flags & IFF_SLAVE) {
- dprintk("IFF_SLAVE\n");
+ pr_debug("IFF_SLAVE\n");
return bond_slave_netdev_event(event, event_dev);
}
@@ -3775,12 +3776,11 @@ static int bond_xmit_hash_policy_l2(struct sk_buff *skb,
static int bond_open(struct net_device *bond_dev)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
bond->kill_timers = 0;
- if ((bond->params.mode == BOND_MODE_TLB) ||
- (bond->params.mode == BOND_MODE_ALB)) {
+ if (bond_is_lb(bond)) {
/* bond_alb_initialize must be called before the timer
* is started.
*/
@@ -3816,6 +3816,7 @@ static int bond_open(struct net_device *bond_dev)
queue_delayed_work(bond->wq, &bond->ad_work, 0);
/* register to receive LACPDUs */
bond_register_lacpdu(bond);
+ bond_3ad_initiate_agg_selection(bond, 1);
}
return 0;
@@ -3823,7 +3824,7 @@ static int bond_open(struct net_device *bond_dev)
static int bond_close(struct net_device *bond_dev)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
if (bond->params.mode == BOND_MODE_8023AD) {
/* Unregister the receive of LACPDUs */
@@ -3836,6 +3837,7 @@ static int bond_close(struct net_device *bond_dev)
write_lock_bh(&bond->lock);
bond->send_grat_arp = 0;
+ bond->send_unsol_na = 0;
/* signal timers not to re-arm */
bond->kill_timers = 1;
@@ -3863,8 +3865,7 @@ static int bond_close(struct net_device *bond_dev)
}
- if ((bond->params.mode == BOND_MODE_TLB) ||
- (bond->params.mode == BOND_MODE_ALB)) {
+ if (bond_is_lb(bond)) {
/* Must be called only after all
* slaves have been released
*/
@@ -3876,8 +3877,8 @@ static int bond_close(struct net_device *bond_dev)
static struct net_device_stats *bond_get_stats(struct net_device *bond_dev)
{
- struct bonding *bond = bond_dev->priv;
- struct net_device_stats *stats = &(bond->stats), *sstats;
+ struct bonding *bond = netdev_priv(bond_dev);
+ struct net_device_stats *stats = &bond->stats;
struct net_device_stats local_stats;
struct slave *slave;
int i;
@@ -3887,7 +3888,8 @@ static struct net_device_stats *bond_get_stats(struct net_device *bond_dev)
read_lock_bh(&bond->lock);
bond_for_each_slave(bond, slave, i) {
- sstats = slave->dev->get_stats(slave->dev);
+ const struct net_device_stats *sstats = dev_get_stats(slave->dev);
+
local_stats.rx_packets += sstats->rx_packets;
local_stats.rx_bytes += sstats->rx_bytes;
local_stats.rx_errors += sstats->rx_errors;
@@ -3932,7 +3934,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
struct mii_ioctl_data *mii = NULL;
int res = 0;
- dprintk("bond_ioctl: master=%s, cmd=%d\n",
+ pr_debug("bond_ioctl: master=%s, cmd=%d\n",
bond_dev->name, cmd);
switch (cmd) {
@@ -3954,7 +3956,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
}
if (mii->reg_num == 1) {
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
mii->val_out = 0;
read_lock(&bond->lock);
read_lock(&bond->curr_slave_lock);
@@ -4010,12 +4012,12 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
down_write(&(bonding_rwsem));
slave_dev = dev_get_by_name(&init_net, ifr->ifr_slave);
- dprintk("slave_dev=%p: \n", slave_dev);
+ pr_debug("slave_dev=%p: \n", slave_dev);
if (!slave_dev) {
res = -ENODEV;
} else {
- dprintk("slave_dev->name=%s: \n", slave_dev->name);
+ pr_debug("slave_dev->name=%s: \n", slave_dev->name);
switch (cmd) {
case BOND_ENSLAVE_OLD:
case SIOCBONDENSLAVE:
@@ -4046,7 +4048,7 @@ static int bond_do_ioctl(struct net_device *bond_dev, struct ifreq *ifr, int cmd
static void bond_set_multicast_list(struct net_device *bond_dev)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
struct dev_mc_list *dmi;
/*
@@ -4102,17 +4104,31 @@ static void bond_set_multicast_list(struct net_device *bond_dev)
read_unlock(&bond->lock);
}
+static int bond_neigh_setup(struct net_device *dev, struct neigh_parms *parms)
+{
+ struct bonding *bond = netdev_priv(dev);
+ struct slave *slave = bond->first_slave;
+
+ if (slave) {
+ const struct net_device_ops *slave_ops
+ = slave->dev->netdev_ops;
+ if (slave_ops->ndo_neigh_setup)
+ return slave_ops->ndo_neigh_setup(dev, parms);
+ }
+ return 0;
+}
+
/*
* Change the MTU of all of a master's slaves to match the master
*/
static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave, *stop_at;
int res = 0;
int i;
- dprintk("bond=%p, name=%s, new_mtu=%d\n", bond,
+ pr_debug("bond=%p, name=%s, new_mtu=%d\n", bond,
(bond_dev ? bond_dev->name : "None"), new_mtu);
/* Can't hold bond->lock with bh disabled here since
@@ -4131,7 +4147,7 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
*/
bond_for_each_slave(bond, slave, i) {
- dprintk("s %p s->p %p c_m %p\n", slave,
+ pr_debug("s %p s->p %p c_m %p\n", slave,
slave->prev, slave->dev->change_mtu);
res = dev_set_mtu(slave->dev, new_mtu);
@@ -4145,7 +4161,7 @@ static int bond_change_mtu(struct net_device *bond_dev, int new_mtu)
* means changing their mtu from timer context, which
* is probably not a good idea.
*/
- dprintk("err %d %s\n", res, slave->dev->name);
+ pr_debug("err %d %s\n", res, slave->dev->name);
goto unwind;
}
}
@@ -4162,7 +4178,7 @@ unwind:
tmp_res = dev_set_mtu(slave->dev, bond_dev->mtu);
if (tmp_res) {
- dprintk("unwind err %d dev %s\n", tmp_res,
+ pr_debug("unwind err %d dev %s\n", tmp_res,
slave->dev->name);
}
}
@@ -4179,13 +4195,17 @@ unwind:
*/
static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
struct sockaddr *sa = addr, tmp_sa;
struct slave *slave, *stop_at;
int res = 0;
int i;
- dprintk("bond=%p, name=%s\n", bond, (bond_dev ? bond_dev->name : "None"));
+ if (bond->params.mode == BOND_MODE_ALB)
+ return bond_alb_set_mac_address(bond_dev, addr);
+
+
+ pr_debug("bond=%p, name=%s\n", bond, (bond_dev ? bond_dev->name : "None"));
/*
* If fail_over_mac is set to active, do nothing and return
@@ -4214,11 +4234,12 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
*/
bond_for_each_slave(bond, slave, i) {
- dprintk("slave %p %s\n", slave, slave->dev->name);
+ const struct net_device_ops *slave_ops = slave->dev->netdev_ops;
+ pr_debug("slave %p %s\n", slave, slave->dev->name);
- if (slave->dev->set_mac_address == NULL) {
+ if (slave_ops->ndo_set_mac_address == NULL) {
res = -EOPNOTSUPP;
- dprintk("EOPNOTSUPP %s\n", slave->dev->name);
+ pr_debug("EOPNOTSUPP %s\n", slave->dev->name);
goto unwind;
}
@@ -4230,7 +4251,7 @@ static int bond_set_mac_address(struct net_device *bond_dev, void *addr)
* breakage anyway until ARP finish
* updating, so...
*/
- dprintk("err %d %s\n", res, slave->dev->name);
+ pr_debug("err %d %s\n", res, slave->dev->name);
goto unwind;
}
}
@@ -4250,7 +4271,7 @@ unwind:
tmp_res = dev_set_mac_address(slave->dev, &tmp_sa);
if (tmp_res) {
- dprintk("unwind err %d dev %s\n", tmp_res,
+ pr_debug("unwind err %d dev %s\n", tmp_res,
slave->dev->name);
}
}
@@ -4260,7 +4281,7 @@ unwind:
static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave, *start_at;
int i, slave_no, res = 1;
@@ -4309,7 +4330,7 @@ out:
*/
static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_dev)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
int res = 1;
read_lock(&bond->lock);
@@ -4341,7 +4362,7 @@ out:
*/
static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave, *start_at;
int slave_no;
int i;
@@ -4387,7 +4408,7 @@ out:
*/
static int bond_xmit_broadcast(struct sk_buff *skb, struct net_device *bond_dev)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave, *start_at;
struct net_device *tx_dev = NULL;
int i;
@@ -4463,6 +4484,35 @@ static void bond_set_xmit_hash_policy(struct bonding *bond)
}
}
+static int bond_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ const struct bonding *bond = netdev_priv(dev);
+
+ switch (bond->params.mode) {
+ case BOND_MODE_ROUNDROBIN:
+ return bond_xmit_roundrobin(skb, dev);
+ case BOND_MODE_ACTIVEBACKUP:
+ return bond_xmit_activebackup(skb, dev);
+ case BOND_MODE_XOR:
+ return bond_xmit_xor(skb, dev);
+ case BOND_MODE_BROADCAST:
+ return bond_xmit_broadcast(skb, dev);
+ case BOND_MODE_8023AD:
+ return bond_3ad_xmit_xor(skb, dev);
+ case BOND_MODE_ALB:
+ case BOND_MODE_TLB:
+ return bond_alb_xmit(skb, dev);
+ default:
+ /* Should never happen, mode already checked */
+ printk(KERN_ERR DRV_NAME ": %s: Error: Unknown bonding mode %d\n",
+ dev->name, bond->params.mode);
+ WARN_ON_ONCE(1);
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+}
+
+
/*
* set bond mode specific net device operations
*/
@@ -4472,29 +4522,22 @@ void bond_set_mode_ops(struct bonding *bond, int mode)
switch (mode) {
case BOND_MODE_ROUNDROBIN:
- bond_dev->hard_start_xmit = bond_xmit_roundrobin;
break;
case BOND_MODE_ACTIVEBACKUP:
- bond_dev->hard_start_xmit = bond_xmit_activebackup;
break;
case BOND_MODE_XOR:
- bond_dev->hard_start_xmit = bond_xmit_xor;
bond_set_xmit_hash_policy(bond);
break;
case BOND_MODE_BROADCAST:
- bond_dev->hard_start_xmit = bond_xmit_broadcast;
break;
case BOND_MODE_8023AD:
bond_set_master_3ad_flags(bond);
- bond_dev->hard_start_xmit = bond_3ad_xmit_xor;
bond_set_xmit_hash_policy(bond);
break;
case BOND_MODE_ALB:
bond_set_master_alb_flags(bond);
/* FALLTHRU */
case BOND_MODE_TLB:
- bond_dev->hard_start_xmit = bond_alb_xmit;
- bond_dev->set_mac_address = bond_alb_set_mac_address;
break;
default:
/* Should never happen, mode already checked */
@@ -4524,15 +4567,30 @@ static const struct ethtool_ops bond_ethtool_ops = {
.get_flags = ethtool_op_get_flags,
};
+static const struct net_device_ops bond_netdev_ops = {
+ .ndo_open = bond_open,
+ .ndo_stop = bond_close,
+ .ndo_start_xmit = bond_start_xmit,
+ .ndo_get_stats = bond_get_stats,
+ .ndo_do_ioctl = bond_do_ioctl,
+ .ndo_set_multicast_list = bond_set_multicast_list,
+ .ndo_change_mtu = bond_change_mtu,
+ .ndo_set_mac_address = bond_set_mac_address,
+ .ndo_neigh_setup = bond_neigh_setup,
+ .ndo_vlan_rx_register = bond_vlan_rx_register,
+ .ndo_vlan_rx_add_vid = bond_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = bond_vlan_rx_kill_vid,
+};
+
/*
* Does not allocate but creates a /proc entry.
* Allowed to fail.
*/
static int bond_init(struct net_device *bond_dev, struct bond_params *params)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
- dprintk("Begin bond_init for %s\n", bond_dev->name);
+ pr_debug("Begin bond_init for %s\n", bond_dev->name);
/* initialize rwlocks */
rwlock_init(&bond->lock);
@@ -4551,20 +4609,13 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
bond->primary_slave = NULL;
bond->dev = bond_dev;
bond->send_grat_arp = 0;
+ bond->send_unsol_na = 0;
bond->setup_by_slave = 0;
INIT_LIST_HEAD(&bond->vlan_list);
/* Initialize the device entry points */
- bond_dev->open = bond_open;
- bond_dev->stop = bond_close;
- bond_dev->get_stats = bond_get_stats;
- bond_dev->do_ioctl = bond_do_ioctl;
+ bond_dev->netdev_ops = &bond_netdev_ops;
bond_dev->ethtool_ops = &bond_ethtool_ops;
- bond_dev->set_multicast_list = bond_set_multicast_list;
- bond_dev->change_mtu = bond_change_mtu;
- bond_dev->set_mac_address = bond_set_mac_address;
- bond_dev->validate_addr = NULL;
-
bond_set_mode_ops(bond, bond->params.mode);
bond_dev->destructor = bond_destructor;
@@ -4573,6 +4624,8 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
bond_dev->tx_queue_len = 0;
bond_dev->flags |= IFF_MASTER|IFF_MULTICAST;
bond_dev->priv_flags |= IFF_BONDING;
+ if (bond->params.arp_interval)
+ bond_dev->priv_flags |= IFF_MASTER_ARPMON;
/* At first, we block adding VLANs. That's the only way to
* prevent problems that occur when adding VLANs over an
@@ -4591,9 +4644,6 @@ static int bond_init(struct net_device *bond_dev, struct bond_params *params)
* when there are slaves that are not hw accel
* capable
*/
- bond_dev->vlan_rx_register = bond_vlan_rx_register;
- bond_dev->vlan_rx_add_vid = bond_vlan_rx_add_vid;
- bond_dev->vlan_rx_kill_vid = bond_vlan_rx_kill_vid;
bond_dev->features |= (NETIF_F_HW_VLAN_TX |
NETIF_F_HW_VLAN_RX |
NETIF_F_HW_VLAN_FILTER);
@@ -4632,7 +4682,7 @@ static void bond_work_cancel_all(struct bonding *bond)
*/
static void bond_deinit(struct net_device *bond_dev)
{
- struct bonding *bond = bond_dev->priv;
+ struct bonding *bond = netdev_priv(bond_dev);
list_del(&bond->bond_list);
@@ -4672,7 +4722,7 @@ static void bond_free_all(void)
* some mode names are substrings of other names, and calls from sysfs
* may have whitespace in the name (trailing newlines, for example).
*/
-int bond_parse_parm(const char *buf, struct bond_parm_tbl *tbl)
+int bond_parse_parm(const char *buf, const struct bond_parm_tbl *tbl)
{
int mode = -1, i, rv;
char *p, modestr[BOND_MAX_MODENAME_LEN + 1] = { 0, };
@@ -4751,6 +4801,23 @@ static int bond_check_params(struct bond_params *params)
}
}
+ if (ad_select) {
+ params->ad_select = bond_parse_parm(ad_select, ad_select_tbl);
+ if (params->ad_select == -1) {
+ printk(KERN_ERR DRV_NAME
+ ": Error: Invalid ad_select \"%s\"\n",
+ ad_select == NULL ? "NULL" : ad_select);
+ return -EINVAL;
+ }
+
+ if (bond_mode != BOND_MODE_8023AD) {
+ printk(KERN_WARNING DRV_NAME
+ ": ad_select param only affects 802.3ad mode\n");
+ }
+ } else {
+ params->ad_select = BOND_AD_STABLE;
+ }
+
if (max_bonds < 0 || max_bonds > INT_MAX) {
printk(KERN_WARNING DRV_NAME
": Warning: max_bonds (%d) not in range %d-%d, so it "
@@ -4798,6 +4865,13 @@ static int bond_check_params(struct bond_params *params)
num_grat_arp = 1;
}
+ if (num_unsol_na < 0 || num_unsol_na > 255) {
+ printk(KERN_WARNING DRV_NAME
+ ": Warning: num_unsol_na (%d) not in range 0-255 so it "
+ "was reset to 1 \n", num_unsol_na);
+ num_unsol_na = 1;
+ }
+
/* reset values for 802.3ad */
if (bond_mode == BOND_MODE_8023AD) {
if (!miimon) {
@@ -4999,6 +5073,7 @@ static int bond_check_params(struct bond_params *params)
params->xmit_policy = xmit_hashtype;
params->miimon = miimon;
params->num_grat_arp = num_grat_arp;
+ params->num_unsol_na = num_unsol_na;
params->arp_interval = arp_interval;
params->arp_validate = arp_validate_value;
params->updelay = updelay;
@@ -5099,7 +5174,7 @@ int bond_create(char *name, struct bond_params *params)
up_write(&bonding_rwsem);
rtnl_unlock(); /* allows sysfs registration of net device */
- res = bond_create_sysfs_entry(bond_dev->priv);
+ res = bond_create_sysfs_entry(netdev_priv(bond_dev));
if (res < 0) {
rtnl_lock();
down_write(&bonding_rwsem);
@@ -5151,6 +5226,7 @@ static int __init bonding_init(void)
register_netdevice_notifier(&bond_netdev_notifier);
register_inetaddr_notifier(&bond_inetaddr_notifier);
+ bond_register_ipv6_notifier();
goto out;
err:
@@ -5173,6 +5249,7 @@ static void __exit bonding_exit(void)
{
unregister_netdevice_notifier(&bond_netdev_notifier);
unregister_inetaddr_notifier(&bond_inetaddr_notifier);
+ bond_unregister_ipv6_notifier();
bond_destroy_sysfs();
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 3bdb47382521..18cf4787874c 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -36,22 +36,13 @@
#include <linux/rtnetlink.h>
#include <net/net_namespace.h>
-/* #define BONDING_DEBUG 1 */
#include "bonding.h"
+
#define to_dev(obj) container_of(obj,struct device,kobj)
-#define to_bond(cd) ((struct bonding *)(to_net_dev(cd)->priv))
+#define to_bond(cd) ((struct bonding *)(netdev_priv(to_net_dev(cd))))
/*---------------------------- Declarations -------------------------------*/
-
-extern struct list_head bond_dev_list;
-extern struct bond_params bonding_defaults;
-extern struct bond_parm_tbl bond_mode_tbl[];
-extern struct bond_parm_tbl bond_lacp_tbl[];
-extern struct bond_parm_tbl xmit_hashtype_tbl[];
-extern struct bond_parm_tbl arp_validate_tbl[];
-extern struct bond_parm_tbl fail_over_mac_tbl[];
-
static int expected_refcount = -1;
/*--------------------------- Data Structures -----------------------------*/
@@ -316,18 +307,12 @@ static ssize_t bonding_store_slaves(struct device *d,
/* Set the slave's MTU to match the bond */
original_mtu = dev->mtu;
- if (dev->mtu != bond->dev->mtu) {
- if (dev->change_mtu) {
- res = dev->change_mtu(dev,
- bond->dev->mtu);
- if (res) {
- ret = res;
- goto out;
- }
- } else {
- dev->mtu = bond->dev->mtu;
- }
+ res = dev_set_mtu(dev, bond->dev->mtu);
+ if (res) {
+ ret = res;
+ goto out;
}
+
res = bond_enslave(bond->dev, dev);
bond_for_each_slave(bond, slave, i)
if (strnicmp(slave->dev->name, ifname, IFNAMSIZ) == 0)
@@ -356,11 +341,7 @@ static ssize_t bonding_store_slaves(struct device *d,
goto out;
}
/* set the slave MTU to the default */
- if (dev->change_mtu) {
- dev->change_mtu(dev, original_mtu);
- } else {
- dev->mtu = original_mtu;
- }
+ dev_set_mtu(dev, original_mtu);
}
else {
printk(KERN_ERR DRV_NAME ": unable to remove non-existent slave %s for bond %s.\n",
@@ -620,6 +601,8 @@ static ssize_t bonding_store_arp_interval(struct device *d,
": %s: Setting ARP monitoring interval to %d.\n",
bond->dev->name, new_value);
bond->params.arp_interval = new_value;
+ if (bond->params.arp_interval)
+ bond->dev->priv_flags |= IFF_MASTER_ARPMON;
if (bond->params.miimon) {
printk(KERN_INFO DRV_NAME
": %s: ARP monitoring cannot be used with MII monitoring. "
@@ -672,8 +655,8 @@ static ssize_t bonding_show_arp_targets(struct device *d,
for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
if (bond->params.arp_targets[i])
- res += sprintf(buf + res, "%u.%u.%u.%u ",
- NIPQUAD(bond->params.arp_targets[i]));
+ res += sprintf(buf + res, "%pI4 ",
+ &bond->params.arp_targets[i]);
}
if (res)
buf[res-1] = '\n'; /* eat the leftover space */
@@ -695,8 +678,8 @@ static ssize_t bonding_store_arp_targets(struct device *d,
if (buf[0] == '+') {
if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) {
printk(KERN_ERR DRV_NAME
- ": %s: invalid ARP target %u.%u.%u.%u specified for addition\n",
- bond->dev->name, NIPQUAD(newtarget));
+ ": %s: invalid ARP target %pI4 specified for addition\n",
+ bond->dev->name, &newtarget);
ret = -EINVAL;
goto out;
}
@@ -704,8 +687,8 @@ static ssize_t bonding_store_arp_targets(struct device *d,
for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
if (targets[i] == newtarget) { /* duplicate */
printk(KERN_ERR DRV_NAME
- ": %s: ARP target %u.%u.%u.%u is already present\n",
- bond->dev->name, NIPQUAD(newtarget));
+ ": %s: ARP target %pI4 is already present\n",
+ bond->dev->name, &newtarget);
if (done)
targets[i] = 0;
ret = -EINVAL;
@@ -713,8 +696,8 @@ static ssize_t bonding_store_arp_targets(struct device *d,
}
if (targets[i] == 0 && !done) {
printk(KERN_INFO DRV_NAME
- ": %s: adding ARP target %d.%d.%d.%d.\n",
- bond->dev->name, NIPQUAD(newtarget));
+ ": %s: adding ARP target %pI4.\n",
+ bond->dev->name, &newtarget);
done = 1;
targets[i] = newtarget;
}
@@ -731,8 +714,8 @@ static ssize_t bonding_store_arp_targets(struct device *d,
else if (buf[0] == '-') {
if ((newtarget == 0) || (newtarget == htonl(INADDR_BROADCAST))) {
printk(KERN_ERR DRV_NAME
- ": %s: invalid ARP target %d.%d.%d.%d specified for removal\n",
- bond->dev->name, NIPQUAD(newtarget));
+ ": %s: invalid ARP target %pI4 specified for removal\n",
+ bond->dev->name, &newtarget);
ret = -EINVAL;
goto out;
}
@@ -740,16 +723,16 @@ static ssize_t bonding_store_arp_targets(struct device *d,
for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
if (targets[i] == newtarget) {
printk(KERN_INFO DRV_NAME
- ": %s: removing ARP target %d.%d.%d.%d.\n",
- bond->dev->name, NIPQUAD(newtarget));
+ ": %s: removing ARP target %pI4.\n",
+ bond->dev->name, &newtarget);
targets[i] = 0;
done = 1;
}
}
if (!done) {
printk(KERN_INFO DRV_NAME
- ": %s: unable to remove nonexistent ARP target %d.%d.%d.%d.\n",
- bond->dev->name, NIPQUAD(newtarget));
+ ": %s: unable to remove nonexistent ARP target %pI4.\n",
+ bond->dev->name, &newtarget);
ret = -EINVAL;
goto out;
}
@@ -942,6 +925,53 @@ out:
}
static DEVICE_ATTR(lacp_rate, S_IRUGO | S_IWUSR, bonding_show_lacp, bonding_store_lacp);
+static ssize_t bonding_show_ad_select(struct device *d,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bonding *bond = to_bond(d);
+
+ return sprintf(buf, "%s %d\n",
+ ad_select_tbl[bond->params.ad_select].modename,
+ bond->params.ad_select);
+}
+
+
+static ssize_t bonding_store_ad_select(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(d);
+
+ if (bond->dev->flags & IFF_UP) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Unable to update ad_select because interface "
+ "is up.\n", bond->dev->name);
+ ret = -EPERM;
+ goto out;
+ }
+
+ new_value = bond_parse_parm(buf, ad_select_tbl);
+
+ if (new_value != -1) {
+ bond->params.ad_select = new_value;
+ printk(KERN_INFO DRV_NAME
+ ": %s: Setting ad_select to %s (%d).\n",
+ bond->dev->name, ad_select_tbl[new_value].modename,
+ new_value);
+ } else {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Ignoring invalid ad_select value %.*s.\n",
+ bond->dev->name, (int)strlen(buf) - 1, buf);
+ ret = -EINVAL;
+ }
+out:
+ return ret;
+}
+
+static DEVICE_ATTR(ad_select, S_IRUGO | S_IWUSR, bonding_show_ad_select, bonding_store_ad_select);
+
/*
* Show and set the number of grat ARP to send after a failover event.
*/
@@ -981,6 +1011,47 @@ out:
return ret;
}
static DEVICE_ATTR(num_grat_arp, S_IRUGO | S_IWUSR, bonding_show_n_grat_arp, bonding_store_n_grat_arp);
+
+/*
+ * Show and set the number of unsolicted NA's to send after a failover event.
+ */
+static ssize_t bonding_show_n_unsol_na(struct device *d,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct bonding *bond = to_bond(d);
+
+ return sprintf(buf, "%d\n", bond->params.num_unsol_na);
+}
+
+static ssize_t bonding_store_n_unsol_na(struct device *d,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int new_value, ret = count;
+ struct bonding *bond = to_bond(d);
+
+ if (sscanf(buf, "%d", &new_value) != 1) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: no num_unsol_na value specified.\n",
+ bond->dev->name);
+ ret = -EINVAL;
+ goto out;
+ }
+ if (new_value < 0 || new_value > 255) {
+ printk(KERN_ERR DRV_NAME
+ ": %s: Invalid num_unsol_na value %d not in range 0-255; rejected.\n",
+ bond->dev->name, new_value);
+ ret = -EINVAL;
+ goto out;
+ } else {
+ bond->params.num_unsol_na = new_value;
+ }
+out:
+ return ret;
+}
+static DEVICE_ATTR(num_unsol_na, S_IRUGO | S_IWUSR, bonding_show_n_unsol_na, bonding_store_n_unsol_na);
+
/*
* Show and set the MII monitor interval. There are two tricky bits
* here. First, if MII monitoring is activated, then we must disable
@@ -1039,6 +1110,7 @@ static ssize_t bonding_store_miimon(struct device *d,
"ARP monitoring. Disabling ARP monitoring...\n",
bond->dev->name);
bond->params.arp_interval = 0;
+ bond->dev->priv_flags &= ~IFF_MASTER_ARPMON;
if (bond->params.arp_validate) {
bond_unregister_arp(bond);
bond->params.arp_validate =
@@ -1391,13 +1463,11 @@ static ssize_t bonding_show_ad_partner_mac(struct device *d,
{
int count = 0;
struct bonding *bond = to_bond(d);
- DECLARE_MAC_BUF(mac);
if (bond->params.mode == BOND_MODE_8023AD) {
struct ad_info ad_info;
if (!bond_3ad_get_active_agg_info(bond, &ad_info)) {
- count = sprintf(buf,"%s\n",
- print_mac(mac, ad_info.partner_system));
+ count = sprintf(buf, "%pM\n", ad_info.partner_system);
}
}
@@ -1417,8 +1487,10 @@ static struct attribute *per_bond_attrs[] = {
&dev_attr_downdelay.attr,
&dev_attr_updelay.attr,
&dev_attr_lacp_rate.attr,
+ &dev_attr_ad_select.attr,
&dev_attr_xmit_hash_policy.attr,
&dev_attr_num_grat_arp.attr,
+ &dev_attr_num_unsol_na.attr,
&dev_attr_miimon.attr,
&dev_attr_primary.attr,
&dev_attr_use_carrier.attr,
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index ffb668dd6d3b..ca849d2adf98 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -19,23 +19,18 @@
#include <linux/proc_fs.h>
#include <linux/if_bonding.h>
#include <linux/kobject.h>
+#include <linux/in6.h>
#include "bond_3ad.h"
#include "bond_alb.h"
-#define DRV_VERSION "3.3.0"
-#define DRV_RELDATE "June 10, 2008"
+#define DRV_VERSION "3.5.0"
+#define DRV_RELDATE "November 4, 2008"
#define DRV_NAME "bonding"
#define DRV_DESCRIPTION "Ethernet Channel Bonding Driver"
#define BOND_MAX_ARP_TARGETS 16
-#ifdef BONDING_DEBUG
-#define dprintk(fmt, args...) \
- printk(KERN_DEBUG \
- DRV_NAME ": %s() %d: " fmt, __func__, __LINE__ , ## args )
-#else
-#define dprintk(fmt, args...)
-#endif /* BONDING_DEBUG */
+extern struct list_head bond_dev_list;
#define IS_UP(dev) \
((((dev)->flags & IFF_UP) == IFF_UP) && \
@@ -126,6 +121,7 @@ struct bond_params {
int xmit_policy;
int miimon;
int num_grat_arp;
+ int num_unsol_na;
int arp_interval;
int arp_validate;
int use_carrier;
@@ -133,6 +129,7 @@ struct bond_params {
int updelay;
int downdelay;
int lacp_fast;
+ int ad_select;
char primary[IFNAMSIZ];
__be32 arp_targets[BOND_MAX_ARP_TARGETS];
};
@@ -148,6 +145,9 @@ struct vlan_entry {
struct list_head vlan_list;
__be32 vlan_ip;
unsigned short vlan_id;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ struct in6_addr vlan_ipv6;
+#endif
};
struct slave {
@@ -195,6 +195,7 @@ struct bonding {
rwlock_t curr_slave_lock;
s8 kill_timers;
s8 send_grat_arp;
+ s8 send_unsol_na;
s8 setup_by_slave;
struct net_device_stats stats;
#ifdef CONFIG_PROC_FS
@@ -218,6 +219,9 @@ struct bonding {
struct delayed_work arp_work;
struct delayed_work alb_work;
struct delayed_work ad_work;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+ struct in6_addr master_ipv6;
+#endif
};
/**
@@ -245,7 +249,13 @@ static inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
return NULL;
}
- return (struct bonding *)slave->dev->master->priv;
+ return (struct bonding *)netdev_priv(slave->dev->master);
+}
+
+static inline bool bond_is_lb(const struct bonding *bond)
+{
+ return bond->params.mode == BOND_MODE_TLB
+ || bond->params.mode == BOND_MODE_ALB;
}
#define BOND_FOM_NONE 0
@@ -275,7 +285,7 @@ static inline unsigned long slave_last_rx(struct bonding *bond,
static inline void bond_set_slave_inactive_flags(struct slave *slave)
{
- struct bonding *bond = slave->dev->master->priv;
+ struct bonding *bond = netdev_priv(slave->dev->master);
if (bond->params.mode != BOND_MODE_TLB &&
bond->params.mode != BOND_MODE_ALB)
slave->state = BOND_STATE_BACKUP;
@@ -327,7 +337,7 @@ void bond_mii_monitor(struct work_struct *);
void bond_loadbalance_arp_mon(struct work_struct *);
void bond_activebackup_arp_mon(struct work_struct *);
void bond_set_mode_ops(struct bonding *bond, int mode);
-int bond_parse_parm(const char *mode_arg, struct bond_parm_tbl *tbl);
+int bond_parse_parm(const char *mode_arg, const struct bond_parm_tbl *tbl);
void bond_select_active_slave(struct bonding *bond);
void bond_change_active_slave(struct bonding *bond, struct slave *new_active);
void bond_register_arp(struct bonding *);
@@ -335,11 +345,35 @@ void bond_unregister_arp(struct bonding *);
/* exported from bond_main.c */
extern struct list_head bond_dev_list;
-extern struct bond_parm_tbl bond_lacp_tbl[];
-extern struct bond_parm_tbl bond_mode_tbl[];
-extern struct bond_parm_tbl xmit_hashtype_tbl[];
-extern struct bond_parm_tbl arp_validate_tbl[];
-extern struct bond_parm_tbl fail_over_mac_tbl[];
+extern const struct bond_parm_tbl bond_lacp_tbl[];
+extern const struct bond_parm_tbl bond_mode_tbl[];
+extern const struct bond_parm_tbl xmit_hashtype_tbl[];
+extern const struct bond_parm_tbl arp_validate_tbl[];
+extern const struct bond_parm_tbl fail_over_mac_tbl[];
+extern struct bond_params bonding_defaults;
+extern struct bond_parm_tbl ad_select_tbl[];
+
+/* exported from bond_sysfs.c */
+extern struct rw_semaphore bonding_rwsem;
+
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+void bond_send_unsolicited_na(struct bonding *bond);
+void bond_register_ipv6_notifier(void);
+void bond_unregister_ipv6_notifier(void);
+#else
+static inline void bond_send_unsolicited_na(struct bonding *bond)
+{
+ return;
+}
+static inline void bond_register_ipv6_notifier(void)
+{
+ return;
+}
+static inline void bond_unregister_ipv6_notifier(void)
+{
+ return;
+}
+#endif
#endif /* _LINUX_BONDING_H */
diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c
index 103f0f1df280..a10c1d7b3b0a 100644
--- a/drivers/net/can/vcan.c
+++ b/drivers/net/can/vcan.c
@@ -128,26 +128,30 @@ static int vcan_tx(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
+static const struct net_device_ops vcan_netdev_ops = {
+ .ndo_start_xmit = vcan_tx,
+};
+
static void vcan_setup(struct net_device *dev)
{
- dev->type = ARPHRD_CAN;
- dev->mtu = sizeof(struct can_frame);
- dev->hard_header_len = 0;
- dev->addr_len = 0;
- dev->tx_queue_len = 0;
- dev->flags = IFF_NOARP;
+ dev->type = ARPHRD_CAN;
+ dev->mtu = sizeof(struct can_frame);
+ dev->hard_header_len = 0;
+ dev->addr_len = 0;
+ dev->tx_queue_len = 0;
+ dev->flags = IFF_NOARP;
/* set flags according to driver capabilities */
if (echo)
dev->flags |= IFF_ECHO;
- dev->hard_start_xmit = vcan_tx;
- dev->destructor = free_netdev;
+ dev->netdev_ops = &vcan_netdev_ops;
+ dev->destructor = free_netdev;
}
static struct rtnl_link_ops vcan_link_ops __read_mostly = {
- .kind = "vcan",
- .setup = vcan_setup,
+ .kind = "vcan",
+ .setup = vcan_setup,
};
static __init int vcan_init_module(void)
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
index 86909cfb14de..321f43d9f0e2 100644
--- a/drivers/net/cassini.c
+++ b/drivers/net/cassini.c
@@ -2347,7 +2347,7 @@ static int cas_rx_ringN(struct cas *cp, int ring, int budget)
drops = 0;
while (1) {
struct cas_rx_comp *rxc = rxcs + entry;
- struct sk_buff *skb;
+ struct sk_buff *uninitialized_var(skb);
int type, len;
u64 words[4];
int i, dring;
@@ -2405,7 +2405,6 @@ static int cas_rx_ringN(struct cas *cp, int ring, int budget)
cp->net_stats[ring].rx_packets++;
cp->net_stats[ring].rx_bytes += len;
spin_unlock(&cp->stat_lock[ring]);
- cp->dev->last_rx = jiffies;
next:
npackets++;
@@ -2507,7 +2506,7 @@ static irqreturn_t cas_interruptN(int irq, void *dev_id)
if (status & INTR_RX_DONE_ALT) { /* handle rx separately */
#ifdef USE_NAPI
cas_mask_intr(cp);
- netif_rx_schedule(dev, &cp->napi);
+ netif_rx_schedule(&cp->napi);
#else
cas_rx_ringN(cp, ring, 0);
#endif
@@ -2558,7 +2557,7 @@ static irqreturn_t cas_interrupt1(int irq, void *dev_id)
if (status & INTR_RX_DONE_ALT) { /* handle rx separately */
#ifdef USE_NAPI
cas_mask_intr(cp);
- netif_rx_schedule(dev, &cp->napi);
+ netif_rx_schedule(&cp->napi);
#else
cas_rx_ringN(cp, 1, 0);
#endif
@@ -2614,7 +2613,7 @@ static irqreturn_t cas_interrupt(int irq, void *dev_id)
if (status & INTR_RX_DONE) {
#ifdef USE_NAPI
cas_mask_intr(cp);
- netif_rx_schedule(dev, &cp->napi);
+ netif_rx_schedule(&cp->napi);
#else
cas_rx_ringN(cp, 0, 0);
#endif
@@ -2692,7 +2691,7 @@ rx_comp:
#endif
spin_unlock_irqrestore(&cp->lock, flags);
if (enable_intr) {
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
cas_unmask_intr(cp);
}
return credits;
@@ -4988,7 +4987,6 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
int i, err, pci_using_dac;
u16 pci_cmd;
u8 orig_cacheline_size = 0, cas_cacheline_size = 0;
- DECLARE_MAC_BUF(mac);
if (cas_version_printed++ == 0)
printk(KERN_INFO "%s", version);
@@ -5201,12 +5199,12 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
i = readl(cp->regs + REG_BIM_CFG);
printk(KERN_INFO "%s: Sun Cassini%s (%sbit/%sMHz PCI/%s) "
- "Ethernet[%d] %s\n", dev->name,
+ "Ethernet[%d] %pM\n", dev->name,
(cp->cas_flags & CAS_FLAG_REG_PLUS) ? "+" : "",
(i & BIM_CFG_32BIT) ? "32" : "64",
(i & BIM_CFG_66MHZ) ? "66" : "33",
(cp->phy_type == CAS_PHY_SERDES) ? "Fi" : "Cu", pdev->irq,
- print_mac(mac, dev->dev_addr));
+ dev->dev_addr);
pci_set_drvdata(pdev, dev);
cp->hw_running = 1;
diff --git a/drivers/net/chelsio/cxgb2.c b/drivers/net/chelsio/cxgb2.c
index 638c9a27a7a6..9b6011e7678e 100644
--- a/drivers/net/chelsio/cxgb2.c
+++ b/drivers/net/chelsio/cxgb2.c
@@ -120,7 +120,7 @@ static const char pci_speed[][4] = {
*/
static void t1_set_rxmode(struct net_device *dev)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
struct cmac *mac = adapter->port[dev->if_port].mac;
struct t1_rx_mode rm;
@@ -252,7 +252,7 @@ static void cxgb_down(struct adapter *adapter)
static int cxgb_open(struct net_device *dev)
{
int err;
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
int other_ports = adapter->open_device_map & PORT_MASK;
napi_enable(&adapter->napi);
@@ -272,7 +272,7 @@ static int cxgb_open(struct net_device *dev)
static int cxgb_close(struct net_device *dev)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
struct port_info *p = &adapter->port[dev->if_port];
struct cmac *mac = p->mac;
@@ -298,7 +298,7 @@ static int cxgb_close(struct net_device *dev)
static struct net_device_stats *t1_get_stats(struct net_device *dev)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
struct port_info *p = &adapter->port[dev->if_port];
struct net_device_stats *ns = &p->netstats;
const struct cmac_statistics *pstats;
@@ -346,14 +346,14 @@ static struct net_device_stats *t1_get_stats(struct net_device *dev)
static u32 get_msglevel(struct net_device *dev)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
return adapter->msg_enable;
}
static void set_msglevel(struct net_device *dev, u32 val)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
adapter->msg_enable = val;
}
@@ -434,7 +434,7 @@ static int get_regs_len(struct net_device *dev)
static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
strcpy(info->driver, DRV_NAME);
strcpy(info->version, DRV_VERSION);
@@ -461,7 +461,7 @@ static void get_strings(struct net_device *dev, u32 stringset, u8 *data)
static void get_stats(struct net_device *dev, struct ethtool_stats *stats,
u64 *data)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
struct cmac *mac = adapter->port[dev->if_port].mac;
const struct cmac_statistics *s;
const struct sge_intr_counts *t;
@@ -552,7 +552,7 @@ static inline void reg_block_dump(struct adapter *ap, void *buf,
static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *buf)
{
- struct adapter *ap = dev->priv;
+ struct adapter *ap = dev->ml_priv;
/*
* Version scheme: bits 0..9: chip version, bits 10..15: chip revision
@@ -574,7 +574,7 @@ static void get_regs(struct net_device *dev, struct ethtool_regs *regs,
static int get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
struct port_info *p = &adapter->port[dev->if_port];
cmd->supported = p->link_config.supported;
@@ -634,7 +634,7 @@ static int speed_duplex_to_caps(int speed, int duplex)
static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
struct port_info *p = &adapter->port[dev->if_port];
struct link_config *lc = &p->link_config;
@@ -669,7 +669,7 @@ static int set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static void get_pauseparam(struct net_device *dev,
struct ethtool_pauseparam *epause)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
struct port_info *p = &adapter->port[dev->if_port];
epause->autoneg = (p->link_config.requested_fc & PAUSE_AUTONEG) != 0;
@@ -680,7 +680,7 @@ static void get_pauseparam(struct net_device *dev,
static int set_pauseparam(struct net_device *dev,
struct ethtool_pauseparam *epause)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
struct port_info *p = &adapter->port[dev->if_port];
struct link_config *lc = &p->link_config;
@@ -709,14 +709,14 @@ static int set_pauseparam(struct net_device *dev,
static u32 get_rx_csum(struct net_device *dev)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
return (adapter->flags & RX_CSUM_ENABLED) != 0;
}
static int set_rx_csum(struct net_device *dev, u32 data)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
if (data)
adapter->flags |= RX_CSUM_ENABLED;
@@ -727,7 +727,7 @@ static int set_rx_csum(struct net_device *dev, u32 data)
static int set_tso(struct net_device *dev, u32 value)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
if (!(adapter->flags & TSO_CAPABLE))
return value ? -EOPNOTSUPP : 0;
@@ -736,7 +736,7 @@ static int set_tso(struct net_device *dev, u32 value)
static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
int jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
e->rx_max_pending = MAX_RX_BUFFERS;
@@ -752,7 +752,7 @@ static void get_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
int jumbo_fl = t1_is_T1B(adapter) ? 1 : 0;
if (e->rx_pending > MAX_RX_BUFFERS || e->rx_mini_pending ||
@@ -776,7 +776,7 @@ static int set_sge_param(struct net_device *dev, struct ethtool_ringparam *e)
static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
adapter->params.sge.rx_coalesce_usecs = c->rx_coalesce_usecs;
adapter->params.sge.coalesce_enable = c->use_adaptive_rx_coalesce;
@@ -787,7 +787,7 @@ static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
c->rx_coalesce_usecs = adapter->params.sge.rx_coalesce_usecs;
c->rate_sample_interval = adapter->params.sge.sample_interval_usecs;
@@ -797,7 +797,7 @@ static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
static int get_eeprom_len(struct net_device *dev)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
return t1_is_asic(adapter) ? EEPROM_SIZE : 0;
}
@@ -810,7 +810,7 @@ static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e,
{
int i;
u8 buf[EEPROM_SIZE] __attribute__((aligned(4)));
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
e->magic = EEPROM_MAGIC(adapter);
for (i = e->offset & ~3; i < e->offset + e->len; i += sizeof(u32))
@@ -848,7 +848,7 @@ static const struct ethtool_ops t1_ethtool_ops = {
static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
struct mii_ioctl_data *data = if_mii(req);
switch (cmd) {
@@ -887,7 +887,7 @@ static int t1_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
static int t1_change_mtu(struct net_device *dev, int new_mtu)
{
int ret;
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
struct cmac *mac = adapter->port[dev->if_port].mac;
if (!mac->ops->set_mtu)
@@ -902,7 +902,7 @@ static int t1_change_mtu(struct net_device *dev, int new_mtu)
static int t1_set_mac_addr(struct net_device *dev, void *p)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
struct cmac *mac = adapter->port[dev->if_port].mac;
struct sockaddr *addr = p;
@@ -915,10 +915,10 @@ static int t1_set_mac_addr(struct net_device *dev, void *p)
}
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-static void vlan_rx_register(struct net_device *dev,
+static void t1_vlan_rx_register(struct net_device *dev,
struct vlan_group *grp)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
spin_lock_irq(&adapter->async_lock);
adapter->vlan_grp = grp;
@@ -931,7 +931,7 @@ static void vlan_rx_register(struct net_device *dev,
static void t1_netpoll(struct net_device *dev)
{
unsigned long flags;
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
local_irq_save(flags);
t1_interrupt(adapter->pdev->irq, adapter);
@@ -1010,6 +1010,24 @@ void t1_fatal_err(struct adapter *adapter)
adapter->name);
}
+static const struct net_device_ops cxgb_netdev_ops = {
+ .ndo_open = cxgb_open,
+ .ndo_stop = cxgb_close,
+ .ndo_start_xmit = t1_start_xmit,
+ .ndo_get_stats = t1_get_stats,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_multicast_list = t1_set_rxmode,
+ .ndo_do_ioctl = t1_ioctl,
+ .ndo_change_mtu = t1_change_mtu,
+ .ndo_set_mac_address = t1_set_mac_addr,
+#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
+ .ndo_vlan_rx_register = t1_vlan_rx_register,
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = t1_netpoll,
+#endif
+};
+
static int __devinit init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -1077,7 +1095,7 @@ static int __devinit init_one(struct pci_dev *pdev,
SET_NETDEV_DEV(netdev, &pdev->dev);
if (!adapter) {
- adapter = netdev->priv;
+ adapter = netdev_priv(netdev);
adapter->pdev = pdev;
adapter->port[0].dev = netdev; /* so we don't leak it */
@@ -1118,7 +1136,7 @@ static int __devinit init_one(struct pci_dev *pdev,
netdev->if_port = i;
netdev->mem_start = mmio_start;
netdev->mem_end = mmio_start + mmio_len - 1;
- netdev->priv = adapter;
+ netdev->ml_priv = adapter;
netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
netdev->features |= NETIF_F_LLTX;
@@ -1130,7 +1148,6 @@ static int __devinit init_one(struct pci_dev *pdev,
adapter->flags |= VLAN_ACCEL_CAPABLE;
netdev->features |=
NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
- netdev->vlan_rx_register = vlan_rx_register;
#endif
/* T204: disable TSO */
@@ -1140,19 +1157,10 @@ static int __devinit init_one(struct pci_dev *pdev,
}
}
- netdev->open = cxgb_open;
- netdev->stop = cxgb_close;
- netdev->hard_start_xmit = t1_start_xmit;
+ netdev->netdev_ops = &cxgb_netdev_ops;
netdev->hard_header_len += (adapter->flags & TSO_CAPABLE) ?
sizeof(struct cpl_tx_pkt_lso) : sizeof(struct cpl_tx_pkt);
- netdev->get_stats = t1_get_stats;
- netdev->set_multicast_list = t1_set_rxmode;
- netdev->do_ioctl = t1_ioctl;
- netdev->change_mtu = t1_change_mtu;
- netdev->set_mac_address = t1_set_mac_addr;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- netdev->poll_controller = t1_netpoll;
-#endif
+
netif_napi_add(netdev, &adapter->napi, t1_poll, 64);
SET_ETHTOOL_OPS(netdev, &t1_ethtool_ops);
@@ -1382,7 +1390,7 @@ static inline void t1_sw_reset(struct pci_dev *pdev)
static void __devexit remove_one(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
int i;
for_each_port(adapter, i) {
diff --git a/drivers/net/chelsio/sge.c b/drivers/net/chelsio/sge.c
index 7092df50ff78..d984b7995763 100644
--- a/drivers/net/chelsio/sge.c
+++ b/drivers/net/chelsio/sge.c
@@ -1381,7 +1381,6 @@ static void sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len)
st = per_cpu_ptr(sge->port_stats[p->iff], smp_processor_id());
skb->protocol = eth_type_trans(skb, adapter->port[p->iff].dev);
- skb->dev->last_rx = jiffies;
if ((adapter->flags & RX_CSUM_ENABLED) && p->csum == 0xffff &&
skb->protocol == htons(ETH_P_IP) &&
(skb->data[9] == IPPROTO_TCP || skb->data[9] == IPPROTO_UDP)) {
@@ -1610,11 +1609,10 @@ static int process_pure_responses(struct adapter *adapter)
int t1_poll(struct napi_struct *napi, int budget)
{
struct adapter *adapter = container_of(napi, struct adapter, napi);
- struct net_device *dev = adapter->port[0].dev;
int work_done = process_responses(adapter, budget);
if (likely(work_done < budget)) {
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
writel(adapter->sge->respQ.cidx,
adapter->regs + A_SG_SLEEPING);
}
@@ -1628,13 +1626,11 @@ irqreturn_t t1_interrupt(int irq, void *data)
int handled;
if (likely(responses_pending(adapter))) {
- struct net_device *dev = sge->netdev;
-
writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE);
if (napi_schedule_prep(&adapter->napi)) {
if (process_pure_responses(adapter))
- __netif_rx_schedule(dev, &adapter->napi);
+ __netif_rx_schedule(&adapter->napi);
else {
/* no data, no NAPI needed */
writel(sge->respQ.cidx, adapter->regs + A_SG_SLEEPING);
@@ -1782,7 +1778,7 @@ static inline int eth_hdr_len(const void *data)
*/
int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
struct sge *sge = adapter->sge;
struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[dev->if_port],
smp_processor_id());
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c
index 017a5361b980..f66548751c38 100644
--- a/drivers/net/cpmac.c
+++ b/drivers/net/cpmac.c
@@ -428,7 +428,7 @@ static int cpmac_poll(struct napi_struct *napi, int budget)
printk(KERN_WARNING "%s: rx: polling, but no queue\n",
priv->dev->name);
spin_unlock(&priv->rx_lock);
- netif_rx_complete(priv->dev, napi);
+ netif_rx_complete(napi);
return 0;
}
@@ -514,7 +514,7 @@ static int cpmac_poll(struct napi_struct *napi, int budget)
if (processed == 0) {
/* we ran out of packets to read,
* revert to interrupt-driven mode */
- netif_rx_complete(priv->dev, napi);
+ netif_rx_complete(napi);
cpmac_write(priv->regs, CPMAC_RX_INT_ENABLE, 1);
return 0;
}
@@ -536,7 +536,7 @@ fatal_error:
}
spin_unlock(&priv->rx_lock);
- netif_rx_complete(priv->dev, napi);
+ netif_rx_complete(napi);
netif_tx_stop_all_queues(priv->dev);
napi_disable(&priv->napi);
@@ -802,9 +802,9 @@ static irqreturn_t cpmac_irq(int irq, void *dev_id)
if (status & MAC_INT_RX) {
queue = (status >> 8) & 7;
- if (netif_rx_schedule_prep(dev, &priv->napi)) {
+ if (netif_rx_schedule_prep(&priv->napi)) {
cpmac_write(priv->regs, CPMAC_RX_INT_CLEAR, 1 << queue);
- __netif_rx_schedule(dev, &priv->napi);
+ __netif_rx_schedule(&priv->napi);
}
}
@@ -1103,7 +1103,6 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
struct cpmac_priv *priv;
struct net_device *dev;
struct plat_cpmac_data *pdata;
- DECLARE_MAC_BUF(mac);
pdata = pdev->dev.platform_data;
@@ -1180,8 +1179,8 @@ static int __devinit cpmac_probe(struct platform_device *pdev)
if (netif_msg_probe(priv)) {
printk(KERN_INFO
"cpmac: device %s (regs: %p, irq: %d, phy: %s, "
- "mac: %s)\n", dev->name, (void *)mem->start, dev->irq,
- priv->phy_name, print_mac(mac, dev->dev_addr));
+ "mac: %pM)\n", dev->name, (void *)mem->start, dev->irq,
+ priv->phy_name, dev->dev_addr);
}
return 0;
diff --git a/drivers/net/cris/eth_v10.c b/drivers/net/cris/eth_v10.c
index 7e8a63106bdf..c9806c58b2fd 100644
--- a/drivers/net/cris/eth_v10.c
+++ b/drivers/net/cris/eth_v10.c
@@ -419,7 +419,6 @@ e100_set_mac_address(struct net_device *dev, void *p)
{
struct net_local *np = netdev_priv(dev);
struct sockaddr *addr = p;
- DECLARE_MAC_BUF(mac);
spin_lock(&np->lock); /* preemption protection */
@@ -440,8 +439,7 @@ e100_set_mac_address(struct net_device *dev, void *p)
/* show it in the log as well */
- printk(KERN_INFO "%s: changed MAC to %s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "%s: changed MAC to %pM\n", dev->name, dev->dev_addr);
spin_unlock(&np->lock);
diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
index 7107620f615d..d548a45d59d5 100644
--- a/drivers/net/cs89x0.c
+++ b/drivers/net/cs89x0.c
@@ -521,7 +521,6 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
unsigned rev_type = 0;
int eeprom_buff[CHKSUM_LEN];
int retval;
- DECLARE_MAC_BUF(mac);
/* Initialize the device structure. */
if (!modular) {
@@ -846,7 +845,7 @@ cs89x0_probe1(struct net_device *dev, int ioaddr, int modular)
}
/* print the ethernet address. */
- printk(", MAC %s", print_mac(mac, dev->dev_addr));
+ printk(", MAC %pM", dev->dev_addr);
dev->open = net_open;
dev->stop = net_close;
@@ -1025,14 +1024,13 @@ skip_this_frame:
}
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
- dev->last_rx = jiffies;
lp->stats.rx_packets++;
lp->stats.rx_bytes += length;
}
#endif /* ALLOW_DMA */
-void __init reset_chip(struct net_device *dev)
+static void __init reset_chip(struct net_device *dev)
{
#if !defined(CONFIG_MACH_MX31ADS)
#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01)
@@ -1719,7 +1717,6 @@ net_rx(struct net_device *dev)
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
- dev->last_rx = jiffies;
lp->stats.rx_packets++;
lp->stats.rx_bytes += length;
}
@@ -1817,11 +1814,10 @@ static int set_mac_address(struct net_device *dev, void *p)
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
- if (net_debug) {
- DECLARE_MAC_BUF(mac);
- printk("%s: Setting MAC address to %s.\n",
- dev->name, print_mac(mac, dev->dev_addr));
- }
+ if (net_debug)
+ printk("%s: Setting MAC address to %pM.\n",
+ dev->name, dev->dev_addr);
+
/* set the Ethernet address */
for (i=0; i < ETH_ALEN/2; i++)
writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h
index bc8e2413abd2..5b346f9eaa8b 100644
--- a/drivers/net/cxgb3/adapter.h
+++ b/drivers/net/cxgb3/adapter.h
@@ -63,6 +63,7 @@ struct port_info {
struct link_config link_config;
struct net_device_stats netstats;
int activity;
+ __be32 iscsi_ipv4addr;
};
enum { /* adapter flags */
@@ -196,6 +197,7 @@ struct sge_qset { /* an SGE queue set */
int lro_frag_len;
void *lro_va;
struct net_device *netdev;
+ struct netdev_queue *tx_q; /* associated netdev TX queue */
unsigned long txq_stopped; /* which Tx queues are stopped */
struct timer_list tx_reclaim_timer; /* reclaims TX buffers */
unsigned long port_stats[SGE_PSTAT_MAX];
@@ -294,7 +296,8 @@ int t3_mgmt_tx(struct adapter *adap, struct sk_buff *skb);
void t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p);
int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
int irq_vec_idx, const struct qset_params *p,
- int ntxq, struct net_device *dev);
+ int ntxq, struct net_device *dev,
+ struct netdev_queue *netdevq);
int t3_get_desc(const struct sge_qset *qs, unsigned int qnum, unsigned int idx,
unsigned char *data);
irqreturn_t t3_sge_intr_msix(int irq, void *cookie);
diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h
index e312d315a42d..db4f4f575b6a 100644
--- a/drivers/net/cxgb3/common.h
+++ b/drivers/net/cxgb3/common.h
@@ -714,7 +714,7 @@ int t3_seeprom_read(struct adapter *adapter, u32 addr, __le32 *data);
int t3_seeprom_write(struct adapter *adapter, u32 addr, __le32 data);
int t3_seeprom_wp(struct adapter *adapter, int enable);
int t3_get_tp_version(struct adapter *adapter, u32 *vers);
-int t3_check_tpsram_version(struct adapter *adapter, int *must_load);
+int t3_check_tpsram_version(struct adapter *adapter);
int t3_check_tpsram(struct adapter *adapter, const u8 *tp_ram,
unsigned int size);
int t3_set_proto_sram(struct adapter *adap, const u8 *data);
@@ -722,7 +722,7 @@ int t3_read_flash(struct adapter *adapter, unsigned int addr,
unsigned int nwords, u32 *data, int byte_oriented);
int t3_load_fw(struct adapter *adapter, const u8 * fw_data, unsigned int size);
int t3_get_fw_version(struct adapter *adapter, u32 *vers);
-int t3_check_fw_version(struct adapter *adapter, int *must_load);
+int t3_check_fw_version(struct adapter *adapter);
int t3_init_hw(struct adapter *adapter, u32 fw_params);
void mac_prep(struct cmac *mac, struct adapter *adapter, int index);
void early_hw_init(struct adapter *adapter, const struct adapter_info *ai);
diff --git a/drivers/net/cxgb3/cxgb3_ctl_defs.h b/drivers/net/cxgb3/cxgb3_ctl_defs.h
index 1d8d46eb3c96..369fe711fd7f 100644
--- a/drivers/net/cxgb3/cxgb3_ctl_defs.h
+++ b/drivers/net/cxgb3/cxgb3_ctl_defs.h
@@ -57,6 +57,9 @@ enum {
RDMA_GET_MIB = 19,
GET_RX_PAGE_INFO = 50,
+ GET_ISCSI_IPV4ADDR = 51,
+
+ GET_EMBEDDED_INFO = 70,
};
/*
@@ -86,6 +89,12 @@ struct iff_mac {
u16 vlan_tag;
};
+/* Structure used to request a port's iSCSI IPv4 address */
+struct iscsi_ipv4addr {
+ struct net_device *dev; /* the net_device */
+ __be32 ipv4addr; /* the return iSCSI IPv4 address */
+};
+
struct pci_dev;
/*
@@ -169,4 +178,12 @@ struct ofld_page_info {
unsigned int page_size; /* Page size, should be a power of 2 */
unsigned int num; /* Number of pages */
};
+
+/*
+ * Structure used to get firmware and protocol engine versions.
+ */
+struct ch_embedded_info {
+ u32 fw_vers;
+ u32 tp_vers;
+};
#endif /* _CXGB3_OFFLOAD_CTL_DEFS_H */
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 2c341f83d327..2847f947499d 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -494,6 +494,36 @@ static void enable_all_napi(struct adapter *adap)
}
/**
+ * set_qset_lro - Turn a queue set's LRO capability on and off
+ * @dev: the device the qset is attached to
+ * @qset_idx: the queue set index
+ * @val: the LRO switch
+ *
+ * Sets LRO on or off for a particular queue set.
+ * the device's features flag is updated to reflect the LRO
+ * capability when all queues belonging to the device are
+ * in the same state.
+ */
+static void set_qset_lro(struct net_device *dev, int qset_idx, int val)
+{
+ struct port_info *pi = netdev_priv(dev);
+ struct adapter *adapter = pi->adapter;
+ int i, lro_on = 1;
+
+ adapter->params.sge.qset[qset_idx].lro = !!val;
+ adapter->sge.qs[qset_idx].lro_enabled = !!val;
+
+ /* let ethtool report LRO on only if all queues are LRO enabled */
+ for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; ++i)
+ lro_on &= adapter->params.sge.qset[i].lro;
+
+ if (lro_on)
+ dev->features |= NETIF_F_LRO;
+ else
+ dev->features &= ~NETIF_F_LRO;
+}
+
+/**
* setup_sge_qsets - configure SGE Tx/Rx/response queues
* @adap: the adapter
*
@@ -516,12 +546,12 @@ static int setup_sge_qsets(struct adapter *adap)
pi->qs = &adap->sge.qs[pi->first_qset];
for (j = pi->first_qset; j < pi->first_qset + pi->nqsets;
++j, ++qset_idx) {
- if (!pi->rx_csum_offload)
- adap->params.sge.qset[qset_idx].lro = 0;
+ set_qset_lro(dev, qset_idx, pi->rx_csum_offload);
err = t3_sge_alloc_qset(adap, qset_idx, 1,
(adap->flags & USING_MSIX) ? qset_idx + 1 :
irq_idx,
- &adap->params.sge.qset[qset_idx], ntxq, dev);
+ &adap->params.sge.qset[qset_idx], ntxq, dev,
+ netdev_get_tx_queue(dev, j));
if (err) {
t3_stop_sge_timers(adap);
t3_free_sge_resources(adap);
@@ -824,8 +854,8 @@ static int bind_qsets(struct adapter *adap)
return err;
}
-#define FW_FNAME "t3fw-%d.%d.%d.bin"
-#define TPSRAM_NAME "t3%c_protocol_sram-%d.%d.%d.bin"
+#define FW_FNAME "cxgb3/t3fw-%d.%d.%d.bin"
+#define TPSRAM_NAME "cxgb3/t3%c_psram-%d.%d.%d.bin"
static int upgrade_fw(struct adapter *adap)
{
@@ -928,21 +958,22 @@ release_tpsram:
static int cxgb_up(struct adapter *adap)
{
int err;
- int must_load;
if (!(adap->flags & FULL_INIT_DONE)) {
- err = t3_check_fw_version(adap, &must_load);
+ err = t3_check_fw_version(adap);
if (err == -EINVAL) {
err = upgrade_fw(adap);
- if (err && must_load)
- goto out;
+ CH_WARN(adap, "FW upgrade to %d.%d.%d %s\n",
+ FW_VERSION_MAJOR, FW_VERSION_MINOR,
+ FW_VERSION_MICRO, err ? "failed" : "succeeded");
}
- err = t3_check_tpsram_version(adap, &must_load);
+ err = t3_check_tpsram_version(adap);
if (err == -EINVAL) {
err = update_tpsram(adap);
- if (err && must_load)
- goto out;
+ CH_WARN(adap, "TP upgrade to %d.%d.%d %s\n",
+ TP_VERSION_MAJOR, TP_VERSION_MINOR,
+ TP_VERSION_MICRO, err ? "failed" : "succeeded");
}
/*
@@ -1136,9 +1167,10 @@ static int cxgb_open(struct net_device *dev)
"Could not initialize offload capabilities\n");
}
+ dev->real_num_tx_queues = pi->nqsets;
link_start(dev);
t3_port_intr_enable(adapter, pi->port_id);
- netif_start_queue(dev);
+ netif_tx_start_all_queues(dev);
if (!other_ports)
schedule_chk_task(adapter);
@@ -1151,7 +1183,7 @@ static int cxgb_close(struct net_device *dev)
struct adapter *adapter = pi->adapter;
t3_port_intr_disable(adapter, pi->port_id);
- netif_stop_queue(dev);
+ netif_tx_stop_all_queues(dev);
pi->phy.ops->power_down(&pi->phy, 1);
netif_carrier_off(dev);
t3_mac_disable(&pi->mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX);
@@ -1634,13 +1666,10 @@ static int set_rx_csum(struct net_device *dev, u32 data)
p->rx_csum_offload = data;
if (!data) {
- struct adapter *adap = p->adapter;
int i;
- for (i = p->first_qset; i < p->first_qset + p->nqsets; i++) {
- adap->params.sge.qset[i].lro = 0;
- adap->sge.qs[i].lro_enabled = 0;
- }
+ for (i = p->first_qset; i < p->first_qset + p->nqsets; i++)
+ set_qset_lro(dev, i, 0);
}
return 0;
}
@@ -1795,6 +1824,25 @@ static void get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
memset(&wol->sopass, 0, sizeof(wol->sopass));
}
+static int cxgb3_set_flags(struct net_device *dev, u32 data)
+{
+ struct port_info *pi = netdev_priv(dev);
+ int i;
+
+ if (data & ETH_FLAG_LRO) {
+ if (!pi->rx_csum_offload)
+ return -EINVAL;
+
+ for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++)
+ set_qset_lro(dev, i, 1);
+
+ } else
+ for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++)
+ set_qset_lro(dev, i, 0);
+
+ return 0;
+}
+
static const struct ethtool_ops cxgb_ethtool_ops = {
.get_settings = get_settings,
.set_settings = set_settings,
@@ -1824,6 +1872,8 @@ static const struct ethtool_ops cxgb_ethtool_ops = {
.get_regs = get_regs,
.get_wol = get_wol,
.set_tso = ethtool_op_set_tso,
+ .get_flags = ethtool_op_get_flags,
+ .set_flags = cxgb3_set_flags,
};
static int in_range(int val, int lo, int hi)
@@ -1940,11 +1990,9 @@ static int cxgb_extension_ioctl(struct net_device *dev, void __user *useraddr)
}
}
}
- if (t.lro >= 0) {
- struct sge_qset *qs = &adapter->sge.qs[t.qset_idx];
- q->lro = t.lro;
- qs->lro_enabled = t.lro;
- }
+ if (t.lro >= 0)
+ set_qset_lro(dev, t.qset_idx, t.lro);
+
break;
}
case CHELSIO_GET_QSET_PARAMS:{
@@ -2783,6 +2831,22 @@ static void __devinit print_port_info(struct adapter *adap,
}
}
+static const struct net_device_ops cxgb_netdev_ops = {
+ .ndo_open = cxgb_open,
+ .ndo_stop = cxgb_close,
+ .ndo_start_xmit = t3_eth_xmit,
+ .ndo_get_stats = cxgb_get_stats,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_multicast_list = cxgb_set_rxmode,
+ .ndo_do_ioctl = cxgb_ioctl,
+ .ndo_change_mtu = cxgb_change_mtu,
+ .ndo_set_mac_address = cxgb_set_mac_addr,
+ .ndo_vlan_rx_register = vlan_rx_register,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = cxgb_netpoll,
+#endif
+};
+
static int __devinit init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -2871,7 +2935,7 @@ static int __devinit init_one(struct pci_dev *pdev,
for (i = 0; i < ai->nports; ++i) {
struct net_device *netdev;
- netdev = alloc_etherdev(sizeof(struct port_info));
+ netdev = alloc_etherdev_mq(sizeof(struct port_info), SGE_QSETS);
if (!netdev) {
err = -ENOMEM;
goto out_free_dev;
@@ -2885,6 +2949,7 @@ static int __devinit init_one(struct pci_dev *pdev,
pi->rx_csum_offload = 1;
pi->port_id = i;
netif_carrier_off(netdev);
+ netif_tx_stop_all_queues(netdev);
netdev->irq = pdev->irq;
netdev->mem_start = mmio_start;
netdev->mem_end = mmio_start + mmio_len - 1;
@@ -2894,20 +2959,7 @@ static int __devinit init_one(struct pci_dev *pdev,
netdev->features |= NETIF_F_HIGHDMA;
netdev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
- netdev->vlan_rx_register = vlan_rx_register;
-
- netdev->open = cxgb_open;
- netdev->stop = cxgb_close;
- netdev->hard_start_xmit = t3_eth_xmit;
- netdev->get_stats = cxgb_get_stats;
- netdev->set_multicast_list = cxgb_set_rxmode;
- netdev->do_ioctl = cxgb_ioctl;
- netdev->change_mtu = cxgb_change_mtu;
- netdev->set_mac_address = cxgb_set_mac_addr;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- netdev->poll_controller = cxgb_netpoll;
-#endif
-
+ netdev->netdev_ops = &cxgb_netdev_ops;
SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops);
}
diff --git a/drivers/net/cxgb3/cxgb3_offload.c b/drivers/net/cxgb3/cxgb3_offload.c
index 265aa8a15afa..2d7f69aff1d9 100644
--- a/drivers/net/cxgb3/cxgb3_offload.c
+++ b/drivers/net/cxgb3/cxgb3_offload.c
@@ -182,7 +182,9 @@ static struct net_device *get_iff_from_mac(struct adapter *adapter,
static int cxgb_ulp_iscsi_ctl(struct adapter *adapter, unsigned int req,
void *data)
{
+ int i;
int ret = 0;
+ unsigned int val = 0;
struct ulp_iscsi_info *uiip = data;
switch (req) {
@@ -191,32 +193,55 @@ static int cxgb_ulp_iscsi_ctl(struct adapter *adapter, unsigned int req,
uiip->llimit = t3_read_reg(adapter, A_ULPRX_ISCSI_LLIMIT);
uiip->ulimit = t3_read_reg(adapter, A_ULPRX_ISCSI_ULIMIT);
uiip->tagmask = t3_read_reg(adapter, A_ULPRX_ISCSI_TAGMASK);
+
+ val = t3_read_reg(adapter, A_ULPRX_ISCSI_PSZ);
+ for (i = 0; i < 4; i++, val >>= 8)
+ uiip->pgsz_factor[i] = val & 0xFF;
+
+ val = t3_read_reg(adapter, A_TP_PARA_REG7);
+ uiip->max_txsz =
+ uiip->max_rxsz = min((val >> S_PMMAXXFERLEN0)&M_PMMAXXFERLEN0,
+ (val >> S_PMMAXXFERLEN1)&M_PMMAXXFERLEN1);
/*
* On tx, the iscsi pdu has to be <= tx page size and has to
* fit into the Tx PM FIFO.
*/
- uiip->max_txsz = min(adapter->params.tp.tx_pg_size,
- t3_read_reg(adapter, A_PM1_TX_CFG) >> 17);
- /* on rx, the iscsi pdu has to be < rx page size and the
- whole pdu + cpl headers has to fit into one sge buffer */
- uiip->max_rxsz = min_t(unsigned int,
- adapter->params.tp.rx_pg_size,
- (adapter->sge.qs[0].fl[1].buf_size -
- sizeof(struct cpl_rx_data) * 2 -
- sizeof(struct cpl_rx_data_ddp)));
+ val = min(adapter->params.tp.tx_pg_size,
+ t3_read_reg(adapter, A_PM1_TX_CFG) >> 17);
+ uiip->max_txsz = min(val, uiip->max_txsz);
+
+ /* set MaxRxData to 16224 */
+ val = t3_read_reg(adapter, A_TP_PARA_REG2);
+ if ((val >> S_MAXRXDATA) != 0x3f60) {
+ val &= (M_RXCOALESCESIZE << S_RXCOALESCESIZE);
+ val |= V_MAXRXDATA(0x3f60);
+ printk(KERN_INFO
+ "%s, iscsi set MaxRxData to 16224 (0x%x).\n",
+ adapter->name, val);
+ t3_write_reg(adapter, A_TP_PARA_REG2, val);
+ }
+
+ /*
+ * on rx, the iscsi pdu has to be < rx page size and the
+ * the max rx data length programmed in TP
+ */
+ val = min(adapter->params.tp.rx_pg_size,
+ ((t3_read_reg(adapter, A_TP_PARA_REG2)) >>
+ S_MAXRXDATA) & M_MAXRXDATA);
+ uiip->max_rxsz = min(val, uiip->max_rxsz);
break;
case ULP_ISCSI_SET_PARAMS:
t3_write_reg(adapter, A_ULPRX_ISCSI_TAGMASK, uiip->tagmask);
- /* set MaxRxData and MaxCoalesceSize to 16224 */
- t3_write_reg(adapter, A_TP_PARA_REG2, 0x3f603f60);
/* program the ddp page sizes */
- {
- int i;
- unsigned int val = 0;
- for (i = 0; i < 4; i++)
- val |= (uiip->pgsz_factor[i] & 0xF) << (8 * i);
- if (val)
- t3_write_reg(adapter, A_ULPRX_ISCSI_PSZ, val);
+ for (i = 0; i < 4; i++)
+ val |= (uiip->pgsz_factor[i] & 0xF) << (8 * i);
+ if (val && (val != t3_read_reg(adapter, A_ULPRX_ISCSI_PSZ))) {
+ printk(KERN_INFO
+ "%s, setting iscsi pgsz 0x%x, %u,%u,%u,%u.\n",
+ adapter->name, val, uiip->pgsz_factor[0],
+ uiip->pgsz_factor[1], uiip->pgsz_factor[2],
+ uiip->pgsz_factor[3]);
+ t3_write_reg(adapter, A_ULPRX_ISCSI_PSZ, val);
}
break;
default:
@@ -407,6 +432,21 @@ static int cxgb_offload_ctl(struct t3cdev *tdev, unsigned int req, void *data)
rx_page_info->page_size = tp->rx_pg_size;
rx_page_info->num = tp->rx_num_pgs;
break;
+ case GET_ISCSI_IPV4ADDR: {
+ struct iscsi_ipv4addr *p = data;
+ struct port_info *pi = netdev_priv(p->dev);
+ p->ipv4addr = pi->iscsi_ipv4addr;
+ break;
+ }
+ case GET_EMBEDDED_INFO: {
+ struct ch_embedded_info *e = data;
+
+ spin_lock(&adapter->stats_lock);
+ t3_get_fw_version(adapter, &e->fw_vers);
+ t3_get_tp_version(adapter, &e->tp_vers);
+ spin_unlock(&adapter->stats_lock);
+ break;
+ }
default:
return -EOPNOTSUPP;
}
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
index c6480be0bc1f..6c641a889471 100644
--- a/drivers/net/cxgb3/sge.c
+++ b/drivers/net/cxgb3/sge.c
@@ -36,6 +36,7 @@
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/dma-mapping.h>
+#include <net/arp.h>
#include "common.h"
#include "regs.h"
#include "sge_defs.h"
@@ -549,16 +550,15 @@ static void *alloc_ring(struct pci_dev *pdev, size_t nelem, size_t elem_size,
if (!p)
return NULL;
- if (sw_size) {
+ if (sw_size && metadata) {
s = kcalloc(nelem, sw_size, GFP_KERNEL);
if (!s) {
dma_free_coherent(&pdev->dev, len, p, *phys);
return NULL;
}
- }
- if (metadata)
*(void **)metadata = s;
+ }
memset(p, 0, len);
return p;
}
@@ -1121,10 +1121,10 @@ static void write_tx_pkt_wr(struct adapter *adap, struct sk_buff *skb,
htonl(V_WR_TID(q->token)));
}
-static inline void t3_stop_queue(struct net_device *dev, struct sge_qset *qs,
- struct sge_txq *q)
+static inline void t3_stop_tx_queue(struct netdev_queue *txq,
+ struct sge_qset *qs, struct sge_txq *q)
{
- netif_stop_queue(dev);
+ netif_tx_stop_queue(txq);
set_bit(TXQ_ETH, &qs->txq_stopped);
q->stops++;
}
@@ -1138,11 +1138,13 @@ static inline void t3_stop_queue(struct net_device *dev, struct sge_qset *qs,
*/
int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev)
{
+ int qidx;
unsigned int ndesc, pidx, credits, gen, compl;
const struct port_info *pi = netdev_priv(dev);
struct adapter *adap = pi->adapter;
- struct sge_qset *qs = pi->qs;
- struct sge_txq *q = &qs->txq[TXQ_ETH];
+ struct netdev_queue *txq;
+ struct sge_qset *qs;
+ struct sge_txq *q;
/*
* The chip min packet length is 9 octets but play safe and reject
@@ -1153,6 +1155,11 @@ int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}
+ qidx = skb_get_queue_mapping(skb);
+ qs = &pi->qs[qidx];
+ q = &qs->txq[TXQ_ETH];
+ txq = netdev_get_tx_queue(dev, qidx);
+
spin_lock(&q->lock);
reclaim_completed_tx(adap, q);
@@ -1160,7 +1167,7 @@ int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev)
ndesc = calc_tx_descs(skb);
if (unlikely(credits < ndesc)) {
- t3_stop_queue(dev, qs, q);
+ t3_stop_tx_queue(txq, qs, q);
dev_err(&adap->pdev->dev,
"%s: Tx ring %u full while queue awake!\n",
dev->name, q->cntxt_id & 7);
@@ -1170,12 +1177,12 @@ int t3_eth_xmit(struct sk_buff *skb, struct net_device *dev)
q->in_use += ndesc;
if (unlikely(credits - ndesc < q->stop_thres)) {
- t3_stop_queue(dev, qs, q);
+ t3_stop_tx_queue(txq, qs, q);
if (should_restart_tx(q) &&
test_and_clear_bit(TXQ_ETH, &qs->txq_stopped)) {
q->restarts++;
- netif_wake_queue(dev);
+ netif_tx_wake_queue(txq);
}
}
@@ -1839,7 +1846,7 @@ static void restart_tx(struct sge_qset *qs)
test_and_clear_bit(TXQ_ETH, &qs->txq_stopped)) {
qs->txq[TXQ_ETH].restarts++;
if (netif_running(qs->netdev))
- netif_wake_queue(qs->netdev);
+ netif_tx_wake_queue(qs->tx_q);
}
if (test_bit(TXQ_OFLD, &qs->txq_stopped) &&
@@ -1857,6 +1864,54 @@ static void restart_tx(struct sge_qset *qs)
}
/**
+ * cxgb3_arp_process - process an ARP request probing a private IP address
+ * @adapter: the adapter
+ * @skb: the skbuff containing the ARP request
+ *
+ * Check if the ARP request is probing the private IP address
+ * dedicated to iSCSI, generate an ARP reply if so.
+ */
+static void cxgb3_arp_process(struct adapter *adapter, struct sk_buff *skb)
+{
+ struct net_device *dev = skb->dev;
+ struct port_info *pi;
+ struct arphdr *arp;
+ unsigned char *arp_ptr;
+ unsigned char *sha;
+ __be32 sip, tip;
+
+ if (!dev)
+ return;
+
+ skb_reset_network_header(skb);
+ arp = arp_hdr(skb);
+
+ if (arp->ar_op != htons(ARPOP_REQUEST))
+ return;
+
+ arp_ptr = (unsigned char *)(arp + 1);
+ sha = arp_ptr;
+ arp_ptr += dev->addr_len;
+ memcpy(&sip, arp_ptr, sizeof(sip));
+ arp_ptr += sizeof(sip);
+ arp_ptr += dev->addr_len;
+ memcpy(&tip, arp_ptr, sizeof(tip));
+
+ pi = netdev_priv(dev);
+ if (tip != pi->iscsi_ipv4addr)
+ return;
+
+ arp_send(ARPOP_REPLY, ETH_P_ARP, sip, dev, tip, sha,
+ dev->dev_addr, sha);
+
+}
+
+static inline int is_arp(struct sk_buff *skb)
+{
+ return skb->protocol == htons(ETH_P_ARP);
+}
+
+/**
* rx_eth - process an ingress ethernet packet
* @adap: the adapter
* @rq: the response queue that received the packet
@@ -1876,11 +1931,10 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
skb_pull(skb, sizeof(*p) + pad);
skb->protocol = eth_type_trans(skb, adap->port[p->iff]);
- skb->dev->last_rx = jiffies;
pi = netdev_priv(skb->dev);
if (pi->rx_csum_offload && p->csum_valid && p->csum == htons(0xffff) &&
!p->fragment) {
- rspq_to_qset(rq)->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++;
+ qs->port_stats[SGE_PSTAT_RX_CSUM_GOOD]++;
skb->ip_summed = CHECKSUM_UNNECESSARY;
} else
skb->ip_summed = CHECKSUM_NONE;
@@ -1895,16 +1949,28 @@ static void rx_eth(struct adapter *adap, struct sge_rspq *rq,
grp,
ntohs(p->vlan),
p);
- else
+ else {
+ if (unlikely(pi->iscsi_ipv4addr &&
+ is_arp(skb))) {
+ unsigned short vtag = ntohs(p->vlan) &
+ VLAN_VID_MASK;
+ skb->dev = vlan_group_get_device(grp,
+ vtag);
+ cxgb3_arp_process(adap, skb);
+ }
__vlan_hwaccel_rx(skb, grp, ntohs(p->vlan),
rq->polling);
+ }
else
dev_kfree_skb_any(skb);
} else if (rq->polling) {
if (lro)
lro_receive_skb(&qs->lro_mgr, skb, p);
- else
+ else {
+ if (unlikely(pi->iscsi_ipv4addr && is_arp(skb)))
+ cxgb3_arp_process(adap, skb);
netif_receive_skb(skb);
+ }
} else
netif_rx(skb);
}
@@ -2308,7 +2374,7 @@ next_fl:
static inline int is_pure_response(const struct rsp_desc *r)
{
- u32 n = ntohl(r->flags) & (F_RSPD_ASYNC_NOTIF | F_RSPD_IMM_DATA_VALID);
+ __be32 n = r->flags & htonl(F_RSPD_ASYNC_NOTIF | F_RSPD_IMM_DATA_VALID);
return (n | r->len_cq) == 0;
}
@@ -2826,6 +2892,7 @@ void t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p)
* @p: configuration parameters for this queue set
* @ntxq: number of Tx queues for the queue set
* @netdev: net device associated with this queue set
+ * @netdevq: net device TX queue associated with this queue set
*
* Allocate resources and initialize an SGE queue set. A queue set
* comprises a response queue, two Rx free-buffer queues, and up to 3
@@ -2834,7 +2901,8 @@ void t3_update_qset_coalesce(struct sge_qset *qs, const struct qset_params *p)
*/
int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
int irq_vec_idx, const struct qset_params *p,
- int ntxq, struct net_device *dev)
+ int ntxq, struct net_device *dev,
+ struct netdev_queue *netdevq)
{
int i, avail, ret = -ENOMEM;
struct sge_qset *q = &adapter->sge.qs[id];
@@ -2970,6 +3038,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
q->adap = adapter;
q->netdev = dev;
+ q->tx_q = netdevq;
t3_update_qset_coalesce(q, p);
init_lro_mgr(q, lro_mgr);
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c
index 9a0898b0dbce..2d1433077a8e 100644
--- a/drivers/net/cxgb3/t3_hw.c
+++ b/drivers/net/cxgb3/t3_hw.c
@@ -925,11 +925,10 @@ int t3_get_tp_version(struct adapter *adapter, u32 *vers)
/**
* t3_check_tpsram_version - read the tp sram version
* @adapter: the adapter
- * @must_load: set to 1 if loading a new microcode image is required
*
* Reads the protocol sram version from flash.
*/
-int t3_check_tpsram_version(struct adapter *adapter, int *must_load)
+int t3_check_tpsram_version(struct adapter *adapter)
{
int ret;
u32 vers;
@@ -938,7 +937,6 @@ int t3_check_tpsram_version(struct adapter *adapter, int *must_load)
if (adapter->params.rev == T3_REV_A)
return 0;
- *must_load = 1;
ret = t3_get_tp_version(adapter, &vers);
if (ret)
@@ -949,13 +947,7 @@ int t3_check_tpsram_version(struct adapter *adapter, int *must_load)
if (major == TP_VERSION_MAJOR && minor == TP_VERSION_MINOR)
return 0;
-
- if (major != TP_VERSION_MAJOR)
- CH_ERR(adapter, "found wrong TP version (%u.%u), "
- "driver needs version %d.%d\n", major, minor,
- TP_VERSION_MAJOR, TP_VERSION_MINOR);
else {
- *must_load = 0;
CH_ERR(adapter, "found wrong TP version (%u.%u), "
"driver compiled for version %d.%d\n", major, minor,
TP_VERSION_MAJOR, TP_VERSION_MINOR);
@@ -1012,18 +1004,16 @@ int t3_get_fw_version(struct adapter *adapter, u32 *vers)
/**
* t3_check_fw_version - check if the FW is compatible with this driver
* @adapter: the adapter
- * @must_load: set to 1 if loading a new FW image is required
-
+ *
* Checks if an adapter's FW is compatible with the driver. Returns 0
* if the versions are compatible, a negative error otherwise.
*/
-int t3_check_fw_version(struct adapter *adapter, int *must_load)
+int t3_check_fw_version(struct adapter *adapter)
{
int ret;
u32 vers;
unsigned int type, major, minor;
- *must_load = 1;
ret = t3_get_fw_version(adapter, &vers);
if (ret)
return ret;
@@ -1035,17 +1025,11 @@ int t3_check_fw_version(struct adapter *adapter, int *must_load)
if (type == FW_VERSION_T3 && major == FW_VERSION_MAJOR &&
minor == FW_VERSION_MINOR)
return 0;
-
- if (major != FW_VERSION_MAJOR)
- CH_ERR(adapter, "found wrong FW version(%u.%u), "
- "driver needs version %u.%u\n", major, minor,
- FW_VERSION_MAJOR, FW_VERSION_MINOR);
- else if (minor < FW_VERSION_MINOR) {
- *must_load = 0;
+ else if (major != FW_VERSION_MAJOR || minor < FW_VERSION_MINOR)
CH_WARN(adapter, "found old FW minor version(%u.%u), "
"driver compiled for version %u.%u\n", major, minor,
FW_VERSION_MAJOR, FW_VERSION_MINOR);
- } else {
+ else {
CH_WARN(adapter, "found newer FW version(%u.%u), "
"driver compiled for version %u.%u\n", major, minor,
FW_VERSION_MAJOR, FW_VERSION_MINOR);
diff --git a/drivers/net/cxgb3/version.h b/drivers/net/cxgb3/version.h
index bb8698a86754..b1b25c37aa10 100644
--- a/drivers/net/cxgb3/version.h
+++ b/drivers/net/cxgb3/version.h
@@ -35,7 +35,7 @@
#define DRV_DESC "Chelsio T3 Network Driver"
#define DRV_NAME "cxgb3"
/* Driver version */
-#define DRV_VERSION "1.1.0-ko"
+#define DRV_VERSION "1.1.1-ko"
/* Firmware version */
#define FW_VERSION_MAJOR 7
diff --git a/drivers/net/cxgb3/vsc8211.c b/drivers/net/cxgb3/vsc8211.c
index 33f956bd6b59..d07130971b8f 100644
--- a/drivers/net/cxgb3/vsc8211.c
+++ b/drivers/net/cxgb3/vsc8211.c
@@ -262,6 +262,7 @@ static int vsc8211_get_link_status_fiber(struct cphy *cphy, int *link_ok,
return 0;
}
+#ifdef UNUSED
/*
* Enable/disable auto MDI/MDI-X in forced link speed mode.
*/
@@ -301,6 +302,7 @@ int vsc8211_set_speed_duplex(struct cphy *phy, int speed, int duplex)
err = vsc8211_set_automdi(phy, 1);
return err;
}
+#endif /* UNUSED */
static int vsc8211_power_down(struct cphy *cphy, int enable)
{
diff --git a/drivers/net/de600.c b/drivers/net/de600.c
index cb849b091f98..970f820ba814 100644
--- a/drivers/net/de600.c
+++ b/drivers/net/de600.c
@@ -369,7 +369,6 @@ static void de600_rx_intr(struct net_device *dev)
netif_rx(skb);
/* update stats */
- dev->last_rx = jiffies;
dev->stats.rx_packets++; /* count all receives */
dev->stats.rx_bytes += size; /* count all received bytes */
@@ -384,7 +383,6 @@ static struct net_device * __init de600_probe(void)
int i;
struct net_device *dev;
int err;
- DECLARE_MAC_BUF(mac);
dev = alloc_etherdev(0);
if (!dev)
@@ -439,7 +437,7 @@ static struct net_device * __init de600_probe(void)
goto out1;
}
- printk(", Ethernet Address: %s\n", print_mac(mac, dev->dev_addr));
+ printk(", Ethernet Address: %pM\n", dev->dev_addr);
dev->open = de600_open;
dev->stop = de600_close;
diff --git a/drivers/net/de620.c b/drivers/net/de620.c
index d454e143483e..bdfa89403389 100644
--- a/drivers/net/de620.c
+++ b/drivers/net/de620.c
@@ -686,7 +686,6 @@ static int de620_rx_intr(struct net_device *dev)
PRINTK(("Read %d bytes\n", size));
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb); /* deliver it "upstairs" */
- dev->last_rx = jiffies;
/* count all receives */
dev->stats.rx_packets++;
dev->stats.rx_bytes += size;
@@ -800,7 +799,6 @@ struct net_device * __init de620_probe(int unit)
struct net_device *dev;
int err = -ENOMEM;
int i;
- DECLARE_MAC_BUF(mac);
dev = alloc_etherdev(0);
if (!dev)
@@ -853,7 +851,7 @@ struct net_device * __init de620_probe(int unit)
dev->broadcast[i] = 0xff;
}
- printk(", Ethernet Address: %s", print_mac(mac, dev->dev_addr));
+ printk(", Ethernet Address: %pM", dev->dev_addr);
printk(" (%dk RAM,",
(nic_data.RAM_Size) ? (nic_data.RAM_Size >> 2) : 64);
@@ -876,10 +874,7 @@ struct net_device * __init de620_probe(int unit)
if (de620_debug) {
printk("\nEEPROM contents:\n");
printk("RAM_Size = 0x%02X\n", nic_data.RAM_Size);
- printk("NodeID = %02X:%02X:%02X:%02X:%02X:%02X\n",
- nic_data.NodeID[0], nic_data.NodeID[1],
- nic_data.NodeID[2], nic_data.NodeID[3],
- nic_data.NodeID[4], nic_data.NodeID[5]);
+ printk("NodeID = %pM\n", nic_data.NodeID);
printk("Model = %d\n", nic_data.Model);
printk("Media = %d\n", nic_data.Media);
printk("SCR = 0x%02x\n", nic_data.SCR);
@@ -1008,20 +1003,3 @@ void cleanup_module(void)
}
#endif /* MODULE */
MODULE_LICENSE("GPL");
-
-
-/*
- * (add '-DMODULE' when compiling as loadable module)
- *
- * compile-command:
- * gcc -D__KERNEL__ -Wall -Wstrict-prototypes -O2 \
- * -fomit-frame-pointer -m486 \
- * -I/usr/src/linux/include -I../../net/inet -c de620.c
-*/
-/*
- * Local variables:
- * kernel-compile-command: "gcc -D__KERNEL__ -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de620.c"
- * module-compile-command: "gcc -D__KERNEL__ -DMODULE -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de620.c"
- * compile-command: "gcc -D__KERNEL__ -DMODULE -Ilinux/include -I../../net/inet -Wall -Wstrict-prototypes -O2 -m486 -c de620.c"
- * End:
- */
diff --git a/drivers/net/declance.c b/drivers/net/declance.c
index 3e3506411ac0..7ce3053530f9 100644
--- a/drivers/net/declance.c
+++ b/drivers/net/declance.c
@@ -622,7 +622,6 @@ static int lance_rx(struct net_device *dev)
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
}
@@ -1023,7 +1022,6 @@ static int __init dec_lance_probe(struct device *bdev, const int type)
int i, ret;
unsigned long esar_base;
unsigned char *esar;
- DECLARE_MAC_BUF(mac);
if (dec_lance_debug && version_printed++ == 0)
printk(version);
@@ -1035,7 +1033,7 @@ static int __init dec_lance_probe(struct device *bdev, const int type)
dev = root_lance_dev;
while (dev) {
i++;
- lp = (struct lance_private *)dev->priv;
+ lp = netdev_priv(dev);
dev = lp->next;
}
snprintf(name, sizeof(name), fmt, i);
@@ -1223,8 +1221,7 @@ static int __init dec_lance_probe(struct device *bdev, const int type)
for (i = 0; i < 6; i++)
dev->dev_addr[i] = esar[i * 4];
- printk(", addr = %s, irq = %d\n",
- print_mac(mac, dev->dev_addr), dev->irq);
+ printk(", addr = %pM, irq = %d\n", dev->dev_addr, dev->irq);
dev->open = &lance_open;
dev->stop = &lance_close;
diff --git a/drivers/net/defxx.c b/drivers/net/defxx.c
index c062aacf229c..6445cedd5868 100644
--- a/drivers/net/defxx.c
+++ b/drivers/net/defxx.c
@@ -477,6 +477,15 @@ static void dfx_get_bars(struct device *bdev,
}
}
+static const struct net_device_ops dfx_netdev_ops = {
+ .ndo_open = dfx_open,
+ .ndo_stop = dfx_close,
+ .ndo_start_xmit = dfx_xmt_queue_pkt,
+ .ndo_get_stats = dfx_ctl_get_stats,
+ .ndo_set_multicast_list = dfx_ctl_set_multicast_list,
+ .ndo_set_mac_address = dfx_ctl_set_mac_address,
+};
+
/*
* ================
* = dfx_register =
@@ -511,7 +520,7 @@ static int __devinit dfx_register(struct device *bdev)
int dfx_bus_pci = DFX_BUS_PCI(bdev);
int dfx_bus_tc = DFX_BUS_TC(bdev);
int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
- char *print_name = bdev->bus_id;
+ const char *print_name = dev_name(bdev);
struct net_device *dev;
DFX_board_t *bp; /* board pointer */
resource_size_t bar_start = 0; /* pointer to port */
@@ -573,13 +582,7 @@ static int __devinit dfx_register(struct device *bdev)
}
/* Initialize new device structure */
-
- dev->get_stats = dfx_ctl_get_stats;
- dev->open = dfx_open;
- dev->stop = dfx_close;
- dev->hard_start_xmit = dfx_xmt_queue_pkt;
- dev->set_multicast_list = dfx_ctl_set_multicast_list;
- dev->set_mac_address = dfx_ctl_set_mac_address;
+ dev->netdev_ops = &dfx_netdev_ops;
if (dfx_bus_pci)
pci_set_master(to_pci_dev(bdev));
@@ -3103,7 +3106,6 @@ static void dfx_rcv_queue_process(
netif_rx(skb);
/* Update the rcv counters */
- bp->dev->last_rx = jiffies;
bp->rcv_total_frames++;
if (*(p_buff + RCV_BUFF_K_DA) & 0x01)
bp->rcv_multicast_frames++;
@@ -3741,10 +3743,3 @@ MODULE_AUTHOR("Lawrence V. Stefani");
MODULE_DESCRIPTION("DEC FDDIcontroller TC/EISA/PCI (DEFTA/DEFEA/DEFPA) driver "
DRV_VERSION " " DRV_RELDATE);
MODULE_LICENSE("GPL");
-
-
-/*
- * Local variables:
- * kernel-compile-command: "gcc -D__KERNEL__ -I/root/linux/include -Wall -Wstrict-prototypes -O2 -pipe -fomit-frame-pointer -fno-strength-reduce -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -c defxx.c"
- * End:
- */
diff --git a/drivers/net/depca.c b/drivers/net/depca.c
index ace39ec0a367..e4cef491dc73 100644
--- a/drivers/net/depca.c
+++ b/drivers/net/depca.c
@@ -573,7 +573,6 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device)
s16 nicsr;
u_long ioaddr;
u_long mem_start;
- DECLARE_MAC_BUF(mac);
/*
* We are now supposed to enter this function with the
@@ -601,7 +600,7 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device)
return -ENXIO;
}
- lp = (struct depca_private *) dev->priv;
+ lp = netdev_priv(dev);
mem_start = lp->mem_start;
if (!mem_start || lp->adapter < DEPCA || lp->adapter >=unknown)
@@ -633,7 +632,7 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device)
printk(", h/w address ");
status = get_hw_addr(dev);
- printk("%s", print_mac(mac, dev->dev_addr));
+ printk("%pM", dev->dev_addr);
if (status != 0) {
printk(" which has an Ethernet PROM CRC error.\n");
return -ENXIO;
@@ -821,7 +820,7 @@ out_priv:
static int depca_open(struct net_device *dev)
{
- struct depca_private *lp = (struct depca_private *) dev->priv;
+ struct depca_private *lp = netdev_priv(dev);
u_long ioaddr = dev->base_addr;
s16 nicsr;
int status = 0;
@@ -866,7 +865,7 @@ static int depca_open(struct net_device *dev)
/* Initialize the lance Rx and Tx descriptor rings. */
static void depca_init_ring(struct net_device *dev)
{
- struct depca_private *lp = (struct depca_private *) dev->priv;
+ struct depca_private *lp = netdev_priv(dev);
u_int i;
u_long offset;
@@ -924,7 +923,7 @@ static void depca_tx_timeout(struct net_device *dev)
*/
static int depca_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct depca_private *lp = (struct depca_private *) dev->priv;
+ struct depca_private *lp = netdev_priv(dev);
u_long ioaddr = dev->base_addr;
int status = 0;
@@ -972,7 +971,7 @@ static irqreturn_t depca_interrupt(int irq, void *dev_id)
return IRQ_NONE;
}
- lp = (struct depca_private *) dev->priv;
+ lp = netdev_priv(dev);
ioaddr = dev->base_addr;
spin_lock(&lp->lock);
@@ -1010,7 +1009,7 @@ static irqreturn_t depca_interrupt(int irq, void *dev_id)
/* Called with lp->lock held */
static int depca_rx(struct net_device *dev)
{
- struct depca_private *lp = (struct depca_private *) dev->priv;
+ struct depca_private *lp = netdev_priv(dev);
int i, entry;
s32 status;
@@ -1057,7 +1056,6 @@ static int depca_rx(struct net_device *dev)
/*
** Update stats
*/
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
for (i = 1; i < DEPCA_PKT_STAT_SZ - 1; i++) {
@@ -1108,7 +1106,7 @@ static int depca_rx(struct net_device *dev)
*/
static int depca_tx(struct net_device *dev)
{
- struct depca_private *lp = (struct depca_private *) dev->priv;
+ struct depca_private *lp = netdev_priv(dev);
int entry;
s32 status;
u_long ioaddr = dev->base_addr;
@@ -1149,7 +1147,7 @@ static int depca_tx(struct net_device *dev)
static int depca_close(struct net_device *dev)
{
- struct depca_private *lp = (struct depca_private *) dev->priv;
+ struct depca_private *lp = netdev_priv(dev);
s16 nicsr;
u_long ioaddr = dev->base_addr;
@@ -1185,7 +1183,7 @@ static int depca_close(struct net_device *dev)
static void LoadCSRs(struct net_device *dev)
{
- struct depca_private *lp = (struct depca_private *) dev->priv;
+ struct depca_private *lp = netdev_priv(dev);
u_long ioaddr = dev->base_addr;
outw(CSR1, DEPCA_ADDR); /* initialisation block address LSW */
@@ -1202,7 +1200,7 @@ static void LoadCSRs(struct net_device *dev)
static int InitRestartDepca(struct net_device *dev)
{
- struct depca_private *lp = (struct depca_private *) dev->priv;
+ struct depca_private *lp = netdev_priv(dev);
u_long ioaddr = dev->base_addr;
int i, status = 0;
@@ -1234,7 +1232,7 @@ static int InitRestartDepca(struct net_device *dev)
*/
static void set_multicast_list(struct net_device *dev)
{
- struct depca_private *lp = (struct depca_private *) dev->priv;
+ struct depca_private *lp = netdev_priv(dev);
u_long ioaddr = dev->base_addr;
netif_stop_queue(dev);
@@ -1263,7 +1261,7 @@ static void set_multicast_list(struct net_device *dev)
*/
static void SetMulticastFilter(struct net_device *dev)
{
- struct depca_private *lp = (struct depca_private *) dev->priv;
+ struct depca_private *lp = netdev_priv(dev);
struct dev_mc_list *dmi = dev->mc_list;
char *addrs;
int i, j, bit, byte;
@@ -1431,7 +1429,7 @@ static int __init depca_mca_probe(struct device *device)
dev->irq = irq;
dev->base_addr = iobase;
- lp = dev->priv;
+ lp = netdev_priv(dev);
lp->depca_bus = DEPCA_BUS_MCA;
lp->adapter = depca_mca_adapter_type[mdev->index];
lp->mem_start = mem_start;
@@ -1534,7 +1532,7 @@ static int __init depca_isa_probe (struct platform_device *device)
dev->base_addr = ioaddr;
dev->irq = irq; /* Use whatever value the user gave
* us, and 0 if he didn't. */
- lp = dev->priv;
+ lp = netdev_priv(dev);
lp->depca_bus = DEPCA_BUS_ISA;
lp->adapter = adapter;
lp->mem_start = mem_start;
@@ -1558,6 +1556,7 @@ static int __init depca_isa_probe (struct platform_device *device)
#ifdef CONFIG_EISA
static int __init depca_eisa_probe (struct device *device)
{
+ enum depca_type adapter = unknown;
struct eisa_device *edev;
struct net_device *dev;
struct depca_private *lp;
@@ -1576,11 +1575,15 @@ static int __init depca_eisa_probe (struct device *device)
* the EISA configuration structures (yet... :-), just rely on
* the ISA probing to sort it out... */
- depca_shmem_probe (&mem_start);
+ adapter = depca_shmem_probe (&mem_start);
+ if (adapter == unknown) {
+ status = -ENODEV;
+ goto out_free;
+ }
dev->base_addr = ioaddr;
dev->irq = irq;
- lp = dev->priv;
+ lp = netdev_priv(dev);
lp->depca_bus = DEPCA_BUS_EISA;
lp->adapter = edev->id.driver_data;
lp->mem_start = mem_start;
@@ -1605,7 +1608,7 @@ static int __devexit depca_device_remove (struct device *device)
int bus;
dev = device->driver_data;
- lp = dev->priv;
+ lp = netdev_priv(dev);
unregister_netdev (dev);
iounmap (lp->sh_mem);
@@ -1747,7 +1750,7 @@ static int __init DevicePresent(u_long ioaddr)
static int __init get_hw_addr(struct net_device *dev)
{
u_long ioaddr = dev->base_addr;
- struct depca_private *lp = dev->priv;
+ struct depca_private *lp = netdev_priv(dev);
int i, k, tmp, status = 0;
u_short j, x, chksum;
@@ -1782,7 +1785,7 @@ static int __init get_hw_addr(struct net_device *dev)
*/
static int load_packet(struct net_device *dev, struct sk_buff *skb)
{
- struct depca_private *lp = (struct depca_private *) dev->priv;
+ struct depca_private *lp = netdev_priv(dev);
int i, entry, end, len, status = 0;
entry = lp->tx_new; /* Ring around buffer number. */
@@ -1837,11 +1840,10 @@ static int load_packet(struct net_device *dev, struct sk_buff *skb)
static void depca_dbg_open(struct net_device *dev)
{
- struct depca_private *lp = (struct depca_private *) dev->priv;
+ struct depca_private *lp = netdev_priv(dev);
u_long ioaddr = dev->base_addr;
struct depca_init *p = &lp->init_block;
int i;
- DECLARE_MAC_BUF(mac);
if (depca_debug > 1) {
/* Do not copy the shadow init block into shared memory */
@@ -1880,7 +1882,7 @@ static void depca_dbg_open(struct net_device *dev)
printk("...0x%8.8x\n", readl(&lp->tx_ring[i].base));
printk("Initialisation block at 0x%8.8lx(Phys)\n", lp->mem_start);
printk(" mode: 0x%4.4x\n", p->mode);
- printk(" physical address: %s\n", print_mac(mac, p->phys_addr));
+ printk(" physical address: %pM\n", p->phys_addr);
printk(" multicast hash table: ");
for (i = 0; i < (HASH_TABLE_LEN >> 3) - 1; i++) {
printk("%2.2x:", p->mcast_table[i]);
@@ -1909,7 +1911,7 @@ static void depca_dbg_open(struct net_device *dev)
*/
static int depca_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
- struct depca_private *lp = (struct depca_private *) dev->priv;
+ struct depca_private *lp = netdev_priv(dev);
struct depca_ioctl *ioc = (struct depca_ioctl *) &rq->ifr_ifru;
int i, status = 0;
u_long ioaddr = dev->base_addr;
diff --git a/drivers/net/dl2k.c b/drivers/net/dl2k.c
index f8037110a522..c749e9fb47ef 100644
--- a/drivers/net/dl2k.c
+++ b/drivers/net/dl2k.c
@@ -85,6 +85,19 @@ static int mii_write (struct net_device *dev, int phy_addr, int reg_num,
static const struct ethtool_ops ethtool_ops;
+static const struct net_device_ops netdev_ops = {
+ .ndo_open = rio_open,
+ .ndo_start_xmit = start_xmit,
+ .ndo_stop = rio_close,
+ .ndo_get_stats = get_stats,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_set_multicast_list = set_multicast,
+ .ndo_do_ioctl = rio_ioctl,
+ .ndo_tx_timeout = rio_tx_timeout,
+ .ndo_change_mtu = change_mtu,
+};
+
static int __devinit
rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
{
@@ -97,7 +110,6 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
static int version_printed;
void *ring_space;
dma_addr_t ring_dma;
- DECLARE_MAC_BUF(mac);
if (!version_printed++)
printk ("%s", version);
@@ -198,15 +210,8 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
else if (tx_coalesce > TX_RING_SIZE-1)
tx_coalesce = TX_RING_SIZE - 1;
}
- dev->open = &rio_open;
- dev->hard_start_xmit = &start_xmit;
- dev->stop = &rio_close;
- dev->get_stats = &get_stats;
- dev->set_multicast_list = &set_multicast;
- dev->do_ioctl = &rio_ioctl;
- dev->tx_timeout = &rio_tx_timeout;
+ dev->netdev_ops = &netdev_ops;
dev->watchdog_timeo = TX_TIMEOUT;
- dev->change_mtu = &change_mtu;
SET_ETHTOOL_OPS(dev, &ethtool_ops);
#if 0
dev->features = NETIF_F_IP_CSUM;
@@ -257,8 +262,8 @@ rio_probe1 (struct pci_dev *pdev, const struct pci_device_id *ent)
card_idx++;
- printk (KERN_INFO "%s: %s, %s, IRQ %d\n",
- dev->name, np->name, print_mac(mac, dev->dev_addr), irq);
+ printk (KERN_INFO "%s: %s, %pM, IRQ %d\n",
+ dev->name, np->name, dev->dev_addr, irq);
if (tx_coalesce > 1)
printk(KERN_INFO "tx_coalesce:\t%d packets\n",
tx_coalesce);
@@ -892,7 +897,6 @@ receive_packet (struct net_device *dev)
}
#endif
netif_rx (skb);
- dev->last_rx = jiffies;
}
entry = (entry + 1) % RX_RING_SIZE;
}
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
index 5a9083e3f443..bcf92917bbf3 100644
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -137,7 +137,7 @@ typedef struct board_info {
static inline board_info_t *to_dm9000_board(struct net_device *dev)
{
- return dev->priv;
+ return netdev_priv(dev);
}
/* DM9000 network board routine ---------------------------- */
@@ -626,7 +626,7 @@ static unsigned char dm9000_type_to_char(enum dm9000_type type)
static void
dm9000_hash_table(struct net_device *dev)
{
- board_info_t *db = (board_info_t *) dev->priv;
+ board_info_t *db = netdev_priv(dev);
struct dev_mc_list *mcptr = dev->mc_list;
int mc_cnt = dev->mc_count;
int i, oft;
@@ -677,7 +677,7 @@ dm9000_hash_table(struct net_device *dev)
static void
dm9000_init_dm9000(struct net_device *dev)
{
- board_info_t *db = dev->priv;
+ board_info_t *db = netdev_priv(dev);
unsigned int imr;
dm9000_dbg(db, 1, "entering %s\n", __func__);
@@ -723,7 +723,7 @@ dm9000_init_dm9000(struct net_device *dev)
/* Our watchdog timed out. Called by the networking layer */
static void dm9000_timeout(struct net_device *dev)
{
- board_info_t *db = (board_info_t *) dev->priv;
+ board_info_t *db = netdev_priv(dev);
u8 reg_save;
unsigned long flags;
@@ -751,7 +751,7 @@ static int
dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned long flags;
- board_info_t *db = dev->priv;
+ board_info_t *db = netdev_priv(dev);
dm9000_dbg(db, 3, "%s:\n", __func__);
@@ -831,7 +831,7 @@ struct dm9000_rxhdr {
static void
dm9000_rx(struct net_device *dev)
{
- board_info_t *db = (board_info_t *) dev->priv;
+ board_info_t *db = netdev_priv(dev);
struct dm9000_rxhdr rxhdr;
struct sk_buff *skb;
u8 rxbyte, *rdptr;
@@ -928,7 +928,7 @@ dm9000_rx(struct net_device *dev)
static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
- board_info_t *db = dev->priv;
+ board_info_t *db = netdev_priv(dev);
int int_status;
u8 reg_save;
@@ -996,7 +996,7 @@ static void dm9000_poll_controller(struct net_device *dev)
static int
dm9000_open(struct net_device *dev)
{
- board_info_t *db = dev->priv;
+ board_info_t *db = netdev_priv(dev);
unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK;
if (netif_msg_ifup(db))
@@ -1046,7 +1046,7 @@ static void dm9000_msleep(board_info_t *db, unsigned int ms)
static int
dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
{
- board_info_t *db = (board_info_t *) dev->priv;
+ board_info_t *db = netdev_priv(dev);
unsigned long flags;
unsigned int reg_save;
int ret;
@@ -1093,7 +1093,7 @@ static void
dm9000_phy_write(struct net_device *dev,
int phyaddr_unused, int reg, int value)
{
- board_info_t *db = (board_info_t *) dev->priv;
+ board_info_t *db = netdev_priv(dev);
unsigned long flags;
unsigned long reg_save;
@@ -1134,7 +1134,7 @@ dm9000_phy_write(struct net_device *dev,
static void
dm9000_shutdown(struct net_device *dev)
{
- board_info_t *db = dev->priv;
+ board_info_t *db = netdev_priv(dev);
/* RESET device */
dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */
@@ -1150,7 +1150,7 @@ dm9000_shutdown(struct net_device *dev)
static int
dm9000_stop(struct net_device *ndev)
{
- board_info_t *db = ndev->priv;
+ board_info_t *db = netdev_priv(ndev);
if (netif_msg_ifdown(db))
dev_dbg(db->dev, "shutting down %s\n", ndev->name);
@@ -1197,7 +1197,7 @@ dm9000_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "dm9000_probe()\n");
/* setup board info structure */
- db = ndev->priv;
+ db = netdev_priv(ndev);
memset(db, 0, sizeof(*db));
db->dev = &pdev->dev;
@@ -1385,13 +1385,11 @@ dm9000_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ndev);
ret = register_netdev(ndev);
- if (ret == 0) {
- DECLARE_MAC_BUF(mac);
- printk(KERN_INFO "%s: dm9000%c at %p,%p IRQ %d MAC: %s (%s)\n",
+ if (ret == 0)
+ printk(KERN_INFO "%s: dm9000%c at %p,%p IRQ %d MAC: %pM (%s)\n",
ndev->name, dm9000_type_to_char(db->type),
db->io_addr, db->io_data, ndev->irq,
- print_mac(mac, ndev->dev_addr), mac_src);
- }
+ ndev->dev_addr, mac_src);
return 0;
out:
@@ -1410,7 +1408,7 @@ dm9000_drv_suspend(struct platform_device *dev, pm_message_t state)
board_info_t *db;
if (ndev) {
- db = (board_info_t *) ndev->priv;
+ db = netdev_priv(ndev);
db->in_suspend = 1;
if (netif_running(ndev)) {
@@ -1425,7 +1423,7 @@ static int
dm9000_drv_resume(struct platform_device *dev)
{
struct net_device *ndev = platform_get_drvdata(dev);
- board_info_t *db = (board_info_t *) ndev->priv;
+ board_info_t *db = netdev_priv(ndev);
if (ndev) {
@@ -1449,7 +1447,7 @@ dm9000_drv_remove(struct platform_device *pdev)
platform_set_drvdata(pdev, NULL);
unregister_netdev(ndev);
- dm9000_release_board(pdev, (board_info_t *) ndev->priv);
+ dm9000_release_board(pdev, (board_info_t *) netdev_priv(ndev));
free_netdev(ndev); /* free device structure */
dev_dbg(&pdev->dev, "released and freed device\n");
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c
index 84e14f397d9a..8ebd7d789405 100644
--- a/drivers/net/dummy.c
+++ b/drivers/net/dummy.c
@@ -57,18 +57,23 @@ static void set_multicast_list(struct net_device *dev)
{
}
+static const struct net_device_ops dummy_netdev_ops = {
+ .ndo_start_xmit = dummy_xmit,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_multicast_list = set_multicast_list,
+ .ndo_set_mac_address = dummy_set_address,
+};
+
static void dummy_setup(struct net_device *dev)
{
+ ether_setup(dev);
+
/* Initialize the device structure. */
- dev->hard_start_xmit = dummy_xmit;
- dev->set_multicast_list = set_multicast_list;
- dev->set_mac_address = dummy_set_address;
+ dev->netdev_ops = &dummy_netdev_ops;
dev->destructor = free_netdev;
/* Fill in device structure with ethernet-generic values. */
- ether_setup(dev);
dev->tx_queue_len = 0;
- dev->change_mtu = NULL;
dev->flags |= IFF_NOARP;
dev->flags &= ~IFF_MULTICAST;
random_ether_addr(dev->dev_addr);
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index e8bfcce6b319..9f38b16ccbbd 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1580,11 +1580,13 @@ static void e100_watchdog(unsigned long data)
mii_ethtool_gset(&nic->mii, &cmd);
if(mii_link_ok(&nic->mii) && !netif_carrier_ok(nic->netdev)) {
- DPRINTK(LINK, INFO, "link up, %sMbps, %s-duplex\n",
- cmd.speed == SPEED_100 ? "100" : "10",
- cmd.duplex == DUPLEX_FULL ? "full" : "half");
+ printk(KERN_INFO "e100: %s NIC Link is Up %s Mbps %s Duplex\n",
+ nic->netdev->name,
+ cmd.speed == SPEED_100 ? "100" : "10",
+ cmd.duplex == DUPLEX_FULL ? "Full" : "Half");
} else if(!mii_link_ok(&nic->mii) && netif_carrier_ok(nic->netdev)) {
- DPRINTK(LINK, INFO, "link down\n");
+ printk(KERN_INFO "e100: %s NIC Link is Down\n",
+ nic->netdev->name);
}
mii_check_link(&nic->mii);
@@ -1880,7 +1882,6 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx,
} else {
dev->stats.rx_packets++;
dev->stats.rx_bytes += actual_size;
- nic->netdev->last_rx = jiffies;
netif_receive_skb(skb);
if(work_done)
(*work_done)++;
@@ -2048,9 +2049,9 @@ static irqreturn_t e100_intr(int irq, void *dev_id)
if(stat_ack & stat_ack_rnr)
nic->ru_running = RU_SUSPENDED;
- if(likely(netif_rx_schedule_prep(netdev, &nic->napi))) {
+ if(likely(netif_rx_schedule_prep(&nic->napi))) {
e100_disable_irq(nic);
- __netif_rx_schedule(netdev, &nic->napi);
+ __netif_rx_schedule(&nic->napi);
}
return IRQ_HANDLED;
@@ -2059,7 +2060,6 @@ static irqreturn_t e100_intr(int irq, void *dev_id)
static int e100_poll(struct napi_struct *napi, int budget)
{
struct nic *nic = container_of(napi, struct nic, napi);
- struct net_device *netdev = nic->netdev;
unsigned int work_done = 0;
e100_rx_clean(nic, &work_done, budget);
@@ -2067,7 +2067,7 @@ static int e100_poll(struct napi_struct *napi, int budget)
/* If budget not fully consumed, exit the polling mode */
if (work_done < budget) {
- netif_rx_complete(netdev, napi);
+ netif_rx_complete(napi);
e100_enable_irq(nic);
}
@@ -2322,7 +2322,8 @@ static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
struct nic *nic = netdev_priv(netdev);
- if(wol->wolopts != WAKE_MAGIC && wol->wolopts != 0)
+ if ((wol->wolopts && wol->wolopts != WAKE_MAGIC) ||
+ !device_can_wakeup(&nic->pdev->dev))
return -EOPNOTSUPP;
if(wol->wolopts)
@@ -2330,6 +2331,8 @@ static int e100_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
else
nic->flags &= ~wol_magic;
+ device_set_wakeup_enable(&nic->pdev->dev, wol->wolopts);
+
e100_exec_cb(nic, NULL, e100_configure);
return 0;
@@ -2610,13 +2613,27 @@ static int e100_close(struct net_device *netdev)
return 0;
}
+static const struct net_device_ops e100_netdev_ops = {
+ .ndo_open = e100_open,
+ .ndo_stop = e100_close,
+ .ndo_start_xmit = e100_xmit_frame,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_multicast_list = e100_set_multicast_list,
+ .ndo_set_mac_address = e100_set_mac_address,
+ .ndo_change_mtu = e100_change_mtu,
+ .ndo_do_ioctl = e100_do_ioctl,
+ .ndo_tx_timeout = e100_tx_timeout,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = e100_netpoll,
+#endif
+};
+
static int __devinit e100_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct net_device *netdev;
struct nic *nic;
int err;
- DECLARE_MAC_BUF(mac);
if(!(netdev = alloc_etherdev(sizeof(struct nic)))) {
if(((1 << debug) - 1) & NETIF_MSG_PROBE)
@@ -2624,19 +2641,9 @@ static int __devinit e100_probe(struct pci_dev *pdev,
return -ENOMEM;
}
- netdev->open = e100_open;
- netdev->stop = e100_close;
- netdev->hard_start_xmit = e100_xmit_frame;
- netdev->set_multicast_list = e100_set_multicast_list;
- netdev->set_mac_address = e100_set_mac_address;
- netdev->change_mtu = e100_change_mtu;
- netdev->do_ioctl = e100_do_ioctl;
+ netdev->netdev_ops = &e100_netdev_ops;
SET_ETHTOOL_OPS(netdev, &e100_ethtool_ops);
- netdev->tx_timeout = e100_tx_timeout;
netdev->watchdog_timeo = E100_WATCHDOG_PERIOD;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- netdev->poll_controller = e100_netpoll;
-#endif
strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
nic = netdev_priv(netdev);
@@ -2734,8 +2741,10 @@ static int __devinit e100_probe(struct pci_dev *pdev,
/* Wol magic packet can be enabled from eeprom */
if((nic->mac >= mac_82558_D101_A4) &&
- (nic->eeprom[eeprom_id] & eeprom_id_wol))
+ (nic->eeprom[eeprom_id] & eeprom_id_wol)) {
nic->flags |= wol_magic;
+ device_set_wakeup_enable(&pdev->dev, true);
+ }
/* ack any pending wake events, disable PME */
pci_pme_active(pdev, false);
@@ -2746,9 +2755,9 @@ static int __devinit e100_probe(struct pci_dev *pdev,
goto err_out_free;
}
- DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %s\n",
+ DPRINTK(PROBE, INFO, "addr 0x%llx, irq %d, MAC addr %pM\n",
(unsigned long long)pci_resource_start(pdev, use_io ? 1 : 0),
- pdev->irq, print_mac(mac, netdev->dev_addr));
+ pdev->irq, netdev->dev_addr);
return 0;
@@ -2794,11 +2803,10 @@ static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
pci_save_state(pdev);
if ((nic->flags & wol_magic) | e100_asf(nic)) {
- pci_enable_wake(pdev, PCI_D3hot, 1);
- pci_enable_wake(pdev, PCI_D3cold, 1);
+ if (pci_enable_wake(pdev, PCI_D3cold, true))
+ pci_enable_wake(pdev, PCI_D3hot, true);
} else {
- pci_enable_wake(pdev, PCI_D3hot, 0);
- pci_enable_wake(pdev, PCI_D3cold, 0);
+ pci_enable_wake(pdev, PCI_D3hot, false);
}
pci_disable_device(pdev);
@@ -2843,7 +2851,7 @@ static pci_ers_result_t e100_io_error_detected(struct pci_dev *pdev, pci_channel
struct nic *nic = netdev_priv(netdev);
/* Similar to calling e100_down(), but avoids adapter I/O. */
- netdev->stop(netdev);
+ e100_close(netdev);
/* Detach; put netif into a state similar to hotplug unplug. */
napi_enable(&nic->napi);
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 62f62970f978..f5581de04757 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -284,7 +284,6 @@ struct e1000_adapter {
int cleaned_count);
struct e1000_rx_ring *rx_ring; /* One per active queue */
struct napi_struct napi;
- struct net_device *polling_netdev; /* One per active queue */
int num_tx_queues;
int num_rx_queues;
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 872799b746f5..26474c92193f 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -888,6 +888,26 @@ static int e1000_is_need_ioport(struct pci_dev *pdev)
}
}
+static const struct net_device_ops e1000_netdev_ops = {
+ .ndo_open = e1000_open,
+ .ndo_stop = e1000_close,
+ .ndo_start_xmit = e1000_xmit_frame,
+ .ndo_get_stats = e1000_get_stats,
+ .ndo_set_rx_mode = e1000_set_rx_mode,
+ .ndo_set_mac_address = e1000_set_mac,
+ .ndo_tx_timeout = e1000_tx_timeout,
+ .ndo_change_mtu = e1000_change_mtu,
+ .ndo_do_ioctl = e1000_ioctl,
+ .ndo_validate_addr = eth_validate_addr,
+
+ .ndo_vlan_rx_register = e1000_vlan_rx_register,
+ .ndo_vlan_rx_add_vid = e1000_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = e1000_vlan_rx_kill_vid,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = e1000_netpoll,
+#endif
+};
+
/**
* e1000_probe - Device Initialization Routine
* @pdev: PCI device information struct
@@ -912,7 +932,6 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
u16 eeprom_data = 0;
u16 eeprom_apme_mask = E1000_EEPROM_APME;
int bars, need_ioport;
- DECLARE_MAC_BUF(mac);
/* do not allocate ioport bars when not needed */
need_ioport = e1000_is_need_ioport(pdev);
@@ -967,8 +986,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
hw->back = adapter;
err = -EIO;
- hw->hw_addr = ioremap(pci_resource_start(pdev, BAR_0),
- pci_resource_len(pdev, BAR_0));
+ hw->hw_addr = pci_ioremap_bar(pdev, BAR_0);
if (!hw->hw_addr)
goto err_ioremap;
@@ -983,24 +1001,11 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
}
}
- netdev->open = &e1000_open;
- netdev->stop = &e1000_close;
- netdev->hard_start_xmit = &e1000_xmit_frame;
- netdev->get_stats = &e1000_get_stats;
- netdev->set_rx_mode = &e1000_set_rx_mode;
- netdev->set_mac_address = &e1000_set_mac;
- netdev->change_mtu = &e1000_change_mtu;
- netdev->do_ioctl = &e1000_ioctl;
+ netdev->netdev_ops = &e1000_netdev_ops;
e1000_set_ethtool_ops(netdev);
- netdev->tx_timeout = &e1000_tx_timeout;
netdev->watchdog_timeo = 5 * HZ;
netif_napi_add(netdev, &adapter->napi, e1000_clean, 64);
- netdev->vlan_rx_register = e1000_vlan_rx_register;
- netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid;
- netdev->vlan_rx_kill_vid = e1000_vlan_rx_kill_vid;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- netdev->poll_controller = e1000_netpoll;
-#endif
+
strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
adapter->bd_number = cards_found;
@@ -1016,9 +1021,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
* because it depends on mac_type */
if ((hw->mac_type == e1000_ich8lan) &&
(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
- hw->flash_address =
- ioremap(pci_resource_start(pdev, 1),
- pci_resource_len(pdev, 1));
+ hw->flash_address = pci_ioremap_bar(pdev, 1);
if (!hw->flash_address)
goto err_flashmap;
}
@@ -1195,7 +1198,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
(hw->bus_width == e1000_bus_width_pciex_1) ? "Width x1" :
"32-bit"));
- printk("%s\n", print_mac(mac, netdev->dev_addr));
+ printk("%pM\n", netdev->dev_addr);
if (hw->bus_type == e1000_bus_type_pci_express) {
DPRINTK(PROBE, WARNING, "This device (id %04x:%04x) will no "
@@ -1239,12 +1242,8 @@ err_eeprom:
if (hw->flash_address)
iounmap(hw->flash_address);
err_flashmap:
- for (i = 0; i < adapter->num_rx_queues; i++)
- dev_put(&adapter->polling_netdev[i]);
-
kfree(adapter->tx_ring);
kfree(adapter->rx_ring);
- kfree(adapter->polling_netdev);
err_sw_init:
iounmap(hw->hw_addr);
err_ioremap:
@@ -1272,7 +1271,6 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
struct net_device *netdev = pci_get_drvdata(pdev);
struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
- int i;
cancel_work_sync(&adapter->reset_task);
@@ -1282,9 +1280,6 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
* would have already happened in close and is redundant. */
e1000_release_hw_control(adapter);
- for (i = 0; i < adapter->num_rx_queues; i++)
- dev_put(&adapter->polling_netdev[i]);
-
unregister_netdev(netdev);
if (!e1000_check_phy_reset_block(hw))
@@ -1292,7 +1287,6 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
kfree(adapter->tx_ring);
kfree(adapter->rx_ring);
- kfree(adapter->polling_netdev);
iounmap(hw->hw_addr);
if (hw->flash_address)
@@ -1318,7 +1312,6 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
- int i;
/* PCI config space info */
@@ -1375,11 +1368,6 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
return -ENOMEM;
}
- for (i = 0; i < adapter->num_rx_queues; i++) {
- adapter->polling_netdev[i].priv = adapter;
- dev_hold(&adapter->polling_netdev[i]);
- set_bit(__LINK_STATE_START, &adapter->polling_netdev[i].state);
- }
spin_lock_init(&adapter->tx_queue_lock);
/* Explicitly disable IRQ since the NIC can be in any state. */
@@ -1397,8 +1385,7 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter)
* @adapter: board private structure to initialize
*
* We allocate one ring per queue at run-time since we don't know the
- * number of queues at compile-time. The polling_netdev array is
- * intended for Multiqueue, but should work fine with a single queue.
+ * number of queues at compile-time.
**/
static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter)
@@ -1415,15 +1402,6 @@ static int __devinit e1000_alloc_queues(struct e1000_adapter *adapter)
return -ENOMEM;
}
- adapter->polling_netdev = kcalloc(adapter->num_rx_queues,
- sizeof(struct net_device),
- GFP_KERNEL);
- if (!adapter->polling_netdev) {
- kfree(adapter->tx_ring);
- kfree(adapter->rx_ring);
- return -ENOMEM;
- }
-
return E1000_SUCCESS;
}
@@ -2521,10 +2499,11 @@ static void e1000_watchdog(unsigned long data)
&adapter->link_duplex);
ctrl = er32(CTRL);
- DPRINTK(LINK, INFO, "NIC Link is Up %d Mbps %s, "
- "Flow Control: %s\n",
- adapter->link_speed,
- adapter->link_duplex == FULL_DUPLEX ?
+ printk(KERN_INFO "e1000: %s NIC Link is Up %d Mbps %s, "
+ "Flow Control: %s\n",
+ netdev->name,
+ adapter->link_speed,
+ adapter->link_duplex == FULL_DUPLEX ?
"Full Duplex" : "Half Duplex",
((ctrl & E1000_CTRL_TFCE) && (ctrl &
E1000_CTRL_RFCE)) ? "RX/TX" : ((ctrl &
@@ -2600,7 +2579,8 @@ static void e1000_watchdog(unsigned long data)
if (netif_carrier_ok(netdev)) {
adapter->link_speed = 0;
adapter->link_duplex = 0;
- DPRINTK(LINK, INFO, "NIC Link is Down\n");
+ printk(KERN_INFO "e1000: %s NIC Link is Down\n",
+ netdev->name);
netif_carrier_off(netdev);
netif_stop_queue(netdev);
mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ));
@@ -3707,12 +3687,12 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
- if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) {
+ if (likely(netif_rx_schedule_prep(&adapter->napi))) {
adapter->total_tx_bytes = 0;
adapter->total_tx_packets = 0;
adapter->total_rx_bytes = 0;
adapter->total_rx_packets = 0;
- __netif_rx_schedule(netdev, &adapter->napi);
+ __netif_rx_schedule(&adapter->napi);
} else
e1000_irq_enable(adapter);
@@ -3767,12 +3747,12 @@ static irqreturn_t e1000_intr(int irq, void *data)
ew32(IMC, ~0);
E1000_WRITE_FLUSH();
}
- if (likely(netif_rx_schedule_prep(netdev, &adapter->napi))) {
+ if (likely(netif_rx_schedule_prep(&adapter->napi))) {
adapter->total_tx_bytes = 0;
adapter->total_tx_packets = 0;
adapter->total_rx_bytes = 0;
adapter->total_rx_packets = 0;
- __netif_rx_schedule(netdev, &adapter->napi);
+ __netif_rx_schedule(&adapter->napi);
} else
/* this really should not happen! if it does it is basically a
* bug, but not a hard error, so enable ints and continue */
@@ -3791,8 +3771,7 @@ static int e1000_clean(struct napi_struct *napi, int budget)
struct net_device *poll_dev = adapter->netdev;
int tx_cleaned = 0, work_done = 0;
- /* Must NOT use netdev_priv macro here. */
- adapter = poll_dev->priv;
+ adapter = netdev_priv(poll_dev);
/* e1000_clean is called per-cpu. This lock protects
* tx_ring[0] from being cleaned by multiple cpus
@@ -3814,7 +3793,7 @@ static int e1000_clean(struct napi_struct *napi, int budget)
if (work_done < budget) {
if (likely(adapter->itr_setting & 3))
e1000_set_itr(adapter);
- netif_rx_complete(poll_dev, napi);
+ netif_rx_complete(napi);
e1000_irq_enable(adapter);
}
@@ -4104,8 +4083,6 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
netif_receive_skb(skb);
}
- netdev->last_rx = jiffies;
-
next_desc:
rx_desc->status = 0;
@@ -4789,7 +4766,7 @@ static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
pci_channel_state_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
netif_device_detach(netdev);
@@ -4811,7 +4788,7 @@ static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev,
static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
int err;
@@ -4845,7 +4822,7 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
static void e1000_io_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct e1000_adapter *adapter = netdev->priv;
+ struct e1000_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
e1000_init_manageability(adapter);
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c
index b2c910c52df9..cf43ee743b3c 100644
--- a/drivers/net/e1000e/82571.c
+++ b/drivers/net/e1000e/82571.c
@@ -28,6 +28,7 @@
/*
* 82571EB Gigabit Ethernet Controller
+ * 82571EB Gigabit Ethernet Controller (Copper)
* 82571EB Gigabit Ethernet Controller (Fiber)
* 82571EB Dual Port Gigabit Mezzanine Adapter
* 82571EB Quad Port Gigabit Mezzanine Adapter
@@ -331,8 +332,9 @@ static s32 e1000_get_variants_82571(struct e1000_adapter *adapter)
case e1000_82573:
if (pdev->device == E1000_DEV_ID_82573L) {
- e1000_read_nvm(&adapter->hw, NVM_INIT_3GIO_3, 1,
- &eeprom_data);
+ if (e1000_read_nvm(&adapter->hw, NVM_INIT_3GIO_3, 1,
+ &eeprom_data) < 0)
+ break;
if (eeprom_data & NVM_WORD1A_ASPM_MASK)
adapter->flags &= ~FLAG_HAS_JUMBO_FRAMES;
}
@@ -973,6 +975,12 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
ew32(CTRL_EXT, reg);
}
+ if (hw->mac.type == e1000_82571) {
+ reg = er32(PBA_ECC);
+ reg |= E1000_PBA_ECC_CORR_EN;
+ ew32(PBA_ECC, reg);
+ }
+
/* PCI-Ex Control Register */
if (hw->mac.type == e1000_82574) {
reg = er32(GCR);
@@ -1111,8 +1119,8 @@ static s32 e1000_setup_link_82571(struct e1000_hw *hw)
* set it to full.
*/
if ((hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) &&
- hw->fc.type == e1000_fc_default)
- hw->fc.type = e1000_fc_full;
+ hw->fc.requested_mode == e1000_fc_default)
+ hw->fc.requested_mode = e1000_fc_full;
return e1000e_setup_link(hw);
}
@@ -1387,6 +1395,7 @@ static struct e1000_phy_operations e82_phy_ops_igp = {
.set_d0_lplu_state = e1000_set_d0_lplu_state_82571,
.set_d3_lplu_state = e1000e_set_d3_lplu_state,
.write_phy_reg = e1000e_write_phy_reg_igp,
+ .cfg_on_link_up = NULL,
};
static struct e1000_phy_operations e82_phy_ops_m88 = {
@@ -1403,6 +1412,7 @@ static struct e1000_phy_operations e82_phy_ops_m88 = {
.set_d0_lplu_state = e1000_set_d0_lplu_state_82571,
.set_d3_lplu_state = e1000e_set_d3_lplu_state,
.write_phy_reg = e1000e_write_phy_reg_m88,
+ .cfg_on_link_up = NULL,
};
static struct e1000_phy_operations e82_phy_ops_bm = {
@@ -1419,6 +1429,7 @@ static struct e1000_phy_operations e82_phy_ops_bm = {
.set_d0_lplu_state = e1000_set_d0_lplu_state_82571,
.set_d3_lplu_state = e1000e_set_d3_lplu_state,
.write_phy_reg = e1000e_write_phy_reg_bm2,
+ .cfg_on_link_up = NULL,
};
static struct e1000_nvm_operations e82571_nvm_ops = {
diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h
index 48f79ecb82a0..e6caf29d4252 100644
--- a/drivers/net/e1000e/defines.h
+++ b/drivers/net/e1000e/defines.h
@@ -372,6 +372,13 @@
#define E1000_ICR_TXQ1 0x00800000 /* Tx Queue 1 Interrupt */
#define E1000_ICR_OTHER 0x01000000 /* Other Interrupts */
+/* PBA ECC Register */
+#define E1000_PBA_ECC_COUNTER_MASK 0xFFF00000 /* ECC counter mask */
+#define E1000_PBA_ECC_COUNTER_SHIFT 20 /* ECC counter shift value */
+#define E1000_PBA_ECC_CORR_EN 0x00000001 /* ECC correction enable */
+#define E1000_PBA_ECC_STAT_CLR 0x00000002 /* Clear ECC error counter */
+#define E1000_PBA_ECC_INT_EN 0x00000004 /* Enable ICR bit 5 for ECC */
+
/*
* This defines the bits that are set in the Interrupt Mask
* Set/Read Register. Each bit is documented below:
@@ -565,6 +572,7 @@
#define E1000_EECD_FLUPD 0x00080000 /* Update FLASH */
#define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */
#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */
+#define E1000_EECD_SEC1VAL_VALID_MASK (E1000_EECD_AUTO_RD | E1000_EECD_PRES)
#define E1000_NVM_RW_REG_DATA 16 /* Offset to data in NVM read/write registers */
#define E1000_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index c55fd6fdb91c..37bcb190eef8 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -193,6 +193,7 @@ struct e1000_adapter {
u16 mng_vlan_id;
u16 link_speed;
u16 link_duplex;
+ u16 eeprom_vers;
spinlock_t tx_queue_lock; /* prevent concurrent tail updates */
@@ -388,6 +389,7 @@ extern int e1000e_setup_tx_resources(struct e1000_adapter *adapter);
extern void e1000e_free_rx_resources(struct e1000_adapter *adapter);
extern void e1000e_free_tx_resources(struct e1000_adapter *adapter);
extern void e1000e_update_stats(struct e1000_adapter *adapter);
+extern bool e1000_has_link(struct e1000_adapter *adapter);
extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter);
extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter);
diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c
index da9c09c248ed..8964838c686b 100644
--- a/drivers/net/e1000e/es2lan.c
+++ b/drivers/net/e1000e/es2lan.c
@@ -112,6 +112,11 @@ static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw);
static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw);
static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw);
static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex);
+static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw);
+static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
+ u16 *data);
+static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
+ u16 data);
/**
* e1000_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs.
@@ -275,8 +280,6 @@ static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw)
u16 mask;
mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
- mask |= E1000_SWFW_CSR_SM;
-
return e1000_acquire_swfw_sync_80003es2lan(hw, mask);
}
@@ -292,7 +295,36 @@ static void e1000_release_phy_80003es2lan(struct e1000_hw *hw)
u16 mask;
mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
- mask |= E1000_SWFW_CSR_SM;
+ e1000_release_swfw_sync_80003es2lan(hw, mask);
+}
+
+/**
+ * e1000_acquire_mac_csr_80003es2lan - Acquire rights to access Kumeran register
+ * @hw: pointer to the HW structure
+ *
+ * Acquire the semaphore to access the Kumeran interface.
+ *
+ **/
+static s32 e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw)
+{
+ u16 mask;
+
+ mask = E1000_SWFW_CSR_SM;
+
+ return e1000_acquire_swfw_sync_80003es2lan(hw, mask);
+}
+
+/**
+ * e1000_release_mac_csr_80003es2lan - Release rights to access Kumeran Register
+ * @hw: pointer to the HW structure
+ *
+ * Release the semaphore used to access the Kumeran interface
+ **/
+static void e1000_release_mac_csr_80003es2lan(struct e1000_hw *hw)
+{
+ u16 mask;
+
+ mask = E1000_SWFW_CSR_SM;
e1000_release_swfw_sync_80003es2lan(hw, mask);
}
@@ -347,7 +379,7 @@ static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask)
u32 swmask = mask;
u32 fwmask = mask << 16;
s32 i = 0;
- s32 timeout = 200;
+ s32 timeout = 50;
while (i < timeout) {
if (e1000e_get_hw_semaphore(hw))
@@ -715,13 +747,7 @@ static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
ret_val = e1000e_get_speed_and_duplex_copper(hw,
speed,
duplex);
- if (ret_val)
- return ret_val;
- if (*speed == SPEED_1000)
- ret_val = e1000_cfg_kmrn_1000_80003es2lan(hw);
- else
- ret_val = e1000_cfg_kmrn_10_100_80003es2lan(hw,
- *duplex);
+ hw->phy.ops.cfg_on_link_up(hw);
} else {
ret_val = e1000e_get_speed_and_duplex_fiber_serdes(hw,
speed,
@@ -763,8 +789,10 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
ctrl = er32(CTRL);
+ ret_val = e1000_acquire_phy_80003es2lan(hw);
hw_dbg(hw, "Issuing a global reset to MAC\n");
ew32(CTRL, ctrl | E1000_CTRL_RST);
+ e1000_release_phy_80003es2lan(hw);
ret_val = e1000e_get_auto_rd_done(hw);
if (ret_val)
@@ -907,8 +935,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
struct e1000_phy_info *phy = &hw->phy;
s32 ret_val;
u32 ctrl_ext;
- u32 i = 0;
- u16 data, data2;
+ u16 data;
ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, &data);
if (ret_val)
@@ -972,19 +999,20 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
}
/* Bypass Rx and Tx FIFO's */
- ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL,
+ ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
+ E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL,
E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS |
E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS);
if (ret_val)
return ret_val;
- ret_val = e1000e_read_kmrn_reg(hw,
+ ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE,
&data);
if (ret_val)
return ret_val;
data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE;
- ret_val = e1000e_write_kmrn_reg(hw,
+ ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE,
data);
if (ret_val)
@@ -1019,18 +1047,9 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
if (ret_val)
return ret_val;
- do {
- ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL,
- &data);
- if (ret_val)
- return ret_val;
-
- ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL,
- &data2);
- if (ret_val)
- return ret_val;
- i++;
- } while ((data != data2) && (i < GG82563_MAX_KMRN_RETRY));
+ ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &data);
+ if (ret_val)
+ return ret_val;
data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, data);
@@ -1077,23 +1096,27 @@ static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
* iteration and increase the max iterations when
* polling the phy; this fixes erroneous timeouts at 10Mbps.
*/
- ret_val = e1000e_write_kmrn_reg(hw, GG82563_REG(0x34, 4), 0xFFFF);
+ ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 4),
+ 0xFFFF);
if (ret_val)
return ret_val;
- ret_val = e1000e_read_kmrn_reg(hw, GG82563_REG(0x34, 9), &reg_data);
+ ret_val = e1000_read_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
+ &reg_data);
if (ret_val)
return ret_val;
reg_data |= 0x3F;
- ret_val = e1000e_write_kmrn_reg(hw, GG82563_REG(0x34, 9), reg_data);
+ ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
+ reg_data);
if (ret_val)
return ret_val;
- ret_val = e1000e_read_kmrn_reg(hw,
+ ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
&reg_data);
if (ret_val)
return ret_val;
reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING;
- ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
+ ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
+ E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
reg_data);
if (ret_val)
return ret_val;
@@ -1108,6 +1131,35 @@ static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
}
/**
+ * e1000_cfg_on_link_up_80003es2lan - es2 link configuration after link-up
+ * @hw: pointer to the HW structure
+ * @duplex: current duplex setting
+ *
+ * Configure the KMRN interface by applying last minute quirks for
+ * 10/100 operation.
+ **/
+static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw)
+{
+ s32 ret_val = 0;
+ u16 speed;
+ u16 duplex;
+
+ if (hw->phy.media_type == e1000_media_type_copper) {
+ ret_val = e1000e_get_speed_and_duplex_copper(hw, &speed,
+ &duplex);
+ if (ret_val)
+ return ret_val;
+
+ if (speed == SPEED_1000)
+ ret_val = e1000_cfg_kmrn_1000_80003es2lan(hw);
+ else
+ ret_val = e1000_cfg_kmrn_10_100_80003es2lan(hw, duplex);
+ }
+
+ return ret_val;
+}
+
+/**
* e1000_cfg_kmrn_10_100_80003es2lan - Apply "quirks" for 10/100 operation
* @hw: pointer to the HW structure
* @duplex: current duplex setting
@@ -1123,8 +1175,9 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
u16 reg_data, reg_data2;
reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT;
- ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
- reg_data);
+ ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
+ E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
+ reg_data);
if (ret_val)
return ret_val;
@@ -1170,8 +1223,9 @@ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
u32 i = 0;
reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT;
- ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
- reg_data);
+ ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
+ E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
+ reg_data);
if (ret_val)
return ret_val;
@@ -1199,6 +1253,71 @@ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
}
/**
+ * e1000_read_kmrn_reg_80003es2lan - Read kumeran register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to be read
+ * @data: pointer to the read data
+ *
+ * Acquire semaphore, then read the PHY register at offset
+ * using the kumeran interface. The information retrieved is stored in data.
+ * Release the semaphore before exiting.
+ **/
+static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
+ u16 *data)
+{
+ u32 kmrnctrlsta;
+ s32 ret_val = 0;
+
+ ret_val = e1000_acquire_mac_csr_80003es2lan(hw);
+ if (ret_val)
+ return ret_val;
+
+ kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
+ E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
+ ew32(KMRNCTRLSTA, kmrnctrlsta);
+
+ udelay(2);
+
+ kmrnctrlsta = er32(KMRNCTRLSTA);
+ *data = (u16)kmrnctrlsta;
+
+ e1000_release_mac_csr_80003es2lan(hw);
+
+ return ret_val;
+}
+
+/**
+ * e1000_write_kmrn_reg_80003es2lan - Write kumeran register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Acquire semaphore, then write the data to PHY register
+ * at the offset using the kumeran interface. Release semaphore
+ * before exiting.
+ **/
+static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
+ u16 data)
+{
+ u32 kmrnctrlsta;
+ s32 ret_val = 0;
+
+ ret_val = e1000_acquire_mac_csr_80003es2lan(hw);
+ if (ret_val)
+ return ret_val;
+
+ kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
+ E1000_KMRNCTRLSTA_OFFSET) | data;
+ ew32(KMRNCTRLSTA, kmrnctrlsta);
+
+ udelay(2);
+
+ e1000_release_mac_csr_80003es2lan(hw);
+
+ return ret_val;
+}
+
+/**
* e1000_clear_hw_cntrs_80003es2lan - Clear device specific hardware counters
* @hw: pointer to the HW structure
*
@@ -1276,6 +1395,7 @@ static struct e1000_phy_operations es2_phy_ops = {
.set_d0_lplu_state = NULL,
.set_d3_lplu_state = e1000e_set_d3_lplu_state,
.write_phy_reg = e1000_write_phy_reg_gg82563_80003es2lan,
+ .cfg_on_link_up = e1000_cfg_on_link_up_80003es2lan,
};
static struct e1000_nvm_operations es2_nvm_ops = {
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c
index 62421ce96311..e48956d924b0 100644
--- a/drivers/net/e1000e/ethtool.c
+++ b/drivers/net/e1000e/ethtool.c
@@ -173,11 +173,8 @@ static int e1000_get_settings(struct net_device *netdev,
static u32 e1000_get_link(struct net_device *netdev)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
- struct e1000_hw *hw = &adapter->hw;
- u32 status;
-
- status = er32(STATUS);
- return (status & E1000_STATUS_LU) ? 1 : 0;
+
+ return e1000_has_link(adapter);
}
static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx)
@@ -249,7 +246,7 @@ static int e1000_set_settings(struct net_device *netdev,
ADVERTISED_Autoneg;
ecmd->advertising = hw->phy.autoneg_advertised;
if (adapter->fc_autoneg)
- hw->fc.original_type = e1000_fc_default;
+ hw->fc.requested_mode = e1000_fc_default;
} else {
if (e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) {
clear_bit(__E1000_RESETTING, &adapter->state);
@@ -279,11 +276,11 @@ static void e1000_get_pauseparam(struct net_device *netdev,
pause->autoneg =
(adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE);
- if (hw->fc.type == e1000_fc_rx_pause) {
+ if (hw->fc.current_mode == e1000_fc_rx_pause) {
pause->rx_pause = 1;
- } else if (hw->fc.type == e1000_fc_tx_pause) {
+ } else if (hw->fc.current_mode == e1000_fc_tx_pause) {
pause->tx_pause = 1;
- } else if (hw->fc.type == e1000_fc_full) {
+ } else if (hw->fc.current_mode == e1000_fc_full) {
pause->rx_pause = 1;
pause->tx_pause = 1;
}
@@ -301,19 +298,8 @@ static int e1000_set_pauseparam(struct net_device *netdev,
while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
msleep(1);
- if (pause->rx_pause && pause->tx_pause)
- hw->fc.type = e1000_fc_full;
- else if (pause->rx_pause && !pause->tx_pause)
- hw->fc.type = e1000_fc_rx_pause;
- else if (!pause->rx_pause && pause->tx_pause)
- hw->fc.type = e1000_fc_tx_pause;
- else if (!pause->rx_pause && !pause->tx_pause)
- hw->fc.type = e1000_fc_none;
-
- hw->fc.original_type = hw->fc.type;
-
if (adapter->fc_autoneg == AUTONEG_ENABLE) {
- hw->fc.type = e1000_fc_default;
+ hw->fc.requested_mode = e1000_fc_default;
if (netif_running(adapter->netdev)) {
e1000e_down(adapter);
e1000e_up(adapter);
@@ -321,6 +307,17 @@ static int e1000_set_pauseparam(struct net_device *netdev,
e1000e_reset(adapter);
}
} else {
+ if (pause->rx_pause && pause->tx_pause)
+ hw->fc.requested_mode = e1000_fc_full;
+ else if (pause->rx_pause && !pause->tx_pause)
+ hw->fc.requested_mode = e1000_fc_rx_pause;
+ else if (!pause->rx_pause && pause->tx_pause)
+ hw->fc.requested_mode = e1000_fc_tx_pause;
+ else if (!pause->rx_pause && !pause->tx_pause)
+ hw->fc.requested_mode = e1000_fc_none;
+
+ hw->fc.current_mode = hw->fc.requested_mode;
+
retval = ((hw->phy.media_type == e1000_media_type_fiber) ?
hw->mac.ops.setup_link(hw) : e1000e_force_mac_fc(hw));
}
@@ -495,18 +492,19 @@ static int e1000_get_eeprom(struct net_device *netdev,
for (i = 0; i < last_word - first_word + 1; i++) {
ret_val = e1000_read_nvm(hw, first_word + i, 1,
&eeprom_buff[i]);
- if (ret_val) {
- /* a read error occurred, throw away the
- * result */
- memset(eeprom_buff, 0xff, sizeof(eeprom_buff));
+ if (ret_val)
break;
- }
}
}
- /* Device's eeprom is always little-endian, word addressable */
- for (i = 0; i < last_word - first_word + 1; i++)
- le16_to_cpus(&eeprom_buff[i]);
+ if (ret_val) {
+ /* a read error occurred, throw away the result */
+ memset(eeprom_buff, 0xff, sizeof(eeprom_buff));
+ } else {
+ /* Device's eeprom is always little-endian, word addressable */
+ for (i = 0; i < last_word - first_word + 1; i++)
+ le16_to_cpus(&eeprom_buff[i]);
+ }
memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len);
kfree(eeprom_buff);
@@ -558,6 +556,9 @@ static int e1000_set_eeprom(struct net_device *netdev,
ret_val = e1000_read_nvm(hw, last_word, 1,
&eeprom_buff[last_word - first_word]);
+ if (ret_val)
+ goto out;
+
/* Device's eeprom is always little-endian, word addressable */
for (i = 0; i < last_word - first_word + 1; i++)
le16_to_cpus(&eeprom_buff[i]);
@@ -570,15 +571,18 @@ static int e1000_set_eeprom(struct net_device *netdev,
ret_val = e1000_write_nvm(hw, first_word,
last_word - first_word + 1, eeprom_buff);
+ if (ret_val)
+ goto out;
+
/*
* Update the checksum over the first part of the EEPROM if needed
- * and flush shadow RAM for 82573 controllers
+ * and flush shadow RAM for applicable controllers
*/
- if ((ret_val == 0) && ((first_word <= NVM_CHECKSUM_REG) ||
- (hw->mac.type == e1000_82574) ||
- (hw->mac.type == e1000_82573)))
- e1000e_update_nvm_checksum(hw);
+ if ((first_word <= NVM_CHECKSUM_REG) ||
+ (hw->mac.type == e1000_82574) || (hw->mac.type == e1000_82573))
+ ret_val = e1000e_update_nvm_checksum(hw);
+out:
kfree(eeprom_buff);
return ret_val;
}
@@ -588,7 +592,6 @@ static void e1000_get_drvinfo(struct net_device *netdev,
{
struct e1000_adapter *adapter = netdev_priv(netdev);
char firmware_version[32];
- u16 eeprom_data;
strncpy(drvinfo->driver, e1000e_driver_name, 32);
strncpy(drvinfo->version, e1000e_driver_version, 32);
@@ -597,11 +600,10 @@ static void e1000_get_drvinfo(struct net_device *netdev,
* EEPROM image version # is reported as firmware version # for
* PCI-E controllers
*/
- e1000_read_nvm(&adapter->hw, 5, 1, &eeprom_data);
sprintf(firmware_version, "%d.%d-%d",
- (eeprom_data & 0xF000) >> 12,
- (eeprom_data & 0x0FF0) >> 4,
- eeprom_data & 0x000F);
+ (adapter->eeprom_vers & 0xF000) >> 12,
+ (adapter->eeprom_vers & 0x0FF0) >> 4,
+ (adapter->eeprom_vers & 0x000F));
strncpy(drvinfo->fw_version, firmware_version, 32);
strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
@@ -865,7 +867,7 @@ static int e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data)
for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
if ((e1000_read_nvm(&adapter->hw, i, 1, &temp)) < 0) {
*data = 1;
- break;
+ return *data;
}
checksum += temp;
}
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
index f66ed37a7f76..f25e961c6b3b 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/e1000e/hw.h
@@ -87,6 +87,7 @@ enum e1e_registers {
E1000_EEMNGCTL = 0x01010, /* MNG EEprom Control */
E1000_EEWR = 0x0102C, /* EEPROM Write Register - RW */
E1000_FLOP = 0x0103C, /* FLASH Opcode Register */
+ E1000_PBA_ECC = 0x01100, /* PBA ECC Register */
E1000_ERT = 0x02008, /* Early Rx Threshold - RW */
E1000_FCRTL = 0x02160, /* Flow Control Receive Threshold Low - RW */
E1000_FCRTH = 0x02168, /* Flow Control Receive Threshold High - RW */
@@ -436,7 +437,7 @@ enum e1000_rev_polarity{
e1000_rev_polarity_undefined = 0xFF
};
-enum e1000_fc_type {
+enum e1000_fc_mode {
e1000_fc_none = 0,
e1000_fc_rx_pause,
e1000_fc_tx_pause,
@@ -738,6 +739,7 @@ struct e1000_phy_operations {
s32 (*set_d0_lplu_state)(struct e1000_hw *, bool);
s32 (*set_d3_lplu_state)(struct e1000_hw *, bool);
s32 (*write_phy_reg)(struct e1000_hw *, u32, u16);
+ s32 (*cfg_on_link_up)(struct e1000_hw *);
};
/* Function pointers for the NVM. */
@@ -848,8 +850,8 @@ struct e1000_fc_info {
u16 pause_time; /* Flow control pause timer */
bool send_xon; /* Flow control send XON */
bool strict_ieee; /* Strict IEEE mode */
- enum e1000_fc_type type; /* Type of flow control */
- enum e1000_fc_type original_type;
+ enum e1000_fc_mode current_mode; /* FC mode in effect */
+ enum e1000_fc_mode requested_mode; /* FC mode requested by caller */
};
struct e1000_dev_spec_82571 {
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index d115a6d30f29..f2a5963b5a95 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -27,6 +27,7 @@
*******************************************************************************/
/*
+ * 82562G 10/100 Network Connection
* 82562G-2 10/100 Network Connection
* 82562GT 10/100 Network Connection
* 82562GT-2 10/100 Network Connection
@@ -40,6 +41,7 @@
* 82566MM Gigabit Network Connection
* 82567LM Gigabit Network Connection
* 82567LF Gigabit Network Connection
+ * 82567V Gigabit Network Connection
* 82567LM-2 Gigabit Network Connection
* 82567LF-2 Gigabit Network Connection
* 82567V-2 Gigabit Network Connection
@@ -92,6 +94,8 @@
#define E1000_ICH_NVM_SIG_WORD 0x13
#define E1000_ICH_NVM_SIG_MASK 0xC000
+#define E1000_ICH_NVM_VALID_SIG_MASK 0xC0
+#define E1000_ICH_NVM_SIG_VALUE 0x80
#define E1000_ICH8_LAN_INIT_TIMEOUT 1500
@@ -956,45 +960,62 @@ static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
* @bank: pointer to the variable that returns the active bank
*
* Reads signature byte from the NVM using the flash access registers.
+ * Word 0x13 bits 15:14 = 10b indicate a valid signature for that bank.
**/
static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
{
+ u32 eecd;
struct e1000_nvm_info *nvm = &hw->nvm;
- /* flash bank size is in words */
u32 bank1_offset = nvm->flash_bank_size * sizeof(u16);
u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1;
- u8 bank_high_byte = 0;
+ u8 sig_byte = 0;
+ s32 ret_val = 0;
- if (hw->mac.type != e1000_ich10lan) {
- if (er32(EECD) & E1000_EECD_SEC1VAL)
- *bank = 1;
- else
- *bank = 0;
- } else {
- /*
- * Make sure the signature for bank 0 is valid,
- * if not check for bank1
- */
- e1000_read_flash_byte_ich8lan(hw, act_offset, &bank_high_byte);
- if ((bank_high_byte & 0xC0) == 0x80) {
+ switch (hw->mac.type) {
+ case e1000_ich8lan:
+ case e1000_ich9lan:
+ eecd = er32(EECD);
+ if ((eecd & E1000_EECD_SEC1VAL_VALID_MASK) ==
+ E1000_EECD_SEC1VAL_VALID_MASK) {
+ if (eecd & E1000_EECD_SEC1VAL)
+ *bank = 1;
+ else
+ *bank = 0;
+
+ return 0;
+ }
+ hw_dbg(hw, "Unable to determine valid NVM bank via EEC - "
+ "reading flash signature\n");
+ /* fall-thru */
+ default:
+ /* set bank to 0 in case flash read fails */
+ *bank = 0;
+
+ /* Check bank 0 */
+ ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset,
+ &sig_byte);
+ if (ret_val)
+ return ret_val;
+ if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
+ E1000_ICH_NVM_SIG_VALUE) {
*bank = 0;
- } else {
- /*
- * find if segment 1 is valid by verifying
- * bit 15:14 = 10b in word 0x13
- */
- e1000_read_flash_byte_ich8lan(hw,
- act_offset + bank1_offset,
- &bank_high_byte);
+ return 0;
+ }
- /* bank1 has a valid signature equivalent to SEC1V */
- if ((bank_high_byte & 0xC0) == 0x80) {
- *bank = 1;
- } else {
- hw_dbg(hw, "ERROR: EEPROM not present\n");
- return -E1000_ERR_NVM;
- }
+ /* Check bank 1 */
+ ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset +
+ bank1_offset,
+ &sig_byte);
+ if (ret_val)
+ return ret_val;
+ if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
+ E1000_ICH_NVM_SIG_VALUE) {
+ *bank = 1;
+ return 0;
}
+
+ hw_dbg(hw, "ERROR: No valid NVM bank present\n");
+ return -E1000_ERR_NVM;
}
return 0;
@@ -1027,11 +1048,11 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
ret_val = e1000_acquire_swflag_ich8lan(hw);
if (ret_val)
- return ret_val;
+ goto out;
ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
if (ret_val)
- return ret_val;
+ goto release;
act_offset = (bank) ? nvm->flash_bank_size : 0;
act_offset += offset;
@@ -1050,8 +1071,13 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
}
}
+release:
e1000_release_swflag_ich8lan(hw);
+out:
+ if (ret_val)
+ hw_dbg(hw, "NVM read error: %d\n", ret_val);
+
return ret_val;
}
@@ -1340,14 +1366,14 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
ret_val = e1000e_update_nvm_checksum_generic(hw);
if (ret_val)
- return ret_val;
+ goto out;
if (nvm->type != e1000_nvm_flash_sw)
- return ret_val;
+ goto out;
ret_val = e1000_acquire_swflag_ich8lan(hw);
if (ret_val)
- return ret_val;
+ goto out;
/*
* We're writing to the opposite bank so if we're on bank 1,
@@ -1355,17 +1381,27 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
* is going to be written
*/
ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
- if (ret_val)
- return ret_val;
+ if (ret_val) {
+ e1000_release_swflag_ich8lan(hw);
+ goto out;
+ }
if (bank == 0) {
new_bank_offset = nvm->flash_bank_size;
old_bank_offset = 0;
- e1000_erase_flash_bank_ich8lan(hw, 1);
+ ret_val = e1000_erase_flash_bank_ich8lan(hw, 1);
+ if (ret_val) {
+ e1000_release_swflag_ich8lan(hw);
+ goto out;
+ }
} else {
old_bank_offset = nvm->flash_bank_size;
new_bank_offset = 0;
- e1000_erase_flash_bank_ich8lan(hw, 0);
+ ret_val = e1000_erase_flash_bank_ich8lan(hw, 0);
+ if (ret_val) {
+ e1000_release_swflag_ich8lan(hw);
+ goto out;
+ }
}
for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) {
@@ -1377,9 +1413,11 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
if (dev_spec->shadow_ram[i].modified) {
data = dev_spec->shadow_ram[i].value;
} else {
- e1000_read_flash_word_ich8lan(hw,
- i + old_bank_offset,
- &data);
+ ret_val = e1000_read_flash_word_ich8lan(hw, i +
+ old_bank_offset,
+ &data);
+ if (ret_val)
+ break;
}
/*
@@ -1420,7 +1458,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
/* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */
hw_dbg(hw, "Flash commit failed.\n");
e1000_release_swflag_ich8lan(hw);
- return ret_val;
+ goto out;
}
/*
@@ -1430,14 +1468,18 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
* and we need to change bit 14 to 0b
*/
act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD;
- e1000_read_flash_word_ich8lan(hw, act_offset, &data);
+ ret_val = e1000_read_flash_word_ich8lan(hw, act_offset, &data);
+ if (ret_val) {
+ e1000_release_swflag_ich8lan(hw);
+ goto out;
+ }
data &= 0xBFFF;
ret_val = e1000_retry_write_flash_byte_ich8lan(hw,
act_offset * 2 + 1,
(u8)(data >> 8));
if (ret_val) {
e1000_release_swflag_ich8lan(hw);
- return ret_val;
+ goto out;
}
/*
@@ -1450,7 +1492,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset, 0);
if (ret_val) {
e1000_release_swflag_ich8lan(hw);
- return ret_val;
+ goto out;
}
/* Great! Everything worked, we can now clear the cached entries. */
@@ -1468,6 +1510,10 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
e1000e_reload_nvm(hw);
msleep(10);
+out:
+ if (ret_val)
+ hw_dbg(hw, "NVM update error: %d\n", ret_val);
+
return ret_val;
}
@@ -1894,7 +1940,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
}
ret_val = e1000_acquire_swflag_ich8lan(hw);
/* Whether or not the swflag was acquired, we need to reset the part */
- hw_dbg(hw, "Issuing a global reset to ich8lan");
+ hw_dbg(hw, "Issuing a global reset to ich8lan\n");
ew32(CTRL, (ctrl | E1000_CTRL_RST));
msleep(20);
@@ -2074,12 +2120,17 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
* the default flow control setting, so we explicitly
* set it to full.
*/
- if (hw->fc.type == e1000_fc_default)
- hw->fc.type = e1000_fc_full;
+ if (hw->fc.requested_mode == e1000_fc_default)
+ hw->fc.requested_mode = e1000_fc_full;
- hw->fc.original_type = hw->fc.type;
+ /*
+ * Save off the requested flow control mode for use later. Depending
+ * on the link partner's capabilities, we may or may not use this mode.
+ */
+ hw->fc.current_mode = hw->fc.requested_mode;
- hw_dbg(hw, "After fix-ups FlowControl is now = %x\n", hw->fc.type);
+ hw_dbg(hw, "After fix-ups FlowControl is now = %x\n",
+ hw->fc.current_mode);
/* Continue to configure the copper link. */
ret_val = e1000_setup_copper_link_ich8lan(hw);
diff --git a/drivers/net/e1000e/lib.c b/drivers/net/e1000e/lib.c
index 089578f6855a..66741104ffd1 100644
--- a/drivers/net/e1000e/lib.c
+++ b/drivers/net/e1000e/lib.c
@@ -575,20 +575,42 @@ s32 e1000e_check_for_serdes_link(struct e1000_hw *hw)
*/
/* SYNCH bit and IV bit are sticky. */
udelay(10);
- if (E1000_RXCW_SYNCH & er32(RXCW)) {
+ rxcw = er32(RXCW);
+ if (rxcw & E1000_RXCW_SYNCH) {
if (!(rxcw & E1000_RXCW_IV)) {
- mac->serdes_has_link = 1;
- hw_dbg(hw, "SERDES: Link is up.\n");
+ mac->serdes_has_link = true;
+ hw_dbg(hw, "SERDES: Link up - forced.\n");
}
} else {
- mac->serdes_has_link = 0;
- hw_dbg(hw, "SERDES: Link is down.\n");
+ mac->serdes_has_link = false;
+ hw_dbg(hw, "SERDES: Link down - force failed.\n");
}
}
if (E1000_TXCW_ANE & er32(TXCW)) {
status = er32(STATUS);
- mac->serdes_has_link = (status & E1000_STATUS_LU);
+ if (status & E1000_STATUS_LU) {
+ /* SYNCH bit and IV bit are sticky, so reread rxcw. */
+ udelay(10);
+ rxcw = er32(RXCW);
+ if (rxcw & E1000_RXCW_SYNCH) {
+ if (!(rxcw & E1000_RXCW_IV)) {
+ mac->serdes_has_link = true;
+ hw_dbg(hw, "SERDES: Link up - autoneg "
+ "completed sucessfully.\n");
+ } else {
+ mac->serdes_has_link = false;
+ hw_dbg(hw, "SERDES: Link down - invalid"
+ "codewords detected in autoneg.\n");
+ }
+ } else {
+ mac->serdes_has_link = false;
+ hw_dbg(hw, "SERDES: Link down - no sync.\n");
+ }
+ } else {
+ mac->serdes_has_link = false;
+ hw_dbg(hw, "SERDES: Link down - autoneg failed\n");
+ }
}
return 0;
@@ -623,12 +645,12 @@ static s32 e1000_set_default_fc_generic(struct e1000_hw *hw)
}
if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == 0)
- hw->fc.type = e1000_fc_none;
+ hw->fc.requested_mode = e1000_fc_none;
else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) ==
NVM_WORD0F_ASM_DIR)
- hw->fc.type = e1000_fc_tx_pause;
+ hw->fc.requested_mode = e1000_fc_tx_pause;
else
- hw->fc.type = e1000_fc_full;
+ hw->fc.requested_mode = e1000_fc_full;
return 0;
}
@@ -656,23 +678,23 @@ s32 e1000e_setup_link(struct e1000_hw *hw)
return 0;
/*
- * If flow control is set to default, set flow control based on
- * the EEPROM flow control settings.
+ * If requested flow control is set to default, set flow control
+ * based on the EEPROM flow control settings.
*/
- if (hw->fc.type == e1000_fc_default) {
+ if (hw->fc.requested_mode == e1000_fc_default) {
ret_val = e1000_set_default_fc_generic(hw);
if (ret_val)
return ret_val;
}
/*
- * We want to save off the original Flow Control configuration just
- * in case we get disconnected and then reconnected into a different
- * hub or switch with different Flow Control capabilities.
+ * Save off the requested flow control mode for use later. Depending
+ * on the link partner's capabilities, we may or may not use this mode.
*/
- hw->fc.original_type = hw->fc.type;
+ hw->fc.current_mode = hw->fc.requested_mode;
- hw_dbg(hw, "After fix-ups FlowControl is now = %x\n", hw->fc.type);
+ hw_dbg(hw, "After fix-ups FlowControl is now = %x\n",
+ hw->fc.current_mode);
/* Call the necessary media_type subroutine to configure the link. */
ret_val = mac->ops.setup_physical_interface(hw);
@@ -724,7 +746,7 @@ static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw)
* do not support receiving pause frames).
* 3: Both Rx and Tx flow control (symmetric) are enabled.
*/
- switch (hw->fc.type) {
+ switch (hw->fc.current_mode) {
case e1000_fc_none:
/* Flow control completely disabled by a software over-ride. */
txcw = (E1000_TXCW_ANE | E1000_TXCW_FD);
@@ -906,7 +928,7 @@ s32 e1000e_set_fc_watermarks(struct e1000_hw *hw)
* ability to transmit pause frames is not enabled, then these
* registers will be set to 0.
*/
- if (hw->fc.type & e1000_fc_tx_pause) {
+ if (hw->fc.current_mode & e1000_fc_tx_pause) {
/*
* We need to set up the Receive Threshold high and low water
* marks as well as (optionally) enabling the transmission of
@@ -945,7 +967,7 @@ s32 e1000e_force_mac_fc(struct e1000_hw *hw)
* receive flow control.
*
* The "Case" statement below enables/disable flow control
- * according to the "hw->fc.type" parameter.
+ * according to the "hw->fc.current_mode" parameter.
*
* The possible values of the "fc" parameter are:
* 0: Flow control is completely disabled
@@ -956,9 +978,9 @@ s32 e1000e_force_mac_fc(struct e1000_hw *hw)
* 3: Both Rx and Tx flow control (symmetric) is enabled.
* other: No other values should be possible at this point.
*/
- hw_dbg(hw, "hw->fc.type = %u\n", hw->fc.type);
+ hw_dbg(hw, "hw->fc.current_mode = %u\n", hw->fc.current_mode);
- switch (hw->fc.type) {
+ switch (hw->fc.current_mode) {
case e1000_fc_none:
ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
break;
@@ -1102,11 +1124,11 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
* ONLY. Hence, we must now check to see if we need to
* turn OFF the TRANSMISSION of PAUSE frames.
*/
- if (hw->fc.original_type == e1000_fc_full) {
- hw->fc.type = e1000_fc_full;
+ if (hw->fc.requested_mode == e1000_fc_full) {
+ hw->fc.current_mode = e1000_fc_full;
hw_dbg(hw, "Flow Control = FULL.\r\n");
} else {
- hw->fc.type = e1000_fc_rx_pause;
+ hw->fc.current_mode = e1000_fc_rx_pause;
hw_dbg(hw, "Flow Control = "
"RX PAUSE frames only.\r\n");
}
@@ -1124,7 +1146,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
(mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
(mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
- hw->fc.type = e1000_fc_tx_pause;
+ hw->fc.current_mode = e1000_fc_tx_pause;
hw_dbg(hw, "Flow Control = Tx PAUSE frames only.\r\n");
}
/*
@@ -1140,14 +1162,14 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
(mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
!(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
(mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
- hw->fc.type = e1000_fc_rx_pause;
+ hw->fc.current_mode = e1000_fc_rx_pause;
hw_dbg(hw, "Flow Control = Rx PAUSE frames only.\r\n");
} else {
/*
* Per the IEEE spec, at this point flow control
* should be disabled.
*/
- hw->fc.type = e1000_fc_none;
+ hw->fc.current_mode = e1000_fc_none;
hw_dbg(hw, "Flow Control = NONE.\r\n");
}
@@ -1163,7 +1185,7 @@ s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw)
}
if (duplex == HALF_DUPLEX)
- hw->fc.type = e1000_fc_none;
+ hw->fc.current_mode = e1000_fc_none;
/*
* Now we call a subroutine to actually force the MAC
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 122539a0e1fe..d4639facd1bd 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -102,9 +102,7 @@ static void e1000_receive_skb(struct e1000_adapter *adapter,
vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
le16_to_cpu(vlan));
else
- netif_receive_skb(skb);
-
- netdev->last_rx = jiffies;
+ napi_gro_receive(&adapter->napi, skb);
}
/**
@@ -1181,12 +1179,12 @@ static irqreturn_t e1000_intr_msi(int irq, void *data)
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
- if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
+ if (netif_rx_schedule_prep(&adapter->napi)) {
adapter->total_tx_bytes = 0;
adapter->total_tx_packets = 0;
adapter->total_rx_bytes = 0;
adapter->total_rx_packets = 0;
- __netif_rx_schedule(netdev, &adapter->napi);
+ __netif_rx_schedule(&adapter->napi);
}
return IRQ_HANDLED;
@@ -1248,12 +1246,12 @@ static irqreturn_t e1000_intr(int irq, void *data)
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
- if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
+ if (netif_rx_schedule_prep(&adapter->napi)) {
adapter->total_tx_bytes = 0;
adapter->total_tx_packets = 0;
adapter->total_rx_bytes = 0;
adapter->total_rx_packets = 0;
- __netif_rx_schedule(netdev, &adapter->napi);
+ __netif_rx_schedule(&adapter->napi);
}
return IRQ_HANDLED;
@@ -1322,10 +1320,10 @@ static irqreturn_t e1000_intr_msix_rx(int irq, void *data)
adapter->rx_ring->set_itr = 0;
}
- if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
+ if (netif_rx_schedule_prep(&adapter->napi)) {
adapter->total_rx_bytes = 0;
adapter->total_rx_packets = 0;
- __netif_rx_schedule(netdev, &adapter->napi);
+ __netif_rx_schedule(&adapter->napi);
}
return IRQ_HANDLED;
}
@@ -1480,7 +1478,7 @@ static int e1000_request_msix(struct e1000_adapter *adapter)
int err = 0, vector = 0;
if (strlen(netdev->name) < (IFNAMSIZ - 5))
- sprintf(adapter->rx_ring->name, "%s-rx0", netdev->name);
+ sprintf(adapter->rx_ring->name, "%s-rx-0", netdev->name);
else
memcpy(adapter->rx_ring->name, netdev->name, IFNAMSIZ);
err = request_irq(adapter->msix_entries[vector].vector,
@@ -1493,7 +1491,7 @@ static int e1000_request_msix(struct e1000_adapter *adapter)
vector++;
if (strlen(netdev->name) < (IFNAMSIZ - 5))
- sprintf(adapter->tx_ring->name, "%s-tx0", netdev->name);
+ sprintf(adapter->tx_ring->name, "%s-tx-0", netdev->name);
else
memcpy(adapter->tx_ring->name, netdev->name, IFNAMSIZ);
err = request_irq(adapter->msix_entries[vector].vector,
@@ -2003,8 +2001,7 @@ static int e1000_clean(struct napi_struct *napi, int budget)
struct net_device *poll_dev = adapter->netdev;
int tx_cleaned = 0, work_done = 0;
- /* Must NOT use netdev_priv macro here. */
- adapter = poll_dev->priv;
+ adapter = netdev_priv(poll_dev);
if (adapter->msix_entries &&
!(adapter->rx_ring->ims_val & adapter->tx_ring->ims_val))
@@ -2031,7 +2028,7 @@ clean_rx:
if (work_done < budget) {
if (adapter->itr_setting & 3)
e1000_set_itr(adapter);
- netif_rx_complete(poll_dev, napi);
+ netif_rx_complete(napi);
if (adapter->msix_entries)
ew32(IMS, adapter->rx_ring->ims_val);
else
@@ -2787,7 +2784,7 @@ void e1000e_reset(struct e1000_adapter *adapter)
else
fc->pause_time = E1000_FC_PAUSE_TIME;
fc->send_xon = 1;
- fc->type = fc->original_type;
+ fc->current_mode = fc->requested_mode;
/* Allow time for pending master requests to run */
mac->ops.reset_hw(hw);
@@ -3410,7 +3407,10 @@ static void e1000_print_link_info(struct e1000_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
u32 ctrl = er32(CTRL);
- e_info("Link is Up %d Mbps %s, Flow Control: %s\n",
+ /* Link status message must follow this format for user tools */
+ printk(KERN_INFO "e1000e: %s NIC Link is Up %d Mbps %s, "
+ "Flow Control: %s\n",
+ adapter->netdev->name,
adapter->link_speed,
(adapter->link_duplex == FULL_DUPLEX) ?
"Full Duplex" : "Half Duplex",
@@ -3420,7 +3420,7 @@ static void e1000_print_link_info(struct e1000_adapter *adapter)
((ctrl & E1000_CTRL_TFCE) ? "TX" : "None" )));
}
-static bool e1000_has_link(struct e1000_adapter *adapter)
+bool e1000_has_link(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
bool link_active = 0;
@@ -3495,6 +3495,7 @@ static void e1000_watchdog_task(struct work_struct *work)
struct e1000_adapter, watchdog_task);
struct net_device *netdev = adapter->netdev;
struct e1000_mac_info *mac = &adapter->hw.mac;
+ struct e1000_phy_info *phy = &adapter->hw.phy;
struct e1000_ring *tx_ring = adapter->tx_ring;
struct e1000_hw *hw = &adapter->hw;
u32 link, tctl;
@@ -3601,6 +3602,13 @@ static void e1000_watchdog_task(struct work_struct *work)
tctl |= E1000_TCTL_EN;
ew32(TCTL, tctl);
+ /*
+ * Perform any post-link-up configuration before
+ * reporting link up.
+ */
+ if (phy->ops.cfg_on_link_up)
+ phy->ops.cfg_on_link_up(hw);
+
netif_carrier_on(netdev);
netif_tx_wake_all_queues(netdev);
@@ -3612,7 +3620,9 @@ static void e1000_watchdog_task(struct work_struct *work)
if (netif_carrier_ok(netdev)) {
adapter->link_speed = 0;
adapter->link_duplex = 0;
- e_info("Link is Down\n");
+ /* Link status message must follow this format */
+ printk(KERN_INFO "e1000e: %s NIC Link is Down\n",
+ adapter->netdev->name);
netif_carrier_off(netdev);
netif_tx_stop_all_queues(netdev);
if (!test_bit(__E1000_DOWN, &adapter->state))
@@ -4464,7 +4474,27 @@ static int e1000_suspend(struct pci_dev *pdev, pm_message_t state)
pci_disable_device(pdev);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ /*
+ * The pci-e switch on some quad port adapters will report a
+ * correctable error when the MAC transitions from D0 to D3. To
+ * prevent this we need to mask off the correctable errors on the
+ * downstream port of the pci-e switch.
+ */
+ if (adapter->flags & FLAG_IS_QUAD_PORT) {
+ struct pci_dev *us_dev = pdev->bus->self;
+ int pos = pci_find_capability(us_dev, PCI_CAP_ID_EXP);
+ u16 devctl;
+
+ pci_read_config_word(us_dev, pos + PCI_EXP_DEVCTL, &devctl);
+ pci_write_config_word(us_dev, pos + PCI_EXP_DEVCTL,
+ (devctl & ~PCI_EXP_DEVCTL_CERE));
+
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ pci_write_config_word(us_dev, pos + PCI_EXP_DEVCTL, devctl);
+ } else {
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+ }
return 0;
}
@@ -4669,14 +4699,12 @@ static void e1000_print_device_info(struct e1000_adapter *adapter)
u32 pba_num;
/* print bus type/speed/width info */
- e_info("(PCI Express:2.5GB/s:%s) %02x:%02x:%02x:%02x:%02x:%02x\n",
+ e_info("(PCI Express:2.5GB/s:%s) %pM\n",
/* bus width */
((hw->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" :
"Width x1"),
/* MAC address */
- netdev->dev_addr[0], netdev->dev_addr[1],
- netdev->dev_addr[2], netdev->dev_addr[3],
- netdev->dev_addr[4], netdev->dev_addr[5]);
+ netdev->dev_addr);
e_info("Intel(R) PRO/%s Network Connection\n",
(hw->phy.type == e1000_phy_ife) ? "10/100" : "1000");
e1000e_read_pba_num(hw, &pba_num);
@@ -4694,20 +4722,40 @@ static void e1000_eeprom_checks(struct e1000_adapter *adapter)
return;
ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &buf);
- if (!(le16_to_cpu(buf) & (1 << 0))) {
+ if (!ret_val && (!(le16_to_cpu(buf) & (1 << 0)))) {
/* Deep Smart Power Down (DSPD) */
dev_warn(&adapter->pdev->dev,
"Warning: detected DSPD enabled in EEPROM\n");
}
ret_val = e1000_read_nvm(hw, NVM_INIT_3GIO_3, 1, &buf);
- if (le16_to_cpu(buf) & (3 << 2)) {
+ if (!ret_val && (le16_to_cpu(buf) & (3 << 2))) {
/* ASPM enable */
dev_warn(&adapter->pdev->dev,
"Warning: detected ASPM enabled in EEPROM\n");
}
}
+static const struct net_device_ops e1000e_netdev_ops = {
+ .ndo_open = e1000_open,
+ .ndo_stop = e1000_close,
+ .ndo_start_xmit = e1000_xmit_frame,
+ .ndo_get_stats = e1000_get_stats,
+ .ndo_set_multicast_list = e1000_set_multi,
+ .ndo_set_mac_address = e1000_set_mac,
+ .ndo_change_mtu = e1000_change_mtu,
+ .ndo_do_ioctl = e1000_ioctl,
+ .ndo_tx_timeout = e1000_tx_timeout,
+ .ndo_validate_addr = eth_validate_addr,
+
+ .ndo_vlan_rx_register = e1000_vlan_rx_register,
+ .ndo_vlan_rx_add_vid = e1000_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = e1000_vlan_rx_kill_vid,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = e1000_netpoll,
+#endif
+};
+
/**
* e1000_probe - Device Initialization Routine
* @pdev: PCI device information struct
@@ -4766,7 +4814,10 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
goto err_pci_reg;
pci_set_master(pdev);
- pci_save_state(pdev);
+ /* PCI config space info */
+ err = pci_save_state(pdev);
+ if (err)
+ goto err_alloc_etherdev;
err = -ENOMEM;
netdev = alloc_etherdev(sizeof(struct e1000_adapter));
@@ -4806,24 +4857,10 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
}
/* construct the net_device struct */
- netdev->open = &e1000_open;
- netdev->stop = &e1000_close;
- netdev->hard_start_xmit = &e1000_xmit_frame;
- netdev->get_stats = &e1000_get_stats;
- netdev->set_multicast_list = &e1000_set_multi;
- netdev->set_mac_address = &e1000_set_mac;
- netdev->change_mtu = &e1000_change_mtu;
- netdev->do_ioctl = &e1000_ioctl;
+ netdev->netdev_ops = &e1000e_netdev_ops;
e1000e_set_ethtool_ops(netdev);
- netdev->tx_timeout = &e1000_tx_timeout;
netdev->watchdog_timeo = 5 * HZ;
netif_napi_add(netdev, &adapter->napi, e1000_clean, 64);
- netdev->vlan_rx_register = e1000_vlan_rx_register;
- netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid;
- netdev->vlan_rx_kill_vid = e1000_vlan_rx_kill_vid;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- netdev->poll_controller = e1000_netpoll;
-#endif
strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
netdev->mem_start = mmio_start;
@@ -4924,10 +4961,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
memcpy(netdev->perm_addr, adapter->hw.mac.addr, netdev->addr_len);
if (!is_valid_ether_addr(netdev->perm_addr)) {
- e_err("Invalid MAC Address: %02x:%02x:%02x:%02x:%02x:%02x\n",
- netdev->perm_addr[0], netdev->perm_addr[1],
- netdev->perm_addr[2], netdev->perm_addr[3],
- netdev->perm_addr[4], netdev->perm_addr[5]);
+ e_err("Invalid MAC Address: %pM\n", netdev->perm_addr);
err = -EIO;
goto err_eeprom;
}
@@ -4948,8 +4982,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
/* Initialize link parameters. User can change them with ethtool */
adapter->hw.mac.autoneg = 1;
adapter->fc_autoneg = 1;
- adapter->hw.fc.original_type = e1000_fc_default;
- adapter->hw.fc.type = e1000_fc_default;
+ adapter->hw.fc.requested_mode = e1000_fc_default;
+ adapter->hw.fc.current_mode = e1000_fc_default;
adapter->hw.phy.autoneg_advertised = 0x2f;
/* ring size defaults */
@@ -4990,6 +5024,9 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
adapter->wol = adapter->eeprom_wol;
device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+ /* save off EEPROM version number */
+ e1000_read_nvm(&adapter->hw, 5, 1, &adapter->eeprom_vers);
+
/* reset the hardware with the new settings */
e1000e_reset(adapter);
diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c
index 6cd333ae61d0..dc4a9cba6a73 100644
--- a/drivers/net/e1000e/phy.c
+++ b/drivers/net/e1000e/phy.c
@@ -744,7 +744,7 @@ static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
* other: No software override. The flow control configuration
* in the EEPROM is used.
*/
- switch (hw->fc.type) {
+ switch (hw->fc.current_mode) {
case e1000_fc_none:
/*
* Flow control (Rx & Tx) is completely disabled by a
@@ -1030,14 +1030,14 @@ s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw)
e1000e_phy_force_speed_duplex_setup(hw, &phy_data);
- /* Reset the phy to commit changes. */
- phy_data |= MII_CR_RESET;
-
ret_val = e1e_wphy(hw, PHY_CONTROL, phy_data);
if (ret_val)
return ret_val;
- udelay(1);
+ /* Reset the phy to commit changes. */
+ ret_val = e1000e_commit_phy(hw);
+ if (ret_val)
+ return ret_val;
if (phy->autoneg_wait_to_complete) {
hw_dbg(hw, "Waiting for forced speed/duplex link on M88 phy.\n");
@@ -1114,7 +1114,7 @@ void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl)
u32 ctrl;
/* Turn off flow control when forcing speed/duplex */
- hw->fc.type = e1000_fc_none;
+ hw->fc.current_mode = e1000_fc_none;
/* Force speed/duplex on the mac */
ctrl = er32(CTRL);
diff --git a/drivers/net/e2100.c b/drivers/net/e2100.c
index 6390f51ea6fb..20eb05cddb83 100644
--- a/drivers/net/e2100.c
+++ b/drivers/net/e2100.c
@@ -107,7 +107,7 @@ static void e21_block_output(struct net_device *dev, int count,
const unsigned char *buf, int start_page);
static void e21_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
int ring_page);
-
+static int e21_open(struct net_device *dev);
static int e21_close(struct net_device *dev);
@@ -160,6 +160,21 @@ out:
}
#endif
+static const struct net_device_ops e21_netdev_ops = {
+ .ndo_open = e21_open,
+ .ndo_stop = e21_close,
+
+ .ndo_start_xmit = ei_start_xmit,
+ .ndo_tx_timeout = ei_tx_timeout,
+ .ndo_get_stats = ei_get_stats,
+ .ndo_set_multicast_list = ei_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = ei_poll,
+#endif
+};
+
static int __init e21_probe1(struct net_device *dev, int ioaddr)
{
int i, status, retval;
@@ -265,11 +280,8 @@ static int __init e21_probe1(struct net_device *dev, int ioaddr)
ei_status.block_input = &e21_block_input;
ei_status.block_output = &e21_block_output;
ei_status.get_8390_hdr = &e21_get_8390_hdr;
- dev->open = &e21_open;
- dev->stop = &e21_close;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = ei_poll;
-#endif
+
+ dev->netdev_ops = &e21_netdev_ops;
NS8390_init(dev, 0);
retval = register_netdev(dev);
diff --git a/drivers/net/eepro.c b/drivers/net/eepro.c
index 1f11350e16cf..e187c88ae145 100644
--- a/drivers/net/eepro.c
+++ b/drivers/net/eepro.c
@@ -605,7 +605,7 @@ out:
static void __init printEEPROMInfo(struct net_device *dev)
{
- struct eepro_local *lp = (struct eepro_local *)dev->priv;
+ struct eepro_local *lp = netdev_priv(dev);
int ioaddr = dev->base_addr;
unsigned short Word;
int i,j;
@@ -690,7 +690,6 @@ static void __init eepro_print_info (struct net_device *dev)
struct eepro_local * lp = netdev_priv(dev);
int i;
const char * ifmap[] = {"AUI", "10Base2", "10BaseT"};
- DECLARE_MAC_BUF(mac);
i = inb(dev->base_addr + ID_REG);
printk(KERN_DEBUG " id: %#x ",i);
@@ -715,7 +714,7 @@ static void __init eepro_print_info (struct net_device *dev)
break;
}
- printk(" %s", print_mac(mac, dev->dev_addr));
+ printk(" %pM", dev->dev_addr);
if (net_debug > 3)
printk(KERN_DEBUG ", %dK RCV buffer",
@@ -1396,7 +1395,7 @@ set_multicast_list(struct net_device *dev)
#define eeprom_delay() { udelay(40); }
#define EE_READ_CMD (6 << 6)
-int
+static int
read_eeprom(int ioaddr, int location, struct net_device *dev)
{
int i;
@@ -1581,7 +1580,6 @@ eepro_rx(struct net_device *dev)
skb->protocol = eth_type_trans(skb,dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
}
@@ -1676,7 +1674,7 @@ eepro_transmit_interrupt(struct net_device *dev)
static int eepro_ethtool_get_settings(struct net_device *dev,
struct ethtool_cmd *cmd)
{
- struct eepro_local *lp = (struct eepro_local *)dev->priv;
+ struct eepro_local *lp = netdev_priv(dev);
cmd->supported = SUPPORTED_10baseT_Half |
SUPPORTED_10baseT_Full |
diff --git a/drivers/net/eepro100.c b/drivers/net/eepro100.c
deleted file mode 100644
index e3e26c595fa3..000000000000
--- a/drivers/net/eepro100.c
+++ /dev/null
@@ -1,2401 +0,0 @@
-/* drivers/net/eepro100.c: An Intel i82557-559 Ethernet driver for Linux. */
-/*
- Written 1996-1999 by Donald Becker.
-
- The driver also contains updates by different kernel developers
- (see incomplete list below).
- Current maintainer is Andrey V. Savochkin <saw@saw.sw.com.sg>.
- Please use this email address and linux-kernel mailing list for bug reports.
-
- This software may be used and distributed according to the terms
- of the GNU General Public License, incorporated herein by reference.
-
- This driver is for the Intel EtherExpress Pro100 (Speedo3) design.
- It should work with all i82557/558/559 boards.
-
- Version history:
- 1998 Apr - 2000 Feb Andrey V. Savochkin <saw@saw.sw.com.sg>
- Serious fixes for multicast filter list setting, TX timeout routine;
- RX ring refilling logic; other stuff
- 2000 Feb Jeff Garzik <jgarzik@pobox.com>
- Convert to new PCI driver interface
- 2000 Mar 24 Dragan Stancevic <visitor@valinux.com>
- Disabled FC and ER, to avoid lockups when when we get FCP interrupts.
- 2000 Jul 17 Goutham Rao <goutham.rao@intel.com>
- PCI DMA API fixes, adding pci_dma_sync_single calls where neccesary
- 2000 Aug 31 David Mosberger <davidm@hpl.hp.com>
- rx_align support: enables rx DMA without causing unaligned accesses.
-*/
-
-static const char * const version =
-"eepro100.c:v1.09j-t 9/29/99 Donald Becker\n"
-"eepro100.c: $Revision: 1.36 $ 2000/11/17 Modified by Andrey V. Savochkin <saw@saw.sw.com.sg> and others\n";
-
-/* A few user-configurable values that apply to all boards.
- First set is undocumented and spelled per Intel recommendations. */
-
-static int congenb /* = 0 */; /* Enable congestion control in the DP83840. */
-static int txfifo = 8; /* Tx FIFO threshold in 4 byte units, 0-15 */
-static int rxfifo = 8; /* Rx FIFO threshold, default 32 bytes. */
-/* Tx/Rx DMA burst length, 0-127, 0 == no preemption, tx==128 -> disabled. */
-static int txdmacount = 128;
-static int rxdmacount /* = 0 */;
-
-#if defined(__ia64__) || defined(__alpha__) || defined(__sparc__) || defined(__mips__) || \
- defined(__arm__)
- /* align rx buffers to 2 bytes so that IP header is aligned */
-# define rx_align(skb) skb_reserve((skb), 2)
-# define RxFD_ALIGNMENT __attribute__ ((aligned (2), packed))
-#else
-# define rx_align(skb)
-# define RxFD_ALIGNMENT
-#endif
-
-/* Set the copy breakpoint for the copy-only-tiny-buffer Rx method.
- Lower values use more memory, but are faster. */
-static int rx_copybreak = 200;
-
-/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
-static int max_interrupt_work = 20;
-
-/* Maximum number of multicast addresses to filter (vs. rx-all-multicast) */
-static int multicast_filter_limit = 64;
-
-/* 'options' is used to pass a transceiver override or full-duplex flag
- e.g. "options=16" for FD, "options=32" for 100mbps-only. */
-static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-
-/* A few values that may be tweaked. */
-/* The ring sizes should be a power of two for efficiency. */
-#define TX_RING_SIZE 64
-#define RX_RING_SIZE 64
-/* How much slots multicast filter setup may take.
- Do not descrease without changing set_rx_mode() implementaion. */
-#define TX_MULTICAST_SIZE 2
-#define TX_MULTICAST_RESERV (TX_MULTICAST_SIZE*2)
-/* Actual number of TX packets queued, must be
- <= TX_RING_SIZE-TX_MULTICAST_RESERV. */
-#define TX_QUEUE_LIMIT (TX_RING_SIZE-TX_MULTICAST_RESERV)
-/* Hysteresis marking queue as no longer full. */
-#define TX_QUEUE_UNFULL (TX_QUEUE_LIMIT-4)
-
-/* Operational parameters that usually are not changed. */
-
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT (2*HZ)
-/* Size of an pre-allocated Rx buffer: <Ethernet MTU> + slack.*/
-#define PKT_BUF_SZ 1536
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/pci.h>
-#include <linux/spinlock.h>
-#include <linux/init.h>
-#include <linux/mii.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/irq.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/rtnetlink.h>
-#include <linux/skbuff.h>
-#include <linux/ethtool.h>
-
-static int use_io;
-static int debug = -1;
-#define DEBUG_DEFAULT (NETIF_MSG_DRV | \
- NETIF_MSG_HW | \
- NETIF_MSG_RX_ERR | \
- NETIF_MSG_TX_ERR)
-#define DEBUG ((debug >= 0) ? (1<<debug)-1 : DEBUG_DEFAULT)
-
-
-MODULE_AUTHOR("Maintainer: Andrey V. Savochkin <saw@saw.sw.com.sg>");
-MODULE_DESCRIPTION("Intel i82557/i82558/i82559 PCI EtherExpressPro driver");
-MODULE_LICENSE("GPL");
-module_param(use_io, int, 0);
-module_param(debug, int, 0);
-module_param_array(options, int, NULL, 0);
-module_param_array(full_duplex, int, NULL, 0);
-module_param(congenb, int, 0);
-module_param(txfifo, int, 0);
-module_param(rxfifo, int, 0);
-module_param(txdmacount, int, 0);
-module_param(rxdmacount, int, 0);
-module_param(rx_copybreak, int, 0);
-module_param(max_interrupt_work, int, 0);
-module_param(multicast_filter_limit, int, 0);
-MODULE_PARM_DESC(debug, "debug level (0-6)");
-MODULE_PARM_DESC(options, "Bits 0-3: transceiver type, bit 4: full duplex, bit 5: 100Mbps");
-MODULE_PARM_DESC(full_duplex, "full duplex setting(s) (1)");
-MODULE_PARM_DESC(congenb, "Enable congestion control (1)");
-MODULE_PARM_DESC(txfifo, "Tx FIFO threshold in 4 byte units, (0-15)");
-MODULE_PARM_DESC(rxfifo, "Rx FIFO threshold in 4 byte units, (0-15)");
-MODULE_PARM_DESC(txdmacount, "Tx DMA burst length; 128 - disable (0-128)");
-MODULE_PARM_DESC(rxdmacount, "Rx DMA burst length; 128 - disable (0-128)");
-MODULE_PARM_DESC(rx_copybreak, "copy breakpoint for copy-only-tiny-frames");
-MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt");
-MODULE_PARM_DESC(multicast_filter_limit, "maximum number of filtered multicast addresses");
-
-#define RUN_AT(x) (jiffies + (x))
-
-#define netdevice_start(dev)
-#define netdevice_stop(dev)
-#define netif_set_tx_timeout(dev, tf, tm) \
- do { \
- (dev)->tx_timeout = (tf); \
- (dev)->watchdog_timeo = (tm); \
- } while(0)
-
-
-
-/*
- Theory of Operation
-
-I. Board Compatibility
-
-This device driver is designed for the Intel i82557 "Speedo3" chip, Intel's
-single-chip fast Ethernet controller for PCI, as used on the Intel
-EtherExpress Pro 100 adapter.
-
-II. Board-specific settings
-
-PCI bus devices are configured by the system at boot time, so no jumpers
-need to be set on the board. The system BIOS should be set to assign the
-PCI INTA signal to an otherwise unused system IRQ line. While it's
-possible to share PCI interrupt lines, it negatively impacts performance and
-only recent kernels support it.
-
-III. Driver operation
-
-IIIA. General
-The Speedo3 is very similar to other Intel network chips, that is to say
-"apparently designed on a different planet". This chips retains the complex
-Rx and Tx descriptors and multiple buffers pointers as previous chips, but
-also has simplified Tx and Rx buffer modes. This driver uses the "flexible"
-Tx mode, but in a simplified lower-overhead manner: it associates only a
-single buffer descriptor with each frame descriptor.
-
-Despite the extra space overhead in each receive skbuff, the driver must use
-the simplified Rx buffer mode to assure that only a single data buffer is
-associated with each RxFD. The driver implements this by reserving space
-for the Rx descriptor at the head of each Rx skbuff.
-
-The Speedo-3 has receive and command unit base addresses that are added to
-almost all descriptor pointers. The driver sets these to zero, so that all
-pointer fields are absolute addresses.
-
-The System Control Block (SCB) of some previous Intel chips exists on the
-chip in both PCI I/O and memory space. This driver uses the I/O space
-registers, but might switch to memory mapped mode to better support non-x86
-processors.
-
-IIIB. Transmit structure
-
-The driver must use the complex Tx command+descriptor mode in order to
-have a indirect pointer to the skbuff data section. Each Tx command block
-(TxCB) is associated with two immediately appended Tx Buffer Descriptor
-(TxBD). A fixed ring of these TxCB+TxBD pairs are kept as part of the
-speedo_private data structure for each adapter instance.
-
-The newer i82558 explicitly supports this structure, and can read the two
-TxBDs in the same PCI burst as the TxCB.
-
-This ring structure is used for all normal transmit packets, but the
-transmit packet descriptors aren't long enough for most non-Tx commands such
-as CmdConfigure. This is complicated by the possibility that the chip has
-already loaded the link address in the previous descriptor. So for these
-commands we convert the next free descriptor on the ring to a NoOp, and point
-that descriptor's link to the complex command.
-
-An additional complexity of these non-transmit commands are that they may be
-added asynchronous to the normal transmit queue, so we disable interrupts
-whenever the Tx descriptor ring is manipulated.
-
-A notable aspect of these special configure commands is that they do
-work with the normal Tx ring entry scavenge method. The Tx ring scavenge
-is done at interrupt time using the 'dirty_tx' index, and checking for the
-command-complete bit. While the setup frames may have the NoOp command on the
-Tx ring marked as complete, but not have completed the setup command, this
-is not a problem. The tx_ring entry can be still safely reused, as the
-tx_skbuff[] entry is always empty for config_cmd and mc_setup frames.
-
-Commands may have bits set e.g. CmdSuspend in the command word to either
-suspend or stop the transmit/command unit. This driver always flags the last
-command with CmdSuspend, erases the CmdSuspend in the previous command, and
-then issues a CU_RESUME.
-Note: Watch out for the potential race condition here: imagine
- erasing the previous suspend
- the chip processes the previous command
- the chip processes the final command, and suspends
- doing the CU_RESUME
- the chip processes the next-yet-valid post-final-command.
-So blindly sending a CU_RESUME is only safe if we do it immediately after
-after erasing the previous CmdSuspend, without the possibility of an
-intervening delay. Thus the resume command is always within the
-interrupts-disabled region. This is a timing dependence, but handling this
-condition in a timing-independent way would considerably complicate the code.
-
-Note: In previous generation Intel chips, restarting the command unit was a
-notoriously slow process. This is presumably no longer true.
-
-IIIC. Receive structure
-
-Because of the bus-master support on the Speedo3 this driver uses the new
-SKBUFF_RX_COPYBREAK scheme, rather than a fixed intermediate receive buffer.
-This scheme allocates full-sized skbuffs as receive buffers. The value
-SKBUFF_RX_COPYBREAK is used as the copying breakpoint: it is chosen to
-trade-off the memory wasted by passing the full-sized skbuff to the queue
-layer for all frames vs. the copying cost of copying a frame to a
-correctly-sized skbuff.
-
-For small frames the copying cost is negligible (esp. considering that we
-are pre-loading the cache with immediately useful header information), so we
-allocate a new, minimally-sized skbuff. For large frames the copying cost
-is non-trivial, and the larger copy might flush the cache of useful data, so
-we pass up the skbuff the packet was received into.
-
-IV. Notes
-
-Thanks to Steve Williams of Intel for arranging the non-disclosure agreement
-that stated that I could disclose the information. But I still resent
-having to sign an Intel NDA when I'm helping Intel sell their own product!
-
-*/
-
-static int speedo_found1(struct pci_dev *pdev, void __iomem *ioaddr, int fnd_cnt, int acpi_idle_state);
-
-/* Offsets to the various registers.
- All accesses need not be longword aligned. */
-enum speedo_offsets {
- SCBStatus = 0, SCBCmd = 2, /* Rx/Command Unit command and status. */
- SCBIntmask = 3,
- SCBPointer = 4, /* General purpose pointer. */
- SCBPort = 8, /* Misc. commands and operands. */
- SCBflash = 12, SCBeeprom = 14, /* EEPROM and flash memory control. */
- SCBCtrlMDI = 16, /* MDI interface control. */
- SCBEarlyRx = 20, /* Early receive byte count. */
-};
-/* Commands that can be put in a command list entry. */
-enum commands {
- CmdNOp = 0, CmdIASetup = 0x10000, CmdConfigure = 0x20000,
- CmdMulticastList = 0x30000, CmdTx = 0x40000, CmdTDR = 0x50000,
- CmdDump = 0x60000, CmdDiagnose = 0x70000,
- CmdSuspend = 0x40000000, /* Suspend after completion. */
- CmdIntr = 0x20000000, /* Interrupt after completion. */
- CmdTxFlex = 0x00080000, /* Use "Flexible mode" for CmdTx command. */
-};
-/* Clear CmdSuspend (1<<30) avoiding interference with the card access to the
- status bits. Previous driver versions used separate 16 bit fields for
- commands and statuses. --SAW
- */
-#if defined(__alpha__)
-# define clear_suspend(cmd) clear_bit(30, &(cmd)->cmd_status);
-#else
-# define clear_suspend(cmd) ((__le16 *)&(cmd)->cmd_status)[1] &= ~cpu_to_le16(1<<14)
-#endif
-
-enum SCBCmdBits {
- SCBMaskCmdDone=0x8000, SCBMaskRxDone=0x4000, SCBMaskCmdIdle=0x2000,
- SCBMaskRxSuspend=0x1000, SCBMaskEarlyRx=0x0800, SCBMaskFlowCtl=0x0400,
- SCBTriggerIntr=0x0200, SCBMaskAll=0x0100,
- /* The rest are Rx and Tx commands. */
- CUStart=0x0010, CUResume=0x0020, CUStatsAddr=0x0040, CUShowStats=0x0050,
- CUCmdBase=0x0060, /* CU Base address (set to zero) . */
- CUDumpStats=0x0070, /* Dump then reset stats counters. */
- RxStart=0x0001, RxResume=0x0002, RxAbort=0x0004, RxAddrLoad=0x0006,
- RxResumeNoResources=0x0007,
-};
-
-enum SCBPort_cmds {
- PortReset=0, PortSelfTest=1, PortPartialReset=2, PortDump=3,
-};
-
-/* The Speedo3 Rx and Tx frame/buffer descriptors. */
-struct descriptor { /* A generic descriptor. */
- volatile __le32 cmd_status; /* All command and status fields. */
- __le32 link; /* struct descriptor * */
- unsigned char params[0];
-};
-
-/* The Speedo3 Rx and Tx buffer descriptors. */
-struct RxFD { /* Receive frame descriptor. */
- volatile __le32 status;
- __le32 link; /* struct RxFD * */
- __le32 rx_buf_addr; /* void * */
- __le32 count;
-} RxFD_ALIGNMENT;
-
-/* Selected elements of the Tx/RxFD.status word. */
-enum RxFD_bits {
- RxComplete=0x8000, RxOK=0x2000,
- RxErrCRC=0x0800, RxErrAlign=0x0400, RxErrTooBig=0x0200, RxErrSymbol=0x0010,
- RxEth2Type=0x0020, RxNoMatch=0x0004, RxNoIAMatch=0x0002,
- TxUnderrun=0x1000, StatusComplete=0x8000,
-};
-
-#define CONFIG_DATA_SIZE 22
-struct TxFD { /* Transmit frame descriptor set. */
- __le32 status;
- __le32 link; /* void * */
- __le32 tx_desc_addr; /* Always points to the tx_buf_addr element. */
- __le32 count; /* # of TBD (=1), Tx start thresh., etc. */
- /* This constitutes two "TBD" entries -- we only use one. */
-#define TX_DESCR_BUF_OFFSET 16
- __le32 tx_buf_addr0; /* void *, frame to be transmitted. */
- __le32 tx_buf_size0; /* Length of Tx frame. */
- __le32 tx_buf_addr1; /* void *, frame to be transmitted. */
- __le32 tx_buf_size1; /* Length of Tx frame. */
- /* the structure must have space for at least CONFIG_DATA_SIZE starting
- * from tx_desc_addr field */
-};
-
-/* Multicast filter setting block. --SAW */
-struct speedo_mc_block {
- struct speedo_mc_block *next;
- unsigned int tx;
- dma_addr_t frame_dma;
- unsigned int len;
- struct descriptor frame __attribute__ ((__aligned__(16)));
-};
-
-/* Elements of the dump_statistics block. This block must be lword aligned. */
-struct speedo_stats {
- __le32 tx_good_frames;
- __le32 tx_coll16_errs;
- __le32 tx_late_colls;
- __le32 tx_underruns;
- __le32 tx_lost_carrier;
- __le32 tx_deferred;
- __le32 tx_one_colls;
- __le32 tx_multi_colls;
- __le32 tx_total_colls;
- __le32 rx_good_frames;
- __le32 rx_crc_errs;
- __le32 rx_align_errs;
- __le32 rx_resource_errs;
- __le32 rx_overrun_errs;
- __le32 rx_colls_errs;
- __le32 rx_runt_errs;
- __le32 done_marker;
-};
-
-enum Rx_ring_state_bits {
- RrNoMem=1, RrPostponed=2, RrNoResources=4, RrOOMReported=8,
-};
-
-/* Do not change the position (alignment) of the first few elements!
- The later elements are grouped for cache locality.
-
- Unfortunately, all the positions have been shifted since there.
- A new re-alignment is required. 2000/03/06 SAW */
-struct speedo_private {
- void __iomem *regs;
- struct TxFD *tx_ring; /* Commands (usually CmdTxPacket). */
- struct RxFD *rx_ringp[RX_RING_SIZE]; /* Rx descriptor, used as ring. */
- /* The addresses of a Tx/Rx-in-place packets/buffers. */
- struct sk_buff *tx_skbuff[TX_RING_SIZE];
- struct sk_buff *rx_skbuff[RX_RING_SIZE];
- /* Mapped addresses of the rings. */
- dma_addr_t tx_ring_dma;
-#define TX_RING_ELEM_DMA(sp, n) ((sp)->tx_ring_dma + (n)*sizeof(struct TxFD))
- dma_addr_t rx_ring_dma[RX_RING_SIZE];
- struct descriptor *last_cmd; /* Last command sent. */
- unsigned int cur_tx, dirty_tx; /* The ring entries to be free()ed. */
- spinlock_t lock; /* Group with Tx control cache line. */
- u32 tx_threshold; /* The value for txdesc.count. */
- struct RxFD *last_rxf; /* Last filled RX buffer. */
- dma_addr_t last_rxf_dma;
- unsigned int cur_rx, dirty_rx; /* The next free ring entry */
- long last_rx_time; /* Last Rx, in jiffies, to handle Rx hang. */
- struct net_device_stats stats;
- struct speedo_stats *lstats;
- dma_addr_t lstats_dma;
- int chip_id;
- struct pci_dev *pdev;
- struct timer_list timer; /* Media selection timer. */
- struct speedo_mc_block *mc_setup_head; /* Multicast setup frame list head. */
- struct speedo_mc_block *mc_setup_tail; /* Multicast setup frame list tail. */
- long in_interrupt; /* Word-aligned dev->interrupt */
- unsigned char acpi_pwr;
- signed char rx_mode; /* Current PROMISC/ALLMULTI setting. */
- unsigned int tx_full:1; /* The Tx queue is full. */
- unsigned int flow_ctrl:1; /* Use 802.3x flow control. */
- unsigned int rx_bug:1; /* Work around receiver hang errata. */
- unsigned char default_port:8; /* Last dev->if_port value. */
- unsigned char rx_ring_state; /* RX ring status flags. */
- unsigned short phy[2]; /* PHY media interfaces available. */
- unsigned short partner; /* Link partner caps. */
- struct mii_if_info mii_if; /* MII API hooks, info */
- u32 msg_enable; /* debug message level */
-};
-
-/* The parameters for a CmdConfigure operation.
- There are so many options that it would be difficult to document each bit.
- We mostly use the default or recommended settings. */
-static const char i82557_config_cmd[CONFIG_DATA_SIZE] = {
- 22, 0x08, 0, 0, 0, 0, 0x32, 0x03, 1, /* 1=Use MII 0=Use AUI */
- 0, 0x2E, 0, 0x60, 0,
- 0xf2, 0x48, 0, 0x40, 0xf2, 0x80, /* 0x40=Force full-duplex */
- 0x3f, 0x05, };
-static const char i82558_config_cmd[CONFIG_DATA_SIZE] = {
- 22, 0x08, 0, 1, 0, 0, 0x22, 0x03, 1, /* 1=Use MII 0=Use AUI */
- 0, 0x2E, 0, 0x60, 0x08, 0x88,
- 0x68, 0, 0x40, 0xf2, 0x84, /* Disable FC */
- 0x31, 0x05, };
-
-/* PHY media interface chips. */
-static const char * const phys[] = {
- "None", "i82553-A/B", "i82553-C", "i82503",
- "DP83840", "80c240", "80c24", "i82555",
- "unknown-8", "unknown-9", "DP83840A", "unknown-11",
- "unknown-12", "unknown-13", "unknown-14", "unknown-15", };
-enum phy_chips { NonSuchPhy=0, I82553AB, I82553C, I82503, DP83840, S80C240,
- S80C24, I82555, DP83840A=10, };
-static const char is_mii[] = { 0, 1, 1, 0, 1, 1, 0, 1 };
-#define EE_READ_CMD (6)
-
-static int eepro100_init_one(struct pci_dev *pdev,
- const struct pci_device_id *ent);
-
-static int do_eeprom_cmd(void __iomem *ioaddr, int cmd, int cmd_len);
-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 location, int value);
-static int speedo_open(struct net_device *dev);
-static void speedo_resume(struct net_device *dev);
-static void speedo_timer(unsigned long data);
-static void speedo_init_rx_ring(struct net_device *dev);
-static void speedo_tx_timeout(struct net_device *dev);
-static int speedo_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static void speedo_refill_rx_buffers(struct net_device *dev, int force);
-static int speedo_rx(struct net_device *dev);
-static void speedo_tx_buffer_gc(struct net_device *dev);
-static irqreturn_t speedo_interrupt(int irq, void *dev_instance);
-static int speedo_close(struct net_device *dev);
-static struct net_device_stats *speedo_get_stats(struct net_device *dev);
-static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static void set_rx_mode(struct net_device *dev);
-static void speedo_show_state(struct net_device *dev);
-static const struct ethtool_ops ethtool_ops;
-
-
-
-#ifdef honor_default_port
-/* Optional driver feature to allow forcing the transceiver setting.
- Not recommended. */
-static int mii_ctrl[8] = { 0x3300, 0x3100, 0x0000, 0x0100,
- 0x2000, 0x2100, 0x0400, 0x3100};
-#endif
-
-/* How to wait for the command unit to accept a command.
- Typically this takes 0 ticks. */
-static inline unsigned char wait_for_cmd_done(struct net_device *dev,
- struct speedo_private *sp)
-{
- int wait = 1000;
- void __iomem *cmd_ioaddr = sp->regs + SCBCmd;
- unsigned char r;
-
- do {
- udelay(1);
- r = ioread8(cmd_ioaddr);
- } while(r && --wait >= 0);
-
- if (wait < 0)
- printk(KERN_ALERT "%s: wait_for_cmd_done timeout!\n", dev->name);
- return r;
-}
-
-static int __devinit eepro100_init_one (struct pci_dev *pdev,
- const struct pci_device_id *ent)
-{
- void __iomem *ioaddr;
- int irq, pci_bar;
- int acpi_idle_state = 0, pm;
- static int cards_found /* = 0 */;
- unsigned long pci_base;
-
-#ifndef MODULE
- /* when built-in, we only print version if device is found */
- static int did_version;
- if (did_version++ == 0)
- printk(version);
-#endif
-
- /* save power state before pci_enable_device overwrites it */
- pm = pci_find_capability(pdev, PCI_CAP_ID_PM);
- if (pm) {
- u16 pwr_command;
- pci_read_config_word(pdev, pm + PCI_PM_CTRL, &pwr_command);
- acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
- }
-
- if (pci_enable_device(pdev))
- goto err_out_free_mmio_region;
-
- pci_set_master(pdev);
-
- if (!request_region(pci_resource_start(pdev, 1),
- pci_resource_len(pdev, 1), "eepro100")) {
- dev_err(&pdev->dev, "eepro100: cannot reserve I/O ports\n");
- goto err_out_none;
- }
- if (!request_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0), "eepro100")) {
- dev_err(&pdev->dev, "eepro100: cannot reserve MMIO region\n");
- goto err_out_free_pio_region;
- }
-
- irq = pdev->irq;
- pci_bar = use_io ? 1 : 0;
- pci_base = pci_resource_start(pdev, pci_bar);
- if (DEBUG & NETIF_MSG_PROBE)
- printk("Found Intel i82557 PCI Speedo at %#lx, IRQ %d.\n",
- pci_base, irq);
-
- ioaddr = pci_iomap(pdev, pci_bar, 0);
- if (!ioaddr) {
- dev_err(&pdev->dev, "eepro100: cannot remap IO\n");
- goto err_out_free_mmio_region;
- }
-
- if (speedo_found1(pdev, ioaddr, cards_found, acpi_idle_state) == 0)
- cards_found++;
- else
- goto err_out_iounmap;
-
- return 0;
-
-err_out_iounmap: ;
- pci_iounmap(pdev, ioaddr);
-err_out_free_mmio_region:
- release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
-err_out_free_pio_region:
- release_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));
-err_out_none:
- return -ENODEV;
-}
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/*
- * Polling 'interrupt' - used by things like netconsole to send skbs
- * without having to re-enable interrupts. It's not called while
- * the interrupt routine is executing.
- */
-
-static void poll_speedo (struct net_device *dev)
-{
- /* disable_irq is not very nice, but with the funny lockless design
- we have no other choice. */
- disable_irq(dev->irq);
- speedo_interrupt (dev->irq, dev);
- enable_irq(dev->irq);
-}
-#endif
-
-static int __devinit speedo_found1(struct pci_dev *pdev,
- void __iomem *ioaddr, int card_idx, int acpi_idle_state)
-{
- struct net_device *dev;
- struct speedo_private *sp;
- const char *product;
- int i, option;
- u16 eeprom[0x100];
- int size;
- void *tx_ring_space;
- dma_addr_t tx_ring_dma;
- DECLARE_MAC_BUF(mac);
-
- size = TX_RING_SIZE * sizeof(struct TxFD) + sizeof(struct speedo_stats);
- tx_ring_space = pci_alloc_consistent(pdev, size, &tx_ring_dma);
- if (tx_ring_space == NULL)
- return -1;
-
- dev = alloc_etherdev(sizeof(struct speedo_private));
- if (dev == NULL) {
- printk(KERN_ERR "eepro100: Could not allocate ethernet device.\n");
- pci_free_consistent(pdev, size, tx_ring_space, tx_ring_dma);
- return -1;
- }
-
- SET_NETDEV_DEV(dev, &pdev->dev);
-
- if (dev->mem_start > 0)
- option = dev->mem_start;
- else if (card_idx >= 0 && options[card_idx] >= 0)
- option = options[card_idx];
- else
- option = 0;
-
- rtnl_lock();
- if (dev_alloc_name(dev, dev->name) < 0)
- goto err_free_unlock;
-
- /* Read the station address EEPROM before doing the reset.
- Nominally his should even be done before accepting the device, but
- then we wouldn't have a device name with which to report the error.
- The size test is for 6 bit vs. 8 bit address serial EEPROMs.
- */
- {
- void __iomem *iobase;
- int read_cmd, ee_size;
- u16 sum;
- int j;
-
- /* Use IO only to avoid postponed writes and satisfy EEPROM timing
- requirements. */
- iobase = pci_iomap(pdev, 1, pci_resource_len(pdev, 1));
- if (!iobase)
- goto err_free_unlock;
- if ((do_eeprom_cmd(iobase, EE_READ_CMD << 24, 27) & 0xffe0000)
- == 0xffe0000) {
- ee_size = 0x100;
- read_cmd = EE_READ_CMD << 24;
- } else {
- ee_size = 0x40;
- read_cmd = EE_READ_CMD << 22;
- }
-
- for (j = 0, i = 0, sum = 0; i < ee_size; i++) {
- u16 value = do_eeprom_cmd(iobase, read_cmd | (i << 16), 27);
- eeprom[i] = value;
- sum += value;
- if (i < 3) {
- dev->dev_addr[j++] = value;
- dev->dev_addr[j++] = value >> 8;
- }
- }
- if (sum != 0xBABA)
- printk(KERN_WARNING "%s: Invalid EEPROM checksum %#4.4x, "
- "check settings before activating this device!\n",
- dev->name, sum);
- /* Don't unregister_netdev(dev); as the EEPro may actually be
- usable, especially if the MAC address is set later.
- On the other hand, it may be unusable if MDI data is corrupted. */
-
- pci_iounmap(pdev, iobase);
- }
-
- /* Reset the chip: stop Tx and Rx processes and clear counters.
- This takes less than 10usec and will easily finish before the next
- action. */
- iowrite32(PortReset, ioaddr + SCBPort);
- ioread32(ioaddr + SCBPort);
- udelay(10);
-
- if (eeprom[3] & 0x0100)
- product = "OEM i82557/i82558 10/100 Ethernet";
- else
- product = pci_name(pdev);
-
- printk(KERN_INFO "%s: %s, %s, IRQ %d.\n", dev->name, product,
- print_mac(mac, dev->dev_addr), pdev->irq);
-
- sp = netdev_priv(dev);
-
- /* we must initialize this early, for mdio_{read,write} */
- sp->regs = ioaddr;
-
-#if 1 || defined(kernel_bloat)
- /* OK, this is pure kernel bloat. I don't like it when other drivers
- waste non-pageable kernel space to emit similar messages, but I need
- them for bug reports. */
- {
- const char *connectors[] = {" RJ45", " BNC", " AUI", " MII"};
- /* The self-test results must be paragraph aligned. */
- volatile s32 *self_test_results;
- int boguscnt = 16000; /* Timeout for set-test. */
- if ((eeprom[3] & 0x03) != 0x03)
- printk(KERN_INFO " Receiver lock-up bug exists -- enabling"
- " work-around.\n");
- printk(KERN_INFO " Board assembly %4.4x%2.2x-%3.3d, Physical"
- " connectors present:",
- eeprom[8], eeprom[9]>>8, eeprom[9] & 0xff);
- for (i = 0; i < 4; i++)
- if (eeprom[5] & (1<<i))
- printk(connectors[i]);
- printk("\n"KERN_INFO" Primary interface chip %s PHY #%d.\n",
- phys[(eeprom[6]>>8)&15], eeprom[6] & 0x1f);
- if (eeprom[7] & 0x0700)
- printk(KERN_INFO " Secondary interface chip %s.\n",
- phys[(eeprom[7]>>8)&7]);
- if (((eeprom[6]>>8) & 0x3f) == DP83840
- || ((eeprom[6]>>8) & 0x3f) == DP83840A) {
- int mdi_reg23 = mdio_read(dev, eeprom[6] & 0x1f, 23) | 0x0422;
- if (congenb)
- mdi_reg23 |= 0x0100;
- printk(KERN_INFO" DP83840 specific setup, setting register 23 to %4.4x.\n",
- mdi_reg23);
- mdio_write(dev, eeprom[6] & 0x1f, 23, mdi_reg23);
- }
- if ((option >= 0) && (option & 0x70)) {
- printk(KERN_INFO " Forcing %dMbs %s-duplex operation.\n",
- (option & 0x20 ? 100 : 10),
- (option & 0x10 ? "full" : "half"));
- mdio_write(dev, eeprom[6] & 0x1f, MII_BMCR,
- ((option & 0x20) ? 0x2000 : 0) | /* 100mbps? */
- ((option & 0x10) ? 0x0100 : 0)); /* Full duplex? */
- }
-
- /* Perform a system self-test. */
- self_test_results = (s32*) ((((long) tx_ring_space) + 15) & ~0xf);
- self_test_results[0] = 0;
- self_test_results[1] = -1;
- iowrite32(tx_ring_dma | PortSelfTest, ioaddr + SCBPort);
- do {
- udelay(10);
- } while (self_test_results[1] == -1 && --boguscnt >= 0);
-
- if (boguscnt < 0) { /* Test optimized out. */
- printk(KERN_ERR "Self test failed, status %8.8x:\n"
- KERN_ERR " Failure to initialize the i82557.\n"
- KERN_ERR " Verify that the card is a bus-master"
- " capable slot.\n",
- self_test_results[1]);
- } else
- printk(KERN_INFO " General self-test: %s.\n"
- KERN_INFO " Serial sub-system self-test: %s.\n"
- KERN_INFO " Internal registers self-test: %s.\n"
- KERN_INFO " ROM checksum self-test: %s (%#8.8x).\n",
- self_test_results[1] & 0x1000 ? "failed" : "passed",
- self_test_results[1] & 0x0020 ? "failed" : "passed",
- self_test_results[1] & 0x0008 ? "failed" : "passed",
- self_test_results[1] & 0x0004 ? "failed" : "passed",
- self_test_results[0]);
- }
-#endif /* kernel_bloat */
-
- iowrite32(PortReset, ioaddr + SCBPort);
- ioread32(ioaddr + SCBPort);
- udelay(10);
-
- /* Return the chip to its original power state. */
- pci_set_power_state(pdev, acpi_idle_state);
-
- pci_set_drvdata (pdev, dev);
- SET_NETDEV_DEV(dev, &pdev->dev);
-
- dev->irq = pdev->irq;
-
- sp->pdev = pdev;
- sp->msg_enable = DEBUG;
- sp->acpi_pwr = acpi_idle_state;
- sp->tx_ring = tx_ring_space;
- sp->tx_ring_dma = tx_ring_dma;
- sp->lstats = (struct speedo_stats *)(sp->tx_ring + TX_RING_SIZE);
- sp->lstats_dma = TX_RING_ELEM_DMA(sp, TX_RING_SIZE);
- init_timer(&sp->timer); /* used in ioctl() */
- spin_lock_init(&sp->lock);
-
- sp->mii_if.full_duplex = option >= 0 && (option & 0x10) ? 1 : 0;
- if (card_idx >= 0) {
- if (full_duplex[card_idx] >= 0)
- sp->mii_if.full_duplex = full_duplex[card_idx];
- }
- sp->default_port = option >= 0 ? (option & 0x0f) : 0;
-
- sp->phy[0] = eeprom[6];
- sp->phy[1] = eeprom[7];
-
- sp->mii_if.phy_id = eeprom[6] & 0x1f;
- sp->mii_if.phy_id_mask = 0x1f;
- sp->mii_if.reg_num_mask = 0x1f;
- sp->mii_if.dev = dev;
- sp->mii_if.mdio_read = mdio_read;
- sp->mii_if.mdio_write = mdio_write;
-
- sp->rx_bug = (eeprom[3] & 0x03) == 3 ? 0 : 1;
- if (((pdev->device > 0x1030 && (pdev->device < 0x103F)))
- || (pdev->device == 0x2449) || (pdev->device == 0x2459)
- || (pdev->device == 0x245D)) {
- sp->chip_id = 1;
- }
-
- if (sp->rx_bug)
- printk(KERN_INFO " Receiver lock-up workaround activated.\n");
-
- /* The Speedo-specific entries in the device structure. */
- dev->open = &speedo_open;
- dev->hard_start_xmit = &speedo_start_xmit;
- netif_set_tx_timeout(dev, &speedo_tx_timeout, TX_TIMEOUT);
- dev->stop = &speedo_close;
- dev->get_stats = &speedo_get_stats;
- dev->set_multicast_list = &set_rx_mode;
- dev->do_ioctl = &speedo_ioctl;
- SET_ETHTOOL_OPS(dev, &ethtool_ops);
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = &poll_speedo;
-#endif
-
- if (register_netdevice(dev))
- goto err_free_unlock;
- rtnl_unlock();
-
- return 0;
-
- err_free_unlock:
- rtnl_unlock();
- free_netdev(dev);
- return -1;
-}
-
-static void do_slow_command(struct net_device *dev, struct speedo_private *sp, int cmd)
-{
- void __iomem *cmd_ioaddr = sp->regs + SCBCmd;
- int wait = 0;
- do
- if (ioread8(cmd_ioaddr) == 0) break;
- while(++wait <= 200);
- if (wait > 100)
- printk(KERN_ERR "Command %4.4x never accepted (%d polls)!\n",
- ioread8(cmd_ioaddr), wait);
-
- iowrite8(cmd, cmd_ioaddr);
-
- for (wait = 0; wait <= 100; wait++)
- if (ioread8(cmd_ioaddr) == 0) return;
- for (; wait <= 20000; wait++)
- if (ioread8(cmd_ioaddr) == 0) return;
- else udelay(1);
- printk(KERN_ERR "Command %4.4x was not accepted after %d polls!"
- " Current status %8.8x.\n",
- cmd, wait, ioread32(sp->regs + SCBStatus));
-}
-
-/* Serial EEPROM section.
- A "bit" grungy, but we work our way through bit-by-bit :->. */
-/* EEPROM_Ctrl bits. */
-#define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */
-#define EE_CS 0x02 /* EEPROM chip select. */
-#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */
-#define EE_DATA_READ 0x08 /* EEPROM chip data out. */
-#define EE_ENB (0x4800 | EE_CS)
-#define EE_WRITE_0 0x4802
-#define EE_WRITE_1 0x4806
-#define EE_OFFSET SCBeeprom
-
-/* The fixes for the code were kindly provided by Dragan Stancevic
- <visitor@valinux.com> to strictly follow Intel specifications of EEPROM
- access timing.
- The publicly available sheet 64486302 (sec. 3.1) specifies 1us access
- interval for serial EEPROM. However, it looks like that there is an
- additional requirement dictating larger udelay's in the code below.
- 2000/05/24 SAW */
-static int __devinit do_eeprom_cmd(void __iomem *ioaddr, int cmd, int cmd_len)
-{
- unsigned retval = 0;
- void __iomem *ee_addr = ioaddr + SCBeeprom;
-
- iowrite16(EE_ENB, ee_addr); udelay(2);
- iowrite16(EE_ENB | EE_SHIFT_CLK, ee_addr); udelay(2);
-
- /* Shift the command bits out. */
- do {
- short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
- iowrite16(dataval, ee_addr); udelay(2);
- iowrite16(dataval | EE_SHIFT_CLK, ee_addr); udelay(2);
- retval = (retval << 1) | ((ioread16(ee_addr) & EE_DATA_READ) ? 1 : 0);
- } while (--cmd_len >= 0);
- iowrite16(EE_ENB, ee_addr); udelay(2);
-
- /* Terminate the EEPROM access. */
- iowrite16(EE_ENB & ~EE_CS, ee_addr);
- return retval;
-}
-
-static int mdio_read(struct net_device *dev, int phy_id, int location)
-{
- struct speedo_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->regs;
- int val, boguscnt = 64*10; /* <64 usec. to complete, typ 27 ticks */
- iowrite32(0x08000000 | (location<<16) | (phy_id<<21), ioaddr + SCBCtrlMDI);
- do {
- val = ioread32(ioaddr + SCBCtrlMDI);
- if (--boguscnt < 0) {
- printk(KERN_ERR " mdio_read() timed out with val = %8.8x.\n", val);
- break;
- }
- } while (! (val & 0x10000000));
- return val & 0xffff;
-}
-
-static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
-{
- struct speedo_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->regs;
- int val, boguscnt = 64*10; /* <64 usec. to complete, typ 27 ticks */
- iowrite32(0x04000000 | (location<<16) | (phy_id<<21) | value,
- ioaddr + SCBCtrlMDI);
- do {
- val = ioread32(ioaddr + SCBCtrlMDI);
- if (--boguscnt < 0) {
- printk(KERN_ERR" mdio_write() timed out with val = %8.8x.\n", val);
- break;
- }
- } while (! (val & 0x10000000));
-}
-
-static int
-speedo_open(struct net_device *dev)
-{
- struct speedo_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->regs;
- int retval;
-
- if (netif_msg_ifup(sp))
- printk(KERN_DEBUG "%s: speedo_open() irq %d.\n", dev->name, dev->irq);
-
- pci_set_power_state(sp->pdev, PCI_D0);
-
- /* Set up the Tx queue early.. */
- sp->cur_tx = 0;
- sp->dirty_tx = 0;
- sp->last_cmd = NULL;
- sp->tx_full = 0;
- sp->in_interrupt = 0;
-
- /* .. we can safely take handler calls during init. */
- retval = request_irq(dev->irq, &speedo_interrupt, IRQF_SHARED, dev->name, dev);
- if (retval) {
- return retval;
- }
-
- dev->if_port = sp->default_port;
-
-#ifdef oh_no_you_dont_unless_you_honour_the_options_passed_in_to_us
- /* Retrigger negotiation to reset previous errors. */
- if ((sp->phy[0] & 0x8000) == 0) {
- int phy_addr = sp->phy[0] & 0x1f ;
- /* Use 0x3300 for restarting NWay, other values to force xcvr:
- 0x0000 10-HD
- 0x0100 10-FD
- 0x2000 100-HD
- 0x2100 100-FD
- */
-#ifdef honor_default_port
- mdio_write(dev, phy_addr, MII_BMCR, mii_ctrl[dev->default_port & 7]);
-#else
- mdio_write(dev, phy_addr, MII_BMCR, 0x3300);
-#endif
- }
-#endif
-
- speedo_init_rx_ring(dev);
-
- /* Fire up the hardware. */
- iowrite16(SCBMaskAll, ioaddr + SCBCmd);
- speedo_resume(dev);
-
- netdevice_start(dev);
- netif_start_queue(dev);
-
- /* Setup the chip and configure the multicast list. */
- sp->mc_setup_head = NULL;
- sp->mc_setup_tail = NULL;
- sp->flow_ctrl = sp->partner = 0;
- sp->rx_mode = -1; /* Invalid -> always reset the mode. */
- set_rx_mode(dev);
- if ((sp->phy[0] & 0x8000) == 0)
- sp->mii_if.advertising = mdio_read(dev, sp->phy[0] & 0x1f, MII_ADVERTISE);
-
- mii_check_link(&sp->mii_if);
-
- if (netif_msg_ifup(sp)) {
- printk(KERN_DEBUG "%s: Done speedo_open(), status %8.8x.\n",
- dev->name, ioread16(ioaddr + SCBStatus));
- }
-
- /* Set the timer. The timer serves a dual purpose:
- 1) to monitor the media interface (e.g. link beat) and perhaps switch
- to an alternate media type
- 2) to monitor Rx activity, and restart the Rx process if the receiver
- hangs. */
- sp->timer.expires = RUN_AT((24*HZ)/10); /* 2.4 sec. */
- sp->timer.data = (unsigned long)dev;
- sp->timer.function = &speedo_timer; /* timer handler */
- add_timer(&sp->timer);
-
- /* No need to wait for the command unit to accept here. */
- if ((sp->phy[0] & 0x8000) == 0)
- mdio_read(dev, sp->phy[0] & 0x1f, MII_BMCR);
-
- return 0;
-}
-
-/* Start the chip hardware after a full reset. */
-static void speedo_resume(struct net_device *dev)
-{
- struct speedo_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->regs;
-
- /* Start with a Tx threshold of 256 (0x..20.... 8 byte units). */
- sp->tx_threshold = 0x01208000;
-
- /* Set the segment registers to '0'. */
- if (wait_for_cmd_done(dev, sp) != 0) {
- iowrite32(PortPartialReset, ioaddr + SCBPort);
- udelay(10);
- }
-
- iowrite32(0, ioaddr + SCBPointer);
- ioread32(ioaddr + SCBPointer); /* Flush to PCI. */
- udelay(10); /* Bogus, but it avoids the bug. */
-
- /* Note: these next two operations can take a while. */
- do_slow_command(dev, sp, RxAddrLoad);
- do_slow_command(dev, sp, CUCmdBase);
-
- /* Load the statistics block and rx ring addresses. */
- iowrite32(sp->lstats_dma, ioaddr + SCBPointer);
- ioread32(ioaddr + SCBPointer); /* Flush to PCI */
-
- iowrite8(CUStatsAddr, ioaddr + SCBCmd);
- sp->lstats->done_marker = 0;
- wait_for_cmd_done(dev, sp);
-
- if (sp->rx_ringp[sp->cur_rx % RX_RING_SIZE] == NULL) {
- if (netif_msg_rx_err(sp))
- printk(KERN_DEBUG "%s: NULL cur_rx in speedo_resume().\n",
- dev->name);
- } else {
- iowrite32(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE],
- ioaddr + SCBPointer);
- ioread32(ioaddr + SCBPointer); /* Flush to PCI */
- }
-
- /* Note: RxStart should complete instantly. */
- do_slow_command(dev, sp, RxStart);
- do_slow_command(dev, sp, CUDumpStats);
-
- /* Fill the first command with our physical address. */
- {
- struct descriptor *ias_cmd;
-
- ias_cmd =
- (struct descriptor *)&sp->tx_ring[sp->cur_tx++ % TX_RING_SIZE];
- /* Avoid a bug(?!) here by marking the command already completed. */
- ias_cmd->cmd_status = cpu_to_le32((CmdSuspend | CmdIASetup) | 0xa000);
- ias_cmd->link =
- cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->cur_tx % TX_RING_SIZE));
- memcpy(ias_cmd->params, dev->dev_addr, 6);
- if (sp->last_cmd)
- clear_suspend(sp->last_cmd);
- sp->last_cmd = ias_cmd;
- }
-
- /* Start the chip's Tx process and unmask interrupts. */
- iowrite32(TX_RING_ELEM_DMA(sp, sp->dirty_tx % TX_RING_SIZE),
- ioaddr + SCBPointer);
- /* We are not ACK-ing FCP and ER in the interrupt handler yet so they should
- remain masked --Dragan */
- iowrite16(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl, ioaddr + SCBCmd);
-}
-
-/*
- * Sometimes the receiver stops making progress. This routine knows how to
- * get it going again, without losing packets or being otherwise nasty like
- * a chip reset would be. Previously the driver had a whole sequence
- * of if RxSuspended, if it's no buffers do one thing, if it's no resources,
- * do another, etc. But those things don't really matter. Separate logic
- * in the ISR provides for allocating buffers--the other half of operation
- * is just making sure the receiver is active. speedo_rx_soft_reset does that.
- * This problem with the old, more involved algorithm is shown up under
- * ping floods on the order of 60K packets/second on a 100Mbps fdx network.
- */
-static void
-speedo_rx_soft_reset(struct net_device *dev)
-{
- struct speedo_private *sp = netdev_priv(dev);
- struct RxFD *rfd;
- void __iomem *ioaddr;
-
- ioaddr = sp->regs;
- if (wait_for_cmd_done(dev, sp) != 0) {
- printk("%s: previous command stalled\n", dev->name);
- return;
- }
- /*
- * Put the hardware into a known state.
- */
- iowrite8(RxAbort, ioaddr + SCBCmd);
-
- rfd = sp->rx_ringp[sp->cur_rx % RX_RING_SIZE];
-
- rfd->rx_buf_addr = cpu_to_le32(0xffffffff);
-
- if (wait_for_cmd_done(dev, sp) != 0) {
- printk("%s: RxAbort command stalled\n", dev->name);
- return;
- }
- iowrite32(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE],
- ioaddr + SCBPointer);
- iowrite8(RxStart, ioaddr + SCBCmd);
-}
-
-
-/* Media monitoring and control. */
-static void speedo_timer(unsigned long data)
-{
- struct net_device *dev = (struct net_device *)data;
- struct speedo_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->regs;
- int phy_num = sp->phy[0] & 0x1f;
-
- /* We have MII and lost link beat. */
- if ((sp->phy[0] & 0x8000) == 0) {
- int partner = mdio_read(dev, phy_num, MII_LPA);
- if (partner != sp->partner) {
- int flow_ctrl = sp->mii_if.advertising & partner & 0x0400 ? 1 : 0;
- if (netif_msg_link(sp)) {
- printk(KERN_DEBUG "%s: Link status change.\n", dev->name);
- printk(KERN_DEBUG "%s: Old partner %x, new %x, adv %x.\n",
- dev->name, sp->partner, partner, sp->mii_if.advertising);
- }
- sp->partner = partner;
- if (flow_ctrl != sp->flow_ctrl) {
- sp->flow_ctrl = flow_ctrl;
- sp->rx_mode = -1; /* Trigger a reload. */
- }
- }
- }
- mii_check_link(&sp->mii_if);
- if (netif_msg_timer(sp)) {
- printk(KERN_DEBUG "%s: Media control tick, status %4.4x.\n",
- dev->name, ioread16(ioaddr + SCBStatus));
- }
- if (sp->rx_mode < 0 ||
- (sp->rx_bug && jiffies - sp->last_rx_time > 2*HZ)) {
- /* We haven't received a packet in a Long Time. We might have been
- bitten by the receiver hang bug. This can be cleared by sending
- a set multicast list command. */
- if (netif_msg_timer(sp))
- printk(KERN_DEBUG "%s: Sending a multicast list set command"
- " from a timer routine,"
- " m=%d, j=%ld, l=%ld.\n",
- dev->name, sp->rx_mode, jiffies, sp->last_rx_time);
- set_rx_mode(dev);
- }
- /* We must continue to monitor the media. */
- sp->timer.expires = RUN_AT(2*HZ); /* 2.0 sec. */
- add_timer(&sp->timer);
-}
-
-static void speedo_show_state(struct net_device *dev)
-{
- struct speedo_private *sp = netdev_priv(dev);
- int i;
-
- if (netif_msg_pktdata(sp)) {
- printk(KERN_DEBUG "%s: Tx ring dump, Tx queue %u / %u:\n",
- dev->name, sp->cur_tx, sp->dirty_tx);
- for (i = 0; i < TX_RING_SIZE; i++)
- printk(KERN_DEBUG "%s: %c%c%2d %8.8x.\n", dev->name,
- i == sp->dirty_tx % TX_RING_SIZE ? '*' : ' ',
- i == sp->cur_tx % TX_RING_SIZE ? '=' : ' ',
- i, sp->tx_ring[i].status);
-
- printk(KERN_DEBUG "%s: Printing Rx ring"
- " (next to receive into %u, dirty index %u).\n",
- dev->name, sp->cur_rx, sp->dirty_rx);
- for (i = 0; i < RX_RING_SIZE; i++)
- printk(KERN_DEBUG "%s: %c%c%c%2d %8.8x.\n", dev->name,
- sp->rx_ringp[i] == sp->last_rxf ? 'l' : ' ',
- i == sp->dirty_rx % RX_RING_SIZE ? '*' : ' ',
- i == sp->cur_rx % RX_RING_SIZE ? '=' : ' ',
- i, (sp->rx_ringp[i] != NULL) ?
- (unsigned)sp->rx_ringp[i]->status : 0);
- }
-
-#if 0
- {
- void __iomem *ioaddr = sp->regs;
- int phy_num = sp->phy[0] & 0x1f;
- for (i = 0; i < 16; i++) {
- /* FIXME: what does it mean? --SAW */
- if (i == 6) i = 21;
- printk(KERN_DEBUG "%s: PHY index %d register %d is %4.4x.\n",
- dev->name, phy_num, i, mdio_read(dev, phy_num, i));
- }
- }
-#endif
-
-}
-
-/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
-static void
-speedo_init_rx_ring(struct net_device *dev)
-{
- struct speedo_private *sp = netdev_priv(dev);
- struct RxFD *rxf, *last_rxf = NULL;
- dma_addr_t last_rxf_dma = 0 /* to shut up the compiler */;
- int i;
-
- sp->cur_rx = 0;
-
- for (i = 0; i < RX_RING_SIZE; i++) {
- struct sk_buff *skb;
- skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
- if (skb)
- rx_align(skb); /* Align IP on 16 byte boundary */
- sp->rx_skbuff[i] = skb;
- if (skb == NULL)
- break; /* OK. Just initially short of Rx bufs. */
- skb->dev = dev; /* Mark as being used by this device. */
- rxf = (struct RxFD *)skb->data;
- sp->rx_ringp[i] = rxf;
- sp->rx_ring_dma[i] =
- pci_map_single(sp->pdev, rxf,
- PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_BIDIRECTIONAL);
- skb_reserve(skb, sizeof(struct RxFD));
- if (last_rxf) {
- last_rxf->link = cpu_to_le32(sp->rx_ring_dma[i]);
- pci_dma_sync_single_for_device(sp->pdev, last_rxf_dma,
- sizeof(struct RxFD), PCI_DMA_TODEVICE);
- }
- last_rxf = rxf;
- last_rxf_dma = sp->rx_ring_dma[i];
- rxf->status = cpu_to_le32(0x00000001); /* '1' is flag value only. */
- rxf->link = 0; /* None yet. */
- /* This field unused by i82557. */
- rxf->rx_buf_addr = cpu_to_le32(0xffffffff);
- rxf->count = cpu_to_le32(PKT_BUF_SZ << 16);
- pci_dma_sync_single_for_device(sp->pdev, sp->rx_ring_dma[i],
- sizeof(struct RxFD), PCI_DMA_TODEVICE);
- }
- sp->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
- /* Mark the last entry as end-of-list. */
- last_rxf->status = cpu_to_le32(0xC0000002); /* '2' is flag value only. */
- pci_dma_sync_single_for_device(sp->pdev, sp->rx_ring_dma[RX_RING_SIZE-1],
- sizeof(struct RxFD), PCI_DMA_TODEVICE);
- sp->last_rxf = last_rxf;
- sp->last_rxf_dma = last_rxf_dma;
-}
-
-static void speedo_purge_tx(struct net_device *dev)
-{
- struct speedo_private *sp = netdev_priv(dev);
- int entry;
-
- while ((int)(sp->cur_tx - sp->dirty_tx) > 0) {
- entry = sp->dirty_tx % TX_RING_SIZE;
- if (sp->tx_skbuff[entry]) {
- sp->stats.tx_errors++;
- pci_unmap_single(sp->pdev,
- le32_to_cpu(sp->tx_ring[entry].tx_buf_addr0),
- sp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE);
- dev_kfree_skb_irq(sp->tx_skbuff[entry]);
- sp->tx_skbuff[entry] = NULL;
- }
- sp->dirty_tx++;
- }
- while (sp->mc_setup_head != NULL) {
- struct speedo_mc_block *t;
- if (netif_msg_tx_err(sp))
- printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name);
- pci_unmap_single(sp->pdev, sp->mc_setup_head->frame_dma,
- sp->mc_setup_head->len, PCI_DMA_TODEVICE);
- t = sp->mc_setup_head->next;
- kfree(sp->mc_setup_head);
- sp->mc_setup_head = t;
- }
- sp->mc_setup_tail = NULL;
- sp->tx_full = 0;
- netif_wake_queue(dev);
-}
-
-static void reset_mii(struct net_device *dev)
-{
- struct speedo_private *sp = netdev_priv(dev);
-
- /* Reset the MII transceiver, suggested by Fred Young @ scalable.com. */
- if ((sp->phy[0] & 0x8000) == 0) {
- int phy_addr = sp->phy[0] & 0x1f;
- int advertising = mdio_read(dev, phy_addr, MII_ADVERTISE);
- int mii_bmcr = mdio_read(dev, phy_addr, MII_BMCR);
- mdio_write(dev, phy_addr, MII_BMCR, 0x0400);
- mdio_write(dev, phy_addr, MII_BMSR, 0x0000);
- mdio_write(dev, phy_addr, MII_ADVERTISE, 0x0000);
- mdio_write(dev, phy_addr, MII_BMCR, 0x8000);
-#ifdef honor_default_port
- mdio_write(dev, phy_addr, MII_BMCR, mii_ctrl[dev->default_port & 7]);
-#else
- mdio_read(dev, phy_addr, MII_BMCR);
- mdio_write(dev, phy_addr, MII_BMCR, mii_bmcr);
- mdio_write(dev, phy_addr, MII_ADVERTISE, advertising);
-#endif
- }
-}
-
-static void speedo_tx_timeout(struct net_device *dev)
-{
- struct speedo_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->regs;
- int status = ioread16(ioaddr + SCBStatus);
- unsigned long flags;
-
- if (netif_msg_tx_err(sp)) {
- printk(KERN_WARNING "%s: Transmit timed out: status %4.4x "
- " %4.4x at %d/%d command %8.8x.\n",
- dev->name, status, ioread16(ioaddr + SCBCmd),
- sp->dirty_tx, sp->cur_tx,
- sp->tx_ring[sp->dirty_tx % TX_RING_SIZE].status);
-
- }
- speedo_show_state(dev);
-#if 0
- if ((status & 0x00C0) != 0x0080
- && (status & 0x003C) == 0x0010) {
- /* Only the command unit has stopped. */
- printk(KERN_WARNING "%s: Trying to restart the transmitter...\n",
- dev->name);
- iowrite32(TX_RING_ELEM_DMA(sp, dirty_tx % TX_RING_SIZE]),
- ioaddr + SCBPointer);
- iowrite16(CUStart, ioaddr + SCBCmd);
- reset_mii(dev);
- } else {
-#else
- {
-#endif
- del_timer_sync(&sp->timer);
- /* Reset the Tx and Rx units. */
- iowrite32(PortReset, ioaddr + SCBPort);
- /* We may get spurious interrupts here. But I don't think that they
- may do much harm. 1999/12/09 SAW */
- udelay(10);
- /* Disable interrupts. */
- iowrite16(SCBMaskAll, ioaddr + SCBCmd);
- synchronize_irq(dev->irq);
- speedo_tx_buffer_gc(dev);
- /* Free as much as possible.
- It helps to recover from a hang because of out-of-memory.
- It also simplifies speedo_resume() in case TX ring is full or
- close-to-be full. */
- speedo_purge_tx(dev);
- speedo_refill_rx_buffers(dev, 1);
- spin_lock_irqsave(&sp->lock, flags);
- speedo_resume(dev);
- sp->rx_mode = -1;
- dev->trans_start = jiffies;
- spin_unlock_irqrestore(&sp->lock, flags);
- set_rx_mode(dev); /* it takes the spinlock itself --SAW */
- /* Reset MII transceiver. Do it before starting the timer to serialize
- mdio_xxx operations. Yes, it's a paranoya :-) 2000/05/09 SAW */
- reset_mii(dev);
- sp->timer.expires = RUN_AT(2*HZ);
- add_timer(&sp->timer);
- }
- return;
-}
-
-static int
-speedo_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct speedo_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->regs;
- int entry;
-
- /* Prevent interrupts from changing the Tx ring from underneath us. */
- unsigned long flags;
-
- spin_lock_irqsave(&sp->lock, flags);
-
- /* Check if there are enough space. */
- if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
- printk(KERN_ERR "%s: incorrect tbusy state, fixed.\n", dev->name);
- netif_stop_queue(dev);
- sp->tx_full = 1;
- spin_unlock_irqrestore(&sp->lock, flags);
- return 1;
- }
-
- /* Calculate the Tx descriptor entry. */
- entry = sp->cur_tx++ % TX_RING_SIZE;
-
- sp->tx_skbuff[entry] = skb;
- sp->tx_ring[entry].status =
- cpu_to_le32(CmdSuspend | CmdTx | CmdTxFlex);
- if (!(entry & ((TX_RING_SIZE>>2)-1)))
- sp->tx_ring[entry].status |= cpu_to_le32(CmdIntr);
- sp->tx_ring[entry].link =
- cpu_to_le32(TX_RING_ELEM_DMA(sp, sp->cur_tx % TX_RING_SIZE));
- sp->tx_ring[entry].tx_desc_addr =
- cpu_to_le32(TX_RING_ELEM_DMA(sp, entry) + TX_DESCR_BUF_OFFSET);
- /* The data region is always in one buffer descriptor. */
- sp->tx_ring[entry].count = cpu_to_le32(sp->tx_threshold);
- sp->tx_ring[entry].tx_buf_addr0 =
- cpu_to_le32(pci_map_single(sp->pdev, skb->data,
- skb->len, PCI_DMA_TODEVICE));
- sp->tx_ring[entry].tx_buf_size0 = cpu_to_le32(skb->len);
-
- /* workaround for hardware bug on 10 mbit half duplex */
-
- if ((sp->partner == 0) && (sp->chip_id == 1)) {
- wait_for_cmd_done(dev, sp);
- iowrite8(0 , ioaddr + SCBCmd);
- udelay(1);
- }
-
- /* Trigger the command unit resume. */
- wait_for_cmd_done(dev, sp);
- clear_suspend(sp->last_cmd);
- /* We want the time window between clearing suspend flag on the previous
- command and resuming CU to be as small as possible.
- Interrupts in between are very undesired. --SAW */
- iowrite8(CUResume, ioaddr + SCBCmd);
- sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
-
- /* Leave room for set_rx_mode(). If there is no more space than reserved
- for multicast filter mark the ring as full. */
- if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
- netif_stop_queue(dev);
- sp->tx_full = 1;
- }
-
- spin_unlock_irqrestore(&sp->lock, flags);
-
- dev->trans_start = jiffies;
-
- return 0;
-}
-
-static void speedo_tx_buffer_gc(struct net_device *dev)
-{
- unsigned int dirty_tx;
- struct speedo_private *sp = netdev_priv(dev);
-
- dirty_tx = sp->dirty_tx;
- while ((int)(sp->cur_tx - dirty_tx) > 0) {
- int entry = dirty_tx % TX_RING_SIZE;
- int status = le32_to_cpu(sp->tx_ring[entry].status);
-
- if (netif_msg_tx_done(sp))
- printk(KERN_DEBUG " scavenge candidate %d status %4.4x.\n",
- entry, status);
- if ((status & StatusComplete) == 0)
- break; /* It still hasn't been processed. */
- if (status & TxUnderrun)
- if (sp->tx_threshold < 0x01e08000) {
- if (netif_msg_tx_err(sp))
- printk(KERN_DEBUG "%s: TX underrun, threshold adjusted.\n",
- dev->name);
- sp->tx_threshold += 0x00040000;
- }
- /* Free the original skb. */
- if (sp->tx_skbuff[entry]) {
- sp->stats.tx_packets++; /* Count only user packets. */
- sp->stats.tx_bytes += sp->tx_skbuff[entry]->len;
- pci_unmap_single(sp->pdev,
- le32_to_cpu(sp->tx_ring[entry].tx_buf_addr0),
- sp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE);
- dev_kfree_skb_irq(sp->tx_skbuff[entry]);
- sp->tx_skbuff[entry] = NULL;
- }
- dirty_tx++;
- }
-
- if (netif_msg_tx_err(sp) && (int)(sp->cur_tx - dirty_tx) > TX_RING_SIZE) {
- printk(KERN_ERR "out-of-sync dirty pointer, %d vs. %d,"
- " full=%d.\n",
- dirty_tx, sp->cur_tx, sp->tx_full);
- dirty_tx += TX_RING_SIZE;
- }
-
- while (sp->mc_setup_head != NULL
- && (int)(dirty_tx - sp->mc_setup_head->tx - 1) > 0) {
- struct speedo_mc_block *t;
- if (netif_msg_tx_err(sp))
- printk(KERN_DEBUG "%s: freeing mc frame.\n", dev->name);
- pci_unmap_single(sp->pdev, sp->mc_setup_head->frame_dma,
- sp->mc_setup_head->len, PCI_DMA_TODEVICE);
- t = sp->mc_setup_head->next;
- kfree(sp->mc_setup_head);
- sp->mc_setup_head = t;
- }
- if (sp->mc_setup_head == NULL)
- sp->mc_setup_tail = NULL;
-
- sp->dirty_tx = dirty_tx;
-}
-
-/* The interrupt handler does all of the Rx thread work and cleans up
- after the Tx thread. */
-static irqreturn_t speedo_interrupt(int irq, void *dev_instance)
-{
- struct net_device *dev = (struct net_device *)dev_instance;
- struct speedo_private *sp;
- void __iomem *ioaddr;
- long boguscnt = max_interrupt_work;
- unsigned short status;
- unsigned int handled = 0;
-
- sp = netdev_priv(dev);
- ioaddr = sp->regs;
-
-#ifndef final_version
- /* A lock to prevent simultaneous entry on SMP machines. */
- if (test_and_set_bit(0, (void*)&sp->in_interrupt)) {
- printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
- dev->name);
- sp->in_interrupt = 0; /* Avoid halting machine. */
- return IRQ_NONE;
- }
-#endif
-
- do {
- status = ioread16(ioaddr + SCBStatus);
- /* Acknowledge all of the current interrupt sources ASAP. */
- /* Will change from 0xfc00 to 0xff00 when we start handling
- FCP and ER interrupts --Dragan */
- iowrite16(status & 0xfc00, ioaddr + SCBStatus);
-
- if (netif_msg_intr(sp))
- printk(KERN_DEBUG "%s: interrupt status=%#4.4x.\n",
- dev->name, status);
-
- if ((status & 0xfc00) == 0)
- break;
- handled = 1;
-
-
- if ((status & 0x5000) || /* Packet received, or Rx error. */
- (sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed)
- /* Need to gather the postponed packet. */
- speedo_rx(dev);
-
- /* Always check if all rx buffers are allocated. --SAW */
- speedo_refill_rx_buffers(dev, 0);
-
- spin_lock(&sp->lock);
- /*
- * The chip may have suspended reception for various reasons.
- * Check for that, and re-prime it should this be the case.
- */
- switch ((status >> 2) & 0xf) {
- case 0: /* Idle */
- break;
- case 1: /* Suspended */
- case 2: /* No resources (RxFDs) */
- case 9: /* Suspended with no more RBDs */
- case 10: /* No resources due to no RBDs */
- case 12: /* Ready with no RBDs */
- speedo_rx_soft_reset(dev);
- break;
- case 3: case 5: case 6: case 7: case 8:
- case 11: case 13: case 14: case 15:
- /* these are all reserved values */
- break;
- }
-
-
- /* User interrupt, Command/Tx unit interrupt or CU not active. */
- if (status & 0xA400) {
- speedo_tx_buffer_gc(dev);
- if (sp->tx_full
- && (int)(sp->cur_tx - sp->dirty_tx) < TX_QUEUE_UNFULL) {
- /* The ring is no longer full. */
- sp->tx_full = 0;
- netif_wake_queue(dev); /* Attention: under a spinlock. --SAW */
- }
- }
-
- spin_unlock(&sp->lock);
-
- if (--boguscnt < 0) {
- printk(KERN_ERR "%s: Too much work at interrupt, status=0x%4.4x.\n",
- dev->name, status);
- /* Clear all interrupt sources. */
- /* Will change from 0xfc00 to 0xff00 when we start handling
- FCP and ER interrupts --Dragan */
- iowrite16(0xfc00, ioaddr + SCBStatus);
- break;
- }
- } while (1);
-
- if (netif_msg_intr(sp))
- printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
- dev->name, ioread16(ioaddr + SCBStatus));
-
- clear_bit(0, (void*)&sp->in_interrupt);
- return IRQ_RETVAL(handled);
-}
-
-static inline struct RxFD *speedo_rx_alloc(struct net_device *dev, int entry)
-{
- struct speedo_private *sp = netdev_priv(dev);
- struct RxFD *rxf;
- struct sk_buff *skb;
- /* Get a fresh skbuff to replace the consumed one. */
- skb = dev_alloc_skb(PKT_BUF_SZ + sizeof(struct RxFD));
- if (skb)
- rx_align(skb); /* Align IP on 16 byte boundary */
- sp->rx_skbuff[entry] = skb;
- if (skb == NULL) {
- sp->rx_ringp[entry] = NULL;
- return NULL;
- }
- rxf = sp->rx_ringp[entry] = (struct RxFD *)skb->data;
- sp->rx_ring_dma[entry] =
- pci_map_single(sp->pdev, rxf,
- PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
- skb->dev = dev;
- skb_reserve(skb, sizeof(struct RxFD));
- rxf->rx_buf_addr = cpu_to_le32(0xffffffff);
- pci_dma_sync_single_for_device(sp->pdev, sp->rx_ring_dma[entry],
- sizeof(struct RxFD), PCI_DMA_TODEVICE);
- return rxf;
-}
-
-static inline void speedo_rx_link(struct net_device *dev, int entry,
- struct RxFD *rxf, dma_addr_t rxf_dma)
-{
- struct speedo_private *sp = netdev_priv(dev);
- rxf->status = cpu_to_le32(0xC0000001); /* '1' for driver use only. */
- rxf->link = 0; /* None yet. */
- rxf->count = cpu_to_le32(PKT_BUF_SZ << 16);
- sp->last_rxf->link = cpu_to_le32(rxf_dma);
- sp->last_rxf->status &= cpu_to_le32(~0xC0000000);
- pci_dma_sync_single_for_device(sp->pdev, sp->last_rxf_dma,
- sizeof(struct RxFD), PCI_DMA_TODEVICE);
- sp->last_rxf = rxf;
- sp->last_rxf_dma = rxf_dma;
-}
-
-static int speedo_refill_rx_buf(struct net_device *dev, int force)
-{
- struct speedo_private *sp = netdev_priv(dev);
- int entry;
- struct RxFD *rxf;
-
- entry = sp->dirty_rx % RX_RING_SIZE;
- if (sp->rx_skbuff[entry] == NULL) {
- rxf = speedo_rx_alloc(dev, entry);
- if (rxf == NULL) {
- unsigned int forw;
- int forw_entry;
- if (netif_msg_rx_err(sp) || !(sp->rx_ring_state & RrOOMReported)) {
- printk(KERN_WARNING "%s: can't fill rx buffer (force %d)!\n",
- dev->name, force);
- sp->rx_ring_state |= RrOOMReported;
- }
- speedo_show_state(dev);
- if (!force)
- return -1; /* Better luck next time! */
- /* Borrow an skb from one of next entries. */
- for (forw = sp->dirty_rx + 1; forw != sp->cur_rx; forw++)
- if (sp->rx_skbuff[forw % RX_RING_SIZE] != NULL)
- break;
- if (forw == sp->cur_rx)
- return -1;
- forw_entry = forw % RX_RING_SIZE;
- sp->rx_skbuff[entry] = sp->rx_skbuff[forw_entry];
- sp->rx_skbuff[forw_entry] = NULL;
- rxf = sp->rx_ringp[forw_entry];
- sp->rx_ringp[forw_entry] = NULL;
- sp->rx_ringp[entry] = rxf;
- }
- } else {
- rxf = sp->rx_ringp[entry];
- }
- speedo_rx_link(dev, entry, rxf, sp->rx_ring_dma[entry]);
- sp->dirty_rx++;
- sp->rx_ring_state &= ~(RrNoMem|RrOOMReported); /* Mark the progress. */
- return 0;
-}
-
-static void speedo_refill_rx_buffers(struct net_device *dev, int force)
-{
- struct speedo_private *sp = netdev_priv(dev);
-
- /* Refill the RX ring. */
- while ((int)(sp->cur_rx - sp->dirty_rx) > 0 &&
- speedo_refill_rx_buf(dev, force) != -1);
-}
-
-static int
-speedo_rx(struct net_device *dev)
-{
- struct speedo_private *sp = netdev_priv(dev);
- int entry = sp->cur_rx % RX_RING_SIZE;
- int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx;
- int alloc_ok = 1;
- int npkts = 0;
-
- if (netif_msg_intr(sp))
- printk(KERN_DEBUG " In speedo_rx().\n");
- /* If we own the next entry, it's a new packet. Send it up. */
- while (sp->rx_ringp[entry] != NULL) {
- int status;
- int pkt_len;
-
- pci_dma_sync_single_for_cpu(sp->pdev, sp->rx_ring_dma[entry],
- sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
- status = le32_to_cpu(sp->rx_ringp[entry]->status);
- pkt_len = le32_to_cpu(sp->rx_ringp[entry]->count) & 0x3fff;
-
- if (!(status & RxComplete))
- break;
-
- if (--rx_work_limit < 0)
- break;
-
- /* Check for a rare out-of-memory case: the current buffer is
- the last buffer allocated in the RX ring. --SAW */
- if (sp->last_rxf == sp->rx_ringp[entry]) {
- /* Postpone the packet. It'll be reaped at an interrupt when this
- packet is no longer the last packet in the ring. */
- if (netif_msg_rx_err(sp))
- printk(KERN_DEBUG "%s: RX packet postponed!\n",
- dev->name);
- sp->rx_ring_state |= RrPostponed;
- break;
- }
-
- if (netif_msg_rx_status(sp))
- printk(KERN_DEBUG " speedo_rx() status %8.8x len %d.\n", status,
- pkt_len);
- if ((status & (RxErrTooBig|RxOK|0x0f90)) != RxOK) {
- if (status & RxErrTooBig)
- printk(KERN_ERR "%s: Ethernet frame overran the Rx buffer, "
- "status %8.8x!\n", dev->name, status);
- else if (! (status & RxOK)) {
- /* There was a fatal error. This *should* be impossible. */
- sp->stats.rx_errors++;
- printk(KERN_ERR "%s: Anomalous event in speedo_rx(), "
- "status %8.8x.\n",
- dev->name, status);
- }
- } else {
- struct sk_buff *skb;
-
- /* Check if the packet is long enough to just accept without
- copying to a properly sized skbuff. */
- if (pkt_len < rx_copybreak
- && (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
- skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
- /* 'skb_put()' points to the start of sk_buff data area. */
- pci_dma_sync_single_for_cpu(sp->pdev, sp->rx_ring_dma[entry],
- sizeof(struct RxFD) + pkt_len,
- PCI_DMA_FROMDEVICE);
-
-#if 1 || USE_IP_CSUM
- /* Packet is in one chunk -- we can copy + cksum. */
- skb_copy_to_linear_data(skb, sp->rx_skbuff[entry]->data, pkt_len);
- skb_put(skb, pkt_len);
-#else
- skb_copy_from_linear_data(sp->rx_skbuff[entry],
- skb_put(skb, pkt_len),
- pkt_len);
-#endif
- pci_dma_sync_single_for_device(sp->pdev, sp->rx_ring_dma[entry],
- sizeof(struct RxFD) + pkt_len,
- PCI_DMA_FROMDEVICE);
- npkts++;
- } else {
- /* Pass up the already-filled skbuff. */
- skb = sp->rx_skbuff[entry];
- if (skb == NULL) {
- printk(KERN_ERR "%s: Inconsistent Rx descriptor chain.\n",
- dev->name);
- break;
- }
- sp->rx_skbuff[entry] = NULL;
- skb_put(skb, pkt_len);
- npkts++;
- sp->rx_ringp[entry] = NULL;
- pci_unmap_single(sp->pdev, sp->rx_ring_dma[entry],
- PKT_BUF_SZ + sizeof(struct RxFD),
- PCI_DMA_FROMDEVICE);
- }
- skb->protocol = eth_type_trans(skb, dev);
- netif_rx(skb);
- dev->last_rx = jiffies;
- sp->stats.rx_packets++;
- sp->stats.rx_bytes += pkt_len;
- }
- entry = (++sp->cur_rx) % RX_RING_SIZE;
- sp->rx_ring_state &= ~RrPostponed;
- /* Refill the recently taken buffers.
- Do it one-by-one to handle traffic bursts better. */
- if (alloc_ok && speedo_refill_rx_buf(dev, 0) == -1)
- alloc_ok = 0;
- }
-
- /* Try hard to refill the recently taken buffers. */
- speedo_refill_rx_buffers(dev, 1);
-
- if (npkts)
- sp->last_rx_time = jiffies;
-
- return 0;
-}
-
-static int
-speedo_close(struct net_device *dev)
-{
- struct speedo_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->regs;
- int i;
-
- netdevice_stop(dev);
- netif_stop_queue(dev);
-
- if (netif_msg_ifdown(sp))
- printk(KERN_DEBUG "%s: Shutting down ethercard, status was %4.4x.\n",
- dev->name, ioread16(ioaddr + SCBStatus));
-
- /* Shut off the media monitoring timer. */
- del_timer_sync(&sp->timer);
-
- iowrite16(SCBMaskAll, ioaddr + SCBCmd);
-
- /* Shutting down the chip nicely fails to disable flow control. So.. */
- iowrite32(PortPartialReset, ioaddr + SCBPort);
- ioread32(ioaddr + SCBPort); /* flush posted write */
- /*
- * The chip requires a 10 microsecond quiet period. Wait here!
- */
- udelay(10);
-
- free_irq(dev->irq, dev);
- speedo_show_state(dev);
-
- /* Free all the skbuffs in the Rx and Tx queues. */
- for (i = 0; i < RX_RING_SIZE; i++) {
- struct sk_buff *skb = sp->rx_skbuff[i];
- sp->rx_skbuff[i] = NULL;
- /* Clear the Rx descriptors. */
- if (skb) {
- pci_unmap_single(sp->pdev,
- sp->rx_ring_dma[i],
- PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
- dev_kfree_skb(skb);
- }
- }
-
- for (i = 0; i < TX_RING_SIZE; i++) {
- struct sk_buff *skb = sp->tx_skbuff[i];
- sp->tx_skbuff[i] = NULL;
- /* Clear the Tx descriptors. */
- if (skb) {
- pci_unmap_single(sp->pdev,
- le32_to_cpu(sp->tx_ring[i].tx_buf_addr0),
- skb->len, PCI_DMA_TODEVICE);
- dev_kfree_skb(skb);
- }
- }
-
- /* Free multicast setting blocks. */
- for (i = 0; sp->mc_setup_head != NULL; i++) {
- struct speedo_mc_block *t;
- t = sp->mc_setup_head->next;
- kfree(sp->mc_setup_head);
- sp->mc_setup_head = t;
- }
- sp->mc_setup_tail = NULL;
- if (netif_msg_ifdown(sp))
- printk(KERN_DEBUG "%s: %d multicast blocks dropped.\n", dev->name, i);
-
- pci_set_power_state(sp->pdev, PCI_D2);
-
- return 0;
-}
-
-/* The Speedo-3 has an especially awkward and unusable method of getting
- statistics out of the chip. It takes an unpredictable length of time
- for the dump-stats command to complete. To avoid a busy-wait loop we
- update the stats with the previous dump results, and then trigger a
- new dump.
-
- Oh, and incoming frames are dropped while executing dump-stats!
- */
-static struct net_device_stats *
-speedo_get_stats(struct net_device *dev)
-{
- struct speedo_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->regs;
-
- /* Update only if the previous dump finished. */
- if (sp->lstats->done_marker == cpu_to_le32(0xA007)) {
- sp->stats.tx_aborted_errors += le32_to_cpu(sp->lstats->tx_coll16_errs);
- sp->stats.tx_window_errors += le32_to_cpu(sp->lstats->tx_late_colls);
- sp->stats.tx_fifo_errors += le32_to_cpu(sp->lstats->tx_underruns);
- sp->stats.tx_fifo_errors += le32_to_cpu(sp->lstats->tx_lost_carrier);
- /*sp->stats.tx_deferred += le32_to_cpu(sp->lstats->tx_deferred);*/
- sp->stats.collisions += le32_to_cpu(sp->lstats->tx_total_colls);
- sp->stats.rx_crc_errors += le32_to_cpu(sp->lstats->rx_crc_errs);
- sp->stats.rx_frame_errors += le32_to_cpu(sp->lstats->rx_align_errs);
- sp->stats.rx_over_errors += le32_to_cpu(sp->lstats->rx_resource_errs);
- sp->stats.rx_fifo_errors += le32_to_cpu(sp->lstats->rx_overrun_errs);
- sp->stats.rx_length_errors += le32_to_cpu(sp->lstats->rx_runt_errs);
- sp->lstats->done_marker = 0x0000;
- if (netif_running(dev)) {
- unsigned long flags;
- /* Take a spinlock to make wait_for_cmd_done and sending the
- command atomic. --SAW */
- spin_lock_irqsave(&sp->lock, flags);
- wait_for_cmd_done(dev, sp);
- iowrite8(CUDumpStats, ioaddr + SCBCmd);
- spin_unlock_irqrestore(&sp->lock, flags);
- }
- }
- return &sp->stats;
-}
-
-static void speedo_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
-{
- struct speedo_private *sp = netdev_priv(dev);
- strncpy(info->driver, "eepro100", sizeof(info->driver)-1);
- strncpy(info->version, version, sizeof(info->version)-1);
- if (sp->pdev)
- strcpy(info->bus_info, pci_name(sp->pdev));
-}
-
-static int speedo_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
- struct speedo_private *sp = netdev_priv(dev);
- spin_lock_irq(&sp->lock);
- mii_ethtool_gset(&sp->mii_if, ecmd);
- spin_unlock_irq(&sp->lock);
- return 0;
-}
-
-static int speedo_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
-{
- struct speedo_private *sp = netdev_priv(dev);
- int res;
- spin_lock_irq(&sp->lock);
- res = mii_ethtool_sset(&sp->mii_if, ecmd);
- spin_unlock_irq(&sp->lock);
- return res;
-}
-
-static int speedo_nway_reset(struct net_device *dev)
-{
- struct speedo_private *sp = netdev_priv(dev);
- return mii_nway_restart(&sp->mii_if);
-}
-
-static u32 speedo_get_link(struct net_device *dev)
-{
- struct speedo_private *sp = netdev_priv(dev);
- return mii_link_ok(&sp->mii_if);
-}
-
-static u32 speedo_get_msglevel(struct net_device *dev)
-{
- struct speedo_private *sp = netdev_priv(dev);
- return sp->msg_enable;
-}
-
-static void speedo_set_msglevel(struct net_device *dev, u32 v)
-{
- struct speedo_private *sp = netdev_priv(dev);
- sp->msg_enable = v;
-}
-
-static const struct ethtool_ops ethtool_ops = {
- .get_drvinfo = speedo_get_drvinfo,
- .get_settings = speedo_get_settings,
- .set_settings = speedo_set_settings,
- .nway_reset = speedo_nway_reset,
- .get_link = speedo_get_link,
- .get_msglevel = speedo_get_msglevel,
- .set_msglevel = speedo_set_msglevel,
-};
-
-static int speedo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
- struct speedo_private *sp = netdev_priv(dev);
- struct mii_ioctl_data *data = if_mii(rq);
- int phy = sp->phy[0] & 0x1f;
- int saved_acpi;
- int t;
-
- switch(cmd) {
- case SIOCGMIIPHY: /* Get address of MII PHY in use. */
- data->phy_id = phy;
-
- case SIOCGMIIREG: /* Read MII PHY register. */
- /* FIXME: these operations need to be serialized with MDIO
- access from the timeout handler.
- They are currently serialized only with MDIO access from the
- timer routine. 2000/05/09 SAW */
- saved_acpi = pci_set_power_state(sp->pdev, PCI_D0);
- t = del_timer_sync(&sp->timer);
- data->val_out = mdio_read(dev, data->phy_id & 0x1f, data->reg_num & 0x1f);
- if (t)
- add_timer(&sp->timer); /* may be set to the past --SAW */
- pci_set_power_state(sp->pdev, saved_acpi);
- return 0;
-
- case SIOCSMIIREG: /* Write MII PHY register. */
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- saved_acpi = pci_set_power_state(sp->pdev, PCI_D0);
- t = del_timer_sync(&sp->timer);
- mdio_write(dev, data->phy_id, data->reg_num, data->val_in);
- if (t)
- add_timer(&sp->timer); /* may be set to the past --SAW */
- pci_set_power_state(sp->pdev, saved_acpi);
- return 0;
- default:
- return -EOPNOTSUPP;
- }
-}
-
-/* Set or clear the multicast filter for this adaptor.
- This is very ugly with Intel chips -- we usually have to execute an
- entire configuration command, plus process a multicast command.
- This is complicated. We must put a large configuration command and
- an arbitrarily-sized multicast command in the transmit list.
- To minimize the disruption -- the previous command might have already
- loaded the link -- we convert the current command block, normally a Tx
- command, into a no-op and link it to the new command.
-*/
-static void set_rx_mode(struct net_device *dev)
-{
- struct speedo_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->regs;
- struct descriptor *last_cmd;
- char new_rx_mode;
- unsigned long flags;
- int entry, i;
-
- if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
- new_rx_mode = 3;
- } else if ((dev->flags & IFF_ALLMULTI) ||
- dev->mc_count > multicast_filter_limit) {
- new_rx_mode = 1;
- } else
- new_rx_mode = 0;
-
- if (netif_msg_rx_status(sp))
- printk(KERN_DEBUG "%s: set_rx_mode %d -> %d\n", dev->name,
- sp->rx_mode, new_rx_mode);
-
- if ((int)(sp->cur_tx - sp->dirty_tx) > TX_RING_SIZE - TX_MULTICAST_SIZE) {
- /* The Tx ring is full -- don't add anything! Hope the mode will be
- * set again later. */
- sp->rx_mode = -1;
- return;
- }
-
- if (new_rx_mode != sp->rx_mode) {
- u8 *config_cmd_data;
-
- spin_lock_irqsave(&sp->lock, flags);
- entry = sp->cur_tx++ % TX_RING_SIZE;
- last_cmd = sp->last_cmd;
- sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
-
- sp->tx_skbuff[entry] = NULL; /* Redundant. */
- sp->tx_ring[entry].status = cpu_to_le32(CmdSuspend | CmdConfigure);
- sp->tx_ring[entry].link =
- cpu_to_le32(TX_RING_ELEM_DMA(sp, (entry + 1) % TX_RING_SIZE));
- config_cmd_data = (void *)&sp->tx_ring[entry].tx_desc_addr;
- /* Construct a full CmdConfig frame. */
- memcpy(config_cmd_data, i82558_config_cmd, CONFIG_DATA_SIZE);
- config_cmd_data[1] = (txfifo << 4) | rxfifo;
- config_cmd_data[4] = rxdmacount;
- config_cmd_data[5] = txdmacount + 0x80;
- config_cmd_data[15] |= (new_rx_mode & 2) ? 1 : 0;
- /* 0x80 doesn't disable FC 0x84 does.
- Disable Flow control since we are not ACK-ing any FC interrupts
- for now. --Dragan */
- config_cmd_data[19] = 0x84;
- config_cmd_data[19] |= sp->mii_if.full_duplex ? 0x40 : 0;
- config_cmd_data[21] = (new_rx_mode & 1) ? 0x0D : 0x05;
- if (sp->phy[0] & 0x8000) { /* Use the AUI port instead. */
- config_cmd_data[15] |= 0x80;
- config_cmd_data[8] = 0;
- }
- /* Trigger the command unit resume. */
- wait_for_cmd_done(dev, sp);
- clear_suspend(last_cmd);
- iowrite8(CUResume, ioaddr + SCBCmd);
- if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
- netif_stop_queue(dev);
- sp->tx_full = 1;
- }
- spin_unlock_irqrestore(&sp->lock, flags);
- }
-
- if (new_rx_mode == 0 && dev->mc_count < 4) {
- /* The simple case of 0-3 multicast list entries occurs often, and
- fits within one tx_ring[] entry. */
- struct dev_mc_list *mclist;
- __le16 *setup_params, *eaddrs;
-
- spin_lock_irqsave(&sp->lock, flags);
- entry = sp->cur_tx++ % TX_RING_SIZE;
- last_cmd = sp->last_cmd;
- sp->last_cmd = (struct descriptor *)&sp->tx_ring[entry];
-
- sp->tx_skbuff[entry] = NULL;
- sp->tx_ring[entry].status = cpu_to_le32(CmdSuspend | CmdMulticastList);
- sp->tx_ring[entry].link =
- cpu_to_le32(TX_RING_ELEM_DMA(sp, (entry + 1) % TX_RING_SIZE));
- sp->tx_ring[entry].tx_desc_addr = 0; /* Really MC list count. */
- setup_params = (__le16 *)&sp->tx_ring[entry].tx_desc_addr;
- *setup_params++ = cpu_to_le16(dev->mc_count*6);
- /* Fill in the multicast addresses. */
- for (i = 0, mclist = dev->mc_list; i < dev->mc_count;
- i++, mclist = mclist->next) {
- eaddrs = (__le16 *)mclist->dmi_addr;
- *setup_params++ = *eaddrs++;
- *setup_params++ = *eaddrs++;
- *setup_params++ = *eaddrs++;
- }
-
- wait_for_cmd_done(dev, sp);
- clear_suspend(last_cmd);
- /* Immediately trigger the command unit resume. */
- iowrite8(CUResume, ioaddr + SCBCmd);
-
- if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
- netif_stop_queue(dev);
- sp->tx_full = 1;
- }
- spin_unlock_irqrestore(&sp->lock, flags);
- } else if (new_rx_mode == 0) {
- struct dev_mc_list *mclist;
- __le16 *setup_params, *eaddrs;
- struct speedo_mc_block *mc_blk;
- struct descriptor *mc_setup_frm;
- int i;
-
- mc_blk = kmalloc(sizeof(*mc_blk) + 2 + multicast_filter_limit*6,
- GFP_ATOMIC);
- if (mc_blk == NULL) {
- printk(KERN_ERR "%s: Failed to allocate a setup frame.\n",
- dev->name);
- sp->rx_mode = -1; /* We failed, try again. */
- return;
- }
- mc_blk->next = NULL;
- mc_blk->len = 2 + multicast_filter_limit*6;
- mc_blk->frame_dma =
- pci_map_single(sp->pdev, &mc_blk->frame, mc_blk->len,
- PCI_DMA_TODEVICE);
- mc_setup_frm = &mc_blk->frame;
-
- /* Fill the setup frame. */
- if (netif_msg_ifup(sp))
- printk(KERN_DEBUG "%s: Constructing a setup frame at %p.\n",
- dev->name, mc_setup_frm);
- mc_setup_frm->cmd_status =
- cpu_to_le32(CmdSuspend | CmdIntr | CmdMulticastList);
- /* Link set below. */
- setup_params = (__le16 *)&mc_setup_frm->params;
- *setup_params++ = cpu_to_le16(dev->mc_count*6);
- /* Fill in the multicast addresses. */
- for (i = 0, mclist = dev->mc_list; i < dev->mc_count;
- i++, mclist = mclist->next) {
- eaddrs = (__le16 *)mclist->dmi_addr;
- *setup_params++ = *eaddrs++;
- *setup_params++ = *eaddrs++;
- *setup_params++ = *eaddrs++;
- }
-
- /* Disable interrupts while playing with the Tx Cmd list. */
- spin_lock_irqsave(&sp->lock, flags);
-
- if (sp->mc_setup_tail)
- sp->mc_setup_tail->next = mc_blk;
- else
- sp->mc_setup_head = mc_blk;
- sp->mc_setup_tail = mc_blk;
- mc_blk->tx = sp->cur_tx;
-
- entry = sp->cur_tx++ % TX_RING_SIZE;
- last_cmd = sp->last_cmd;
- sp->last_cmd = mc_setup_frm;
-
- /* Change the command to a NoOp, pointing to the CmdMulti command. */
- sp->tx_skbuff[entry] = NULL;
- sp->tx_ring[entry].status = cpu_to_le32(CmdNOp);
- sp->tx_ring[entry].link = cpu_to_le32(mc_blk->frame_dma);
-
- /* Set the link in the setup frame. */
- mc_setup_frm->link =
- cpu_to_le32(TX_RING_ELEM_DMA(sp, (entry + 1) % TX_RING_SIZE));
-
- pci_dma_sync_single_for_device(sp->pdev, mc_blk->frame_dma,
- mc_blk->len, PCI_DMA_TODEVICE);
-
- wait_for_cmd_done(dev, sp);
- clear_suspend(last_cmd);
- /* Immediately trigger the command unit resume. */
- iowrite8(CUResume, ioaddr + SCBCmd);
-
- if ((int)(sp->cur_tx - sp->dirty_tx) >= TX_QUEUE_LIMIT) {
- netif_stop_queue(dev);
- sp->tx_full = 1;
- }
- spin_unlock_irqrestore(&sp->lock, flags);
-
- if (netif_msg_rx_status(sp))
- printk(" CmdMCSetup frame length %d in entry %d.\n",
- dev->mc_count, entry);
- }
-
- sp->rx_mode = new_rx_mode;
-}
-
-#ifdef CONFIG_PM
-static int eepro100_suspend(struct pci_dev *pdev, pm_message_t state)
-{
- struct net_device *dev = pci_get_drvdata (pdev);
- struct speedo_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->regs;
-
- pci_save_state(pdev);
-
- if (!netif_running(dev))
- return 0;
-
- del_timer_sync(&sp->timer);
-
- netif_device_detach(dev);
- iowrite32(PortPartialReset, ioaddr + SCBPort);
-
- /* XXX call pci_set_power_state ()? */
- pci_disable_device(pdev);
- pci_set_power_state (pdev, PCI_D3hot);
- return 0;
-}
-
-static int eepro100_resume(struct pci_dev *pdev)
-{
- struct net_device *dev = pci_get_drvdata (pdev);
- struct speedo_private *sp = netdev_priv(dev);
- void __iomem *ioaddr = sp->regs;
- int rc;
-
- pci_set_power_state(pdev, PCI_D0);
- pci_restore_state(pdev);
-
- rc = pci_enable_device(pdev);
- if (rc)
- return rc;
-
- pci_set_master(pdev);
-
- if (!netif_running(dev))
- return 0;
-
- /* I'm absolutely uncertain if this part of code may work.
- The problems are:
- - correct hardware reinitialization;
- - correct driver behavior between different steps of the
- reinitialization;
- - serialization with other driver calls.
- 2000/03/08 SAW */
- iowrite16(SCBMaskAll, ioaddr + SCBCmd);
- speedo_resume(dev);
- netif_device_attach(dev);
- sp->rx_mode = -1;
- sp->flow_ctrl = sp->partner = 0;
- set_rx_mode(dev);
- sp->timer.expires = RUN_AT(2*HZ);
- add_timer(&sp->timer);
- return 0;
-}
-#endif /* CONFIG_PM */
-
-static void __devexit eepro100_remove_one (struct pci_dev *pdev)
-{
- struct net_device *dev = pci_get_drvdata (pdev);
- struct speedo_private *sp = netdev_priv(dev);
-
- unregister_netdev(dev);
-
- release_region(pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));
- release_mem_region(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0));
-
- pci_iounmap(pdev, sp->regs);
- pci_free_consistent(pdev, TX_RING_SIZE * sizeof(struct TxFD)
- + sizeof(struct speedo_stats),
- sp->tx_ring, sp->tx_ring_dma);
- pci_disable_device(pdev);
- free_netdev(dev);
-}
-
-static struct pci_device_id eepro100_pci_tbl[] = {
- { PCI_VENDOR_ID_INTEL, 0x1229, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x1209, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x1029, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x1030, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x1031, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x1032, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x1033, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x1034, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x1035, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x1036, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x1037, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x1038, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x1039, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x103A, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x103B, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x103C, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x103D, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x103E, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x1050, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x1059, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x1227, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x2449, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x2459, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x245D, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x5200, PCI_ANY_ID, PCI_ANY_ID, },
- { PCI_VENDOR_ID_INTEL, 0x5201, PCI_ANY_ID, PCI_ANY_ID, },
- { 0,}
-};
-MODULE_DEVICE_TABLE(pci, eepro100_pci_tbl);
-
-static struct pci_driver eepro100_driver = {
- .name = "eepro100",
- .id_table = eepro100_pci_tbl,
- .probe = eepro100_init_one,
- .remove = __devexit_p(eepro100_remove_one),
-#ifdef CONFIG_PM
- .suspend = eepro100_suspend,
- .resume = eepro100_resume,
-#endif /* CONFIG_PM */
-};
-
-static int __init eepro100_init_module(void)
-{
-#ifdef MODULE
- printk(version);
-#endif
- return pci_register_driver(&eepro100_driver);
-}
-
-static void __exit eepro100_cleanup_module(void)
-{
- pci_unregister_driver(&eepro100_driver);
-}
-
-module_init(eepro100_init_module);
-module_exit(eepro100_cleanup_module);
-
-/*
- * Local variables:
- * compile-command: "gcc -DMODULE -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -c eepro100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
- * c-indent-level: 4
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
diff --git a/drivers/net/eexpress.c b/drivers/net/eexpress.c
index b751c1b96cfa..9ff3f2f5e382 100644
--- a/drivers/net/eexpress.c
+++ b/drivers/net/eexpress.c
@@ -967,7 +967,6 @@ static void eexp_hw_rx_pio(struct net_device *dev)
insw(ioaddr+DATAPORT, skb_put(skb,pkt_len),(pkt_len+1)>>1);
skb->protocol = eth_type_trans(skb,dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
}
@@ -1047,7 +1046,7 @@ static void eexp_hw_tx_pio(struct net_device *dev, unsigned short *buf,
/*
* Sanity check the suspected EtherExpress card
* Read hardware address, reset card, size memory and initialize buffer
- * memory pointers. These are held in dev->priv, in case someone has more
+ * memory pointers. These are held in netdev_priv(), in case someone has more
* than one card in a machine.
*/
diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
index 002d918fb4c7..9930d5f8b9e1 100644
--- a/drivers/net/ehea/ehea.h
+++ b/drivers/net/ehea/ehea.h
@@ -40,7 +40,7 @@
#include <asm/io.h>
#define DRV_NAME "ehea"
-#define DRV_VERSION "EHEA_0095"
+#define DRV_VERSION "EHEA_0096"
/* eHEA capability flags */
#define DLPAR_PORT_ADD_REM 1
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
index 422fcb93e2c3..a2f1905a23df 100644
--- a/drivers/net/ehea/ehea_main.c
+++ b/drivers/net/ehea/ehea_main.c
@@ -728,7 +728,6 @@ static int ehea_proc_rwqes(struct net_device *dev,
}
ehea_proc_skb(pr, cqe, skb);
- dev->last_rx = jiffies;
} else {
pr->p_stats.poll_receive_errors++;
port_reset = ehea_treat_poll_error(pr, rq, cqe,
@@ -831,7 +830,7 @@ static int ehea_poll(struct napi_struct *napi, int budget)
while ((rx != budget) || force_irq) {
pr->poll_counter = 0;
force_irq = 0;
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
ehea_reset_cq_ep(pr->recv_cq);
ehea_reset_cq_ep(pr->send_cq);
ehea_reset_cq_n1(pr->recv_cq);
@@ -842,7 +841,7 @@ static int ehea_poll(struct napi_struct *napi, int budget)
if (!cqe && !cqe_skb)
return rx;
- if (!netif_rx_reschedule(dev, napi))
+ if (!netif_rx_reschedule(napi))
return rx;
cqe_skb = ehea_proc_cqes(pr, EHEA_POLL_MAX_CQES);
@@ -860,7 +859,7 @@ static void ehea_netpoll(struct net_device *dev)
int i;
for (i = 0; i < port->num_def_qps; i++)
- netif_rx_schedule(dev, &port->port_res[i].napi);
+ netif_rx_schedule(&port->port_res[i].napi);
}
#endif
@@ -868,7 +867,7 @@ static irqreturn_t ehea_recv_irq_handler(int irq, void *param)
{
struct ehea_port_res *pr = param;
- netif_rx_schedule(pr->port->netdev, &pr->napi);
+ netif_rx_schedule(&pr->napi);
return IRQ_HANDLED;
}
diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c
index 9d006878f045..225c692b5d99 100644
--- a/drivers/net/ehea/ehea_qmr.c
+++ b/drivers/net/ehea/ehea_qmr.c
@@ -182,7 +182,7 @@ struct ehea_cq *ehea_create_cq(struct ehea_adapter *adapter,
goto out_kill_hwq;
}
} else {
- if ((hret != H_PAGE_REGISTERED) || (!vpage)) {
+ if (hret != H_PAGE_REGISTERED) {
ehea_error("CQ: registration of page failed "
"hret=%lx\n", hret);
goto out_kill_hwq;
@@ -303,7 +303,7 @@ struct ehea_eq *ehea_create_eq(struct ehea_adapter *adapter,
goto out_kill_hwq;
} else {
- if ((hret != H_PAGE_REGISTERED) || (!vpage))
+ if (hret != H_PAGE_REGISTERED)
goto out_kill_hwq;
}
@@ -653,7 +653,7 @@ static int ehea_update_busmap(unsigned long pfn, unsigned long nr_pages, int add
int top = ehea_calc_index(i, EHEA_TOP_INDEX_SHIFT);
int dir = ehea_calc_index(i, EHEA_DIR_INDEX_SHIFT);
int idx = i & EHEA_INDEX_MASK;
-
+
if (add) {
int ret = ehea_init_bmap(ehea_bmap, top, dir);
if (ret)
@@ -780,7 +780,7 @@ void ehea_destroy_busmap(void)
kfree(ehea_bmap);
ehea_bmap = NULL;
-out_destroy:
+out_destroy:
mutex_unlock(&ehea_busmap_mutex);
}
@@ -858,10 +858,10 @@ static u64 ehea_reg_mr_sections(int top, int dir, u64 *pt,
for (idx = 0; idx < EHEA_MAP_ENTRIES; idx++) {
if (!ehea_bmap->top[top]->dir[dir]->ent[idx])
continue;
-
+
hret = ehea_reg_mr_section(top, dir, idx, pt, adapter, mr);
if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED))
- return hret;
+ return hret;
}
return hret;
}
@@ -879,7 +879,7 @@ static u64 ehea_reg_mr_dir_sections(int top, u64 *pt,
hret = ehea_reg_mr_sections(top, dir, pt, adapter, mr);
if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED))
- return hret;
+ return hret;
}
return hret;
}
@@ -893,7 +893,7 @@ int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr)
unsigned long top;
- pt = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ pt = (void *)get_zeroed_page(GFP_KERNEL);
if (!pt) {
ehea_error("no mem");
ret = -ENOMEM;
@@ -937,7 +937,7 @@ int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr)
mr->adapter = adapter;
ret = 0;
out:
- kfree(pt);
+ free_page((unsigned long)pt);
return ret;
}
diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c
index c414554ac321..b0ef46c51a9d 100644
--- a/drivers/net/enc28j60.c
+++ b/drivers/net/enc28j60.c
@@ -196,16 +196,32 @@ static void enc28j60_soft_reset(struct enc28j60_net *priv)
*/
static void enc28j60_set_bank(struct enc28j60_net *priv, u8 addr)
{
- if ((addr & BANK_MASK) != priv->bank) {
- u8 b = (addr & BANK_MASK) >> 5;
+ u8 b = (addr & BANK_MASK) >> 5;
- if (b != (ECON1_BSEL1 | ECON1_BSEL0))
+ /* These registers (EIE, EIR, ESTAT, ECON2, ECON1)
+ * are present in all banks, no need to switch bank
+ */
+ if (addr >= EIE && addr <= ECON1)
+ return;
+
+ /* Clear or set each bank selection bit as needed */
+ if ((b & ECON1_BSEL0) != (priv->bank & ECON1_BSEL0)) {
+ if (b & ECON1_BSEL0)
+ spi_write_op(priv, ENC28J60_BIT_FIELD_SET, ECON1,
+ ECON1_BSEL0);
+ else
spi_write_op(priv, ENC28J60_BIT_FIELD_CLR, ECON1,
- ECON1_BSEL1 | ECON1_BSEL0);
- if (b != 0)
- spi_write_op(priv, ENC28J60_BIT_FIELD_SET, ECON1, b);
- priv->bank = (addr & BANK_MASK);
+ ECON1_BSEL0);
}
+ if ((b & ECON1_BSEL1) != (priv->bank & ECON1_BSEL1)) {
+ if (b & ECON1_BSEL1)
+ spi_write_op(priv, ENC28J60_BIT_FIELD_SET, ECON1,
+ ECON1_BSEL1);
+ else
+ spi_write_op(priv, ENC28J60_BIT_FIELD_CLR, ECON1,
+ ECON1_BSEL1);
+ }
+ priv->bank = b;
}
/*
@@ -477,12 +493,10 @@ static int enc28j60_set_hw_macaddr(struct net_device *ndev)
mutex_lock(&priv->lock);
if (!priv->hw_enable) {
- if (netif_msg_drv(priv)) {
- DECLARE_MAC_BUF(mac);
+ if (netif_msg_drv(priv))
printk(KERN_INFO DRV_NAME
- ": %s: Setting MAC address to %s\n",
- ndev->name, print_mac(mac, ndev->dev_addr));
- }
+ ": %s: Setting MAC address to %pM\n",
+ ndev->name, ndev->dev_addr);
/* NOTE: MAC address in ENC28J60 is byte-backward */
nolock_regb_write(priv, MAADR5, ndev->dev_addr[0]);
nolock_regb_write(priv, MAADR4, ndev->dev_addr[1]);
@@ -958,8 +972,7 @@ static void enc28j60_hw_rx(struct net_device *ndev)
/* update statistics */
ndev->stats.rx_packets++;
ndev->stats.rx_bytes += len;
- ndev->last_rx = jiffies;
- netif_rx(skb);
+ netif_rx_ni(skb);
}
}
/*
@@ -1340,11 +1353,9 @@ static int enc28j60_net_open(struct net_device *dev)
printk(KERN_DEBUG DRV_NAME ": %s() enter\n", __func__);
if (!is_valid_ether_addr(dev->dev_addr)) {
- if (netif_msg_ifup(priv)) {
- DECLARE_MAC_BUF(mac);
- dev_err(&dev->dev, "invalid MAC address %s\n",
- print_mac(mac, dev->dev_addr));
- }
+ if (netif_msg_ifup(priv))
+ dev_err(&dev->dev, "invalid MAC address %pM\n",
+ dev->dev_addr);
return -EADDRNOTAVAIL;
}
/* Reset the hardware here (and take it out of low power mode) */
@@ -1465,7 +1476,7 @@ enc28j60_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
strlcpy(info->bus_info,
- dev->dev.parent->bus_id, sizeof(info->bus_info));
+ dev_name(dev->dev.parent), sizeof(info->bus_info));
}
static int
diff --git a/drivers/net/enic/cq_desc.h b/drivers/net/enic/cq_desc.h
index c036a8bfd043..1eb289f773bf 100644
--- a/drivers/net/enic/cq_desc.h
+++ b/drivers/net/enic/cq_desc.h
@@ -44,9 +44,10 @@ struct cq_desc {
u8 type_color;
};
-#define CQ_DESC_TYPE_BITS 7
+#define CQ_DESC_TYPE_BITS 4
#define CQ_DESC_TYPE_MASK ((1 << CQ_DESC_TYPE_BITS) - 1)
#define CQ_DESC_COLOR_MASK 1
+#define CQ_DESC_COLOR_SHIFT 7
#define CQ_DESC_Q_NUM_BITS 10
#define CQ_DESC_Q_NUM_MASK ((1 << CQ_DESC_Q_NUM_BITS) - 1)
#define CQ_DESC_COMP_NDX_BITS 12
@@ -58,7 +59,7 @@ static inline void cq_desc_dec(const struct cq_desc *desc_arg,
const struct cq_desc *desc = desc_arg;
const u8 type_color = desc->type_color;
- *color = (type_color >> CQ_DESC_TYPE_BITS) & CQ_DESC_COLOR_MASK;
+ *color = (type_color >> CQ_DESC_COLOR_SHIFT) & CQ_DESC_COLOR_MASK;
/*
* Make sure color bit is read from desc *before* other fields
diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h
index 7f677e89a788..a832cc5d6a1e 100644
--- a/drivers/net/enic/enic.h
+++ b/drivers/net/enic/enic.h
@@ -33,7 +33,7 @@
#define DRV_NAME "enic"
#define DRV_DESCRIPTION "Cisco 10G Ethernet Driver"
-#define DRV_VERSION "0.0.1-18163.472-k1"
+#define DRV_VERSION "1.0.0.648"
#define DRV_COPYRIGHT "Copyright 2008 Cisco Systems, Inc"
#define PFX DRV_NAME ": "
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c
index 180e968dc54d..d039e16f2763 100644
--- a/drivers/net/enic/enic_main.c
+++ b/drivers/net/enic/enic_main.c
@@ -273,6 +273,8 @@ static struct ethtool_ops enic_ethtool_ops = {
.set_sg = ethtool_op_set_sg,
.get_tso = ethtool_op_get_tso,
.set_tso = enic_set_tso,
+ .get_flags = ethtool_op_get_flags,
+ .set_flags = ethtool_op_set_flags,
};
static void enic_free_wq_buf(struct vnic_wq *wq, struct vnic_wq_buf *buf)
@@ -409,8 +411,8 @@ static irqreturn_t enic_isr_legacy(int irq, void *data)
}
if (ENIC_TEST_INTR(pba, ENIC_INTX_WQ_RQ)) {
- if (netif_rx_schedule_prep(netdev, &enic->napi))
- __netif_rx_schedule(netdev, &enic->napi);
+ if (netif_rx_schedule_prep(&enic->napi))
+ __netif_rx_schedule(&enic->napi);
} else {
vnic_intr_unmask(&enic->intr[ENIC_INTX_WQ_RQ]);
}
@@ -438,7 +440,7 @@ static irqreturn_t enic_isr_msi(int irq, void *data)
* writes).
*/
- netif_rx_schedule(enic->netdev, &enic->napi);
+ netif_rx_schedule(&enic->napi);
return IRQ_HANDLED;
}
@@ -448,7 +450,7 @@ static irqreturn_t enic_isr_msix_rq(int irq, void *data)
struct enic *enic = data;
/* schedule NAPI polling for RQ cleanup */
- netif_rx_schedule(enic->netdev, &enic->napi);
+ netif_rx_schedule(&enic->napi);
return IRQ_HANDLED;
}
@@ -895,6 +897,7 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
int skipped, void *opaque)
{
struct enic *enic = vnic_dev_priv(rq->vdev);
+ struct net_device *netdev = enic->netdev;
struct sk_buff *skb;
u8 type, color, eop, sop, ingress_port, vlan_stripped;
@@ -929,7 +932,7 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
if (net_ratelimit())
printk(KERN_ERR PFX
"%s: packet error: bad FCS\n",
- enic->netdev->name);
+ netdev->name);
}
dev_kfree_skb_any(skb);
@@ -943,19 +946,18 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
*/
skb_put(skb, bytes_written);
- skb->protocol = eth_type_trans(skb, enic->netdev);
+ skb->protocol = eth_type_trans(skb, netdev);
if (enic->csum_rx_enabled && !csum_not_calc) {
skb->csum = htons(checksum);
skb->ip_summed = CHECKSUM_COMPLETE;
}
- skb->dev = enic->netdev;
- enic->netdev->last_rx = jiffies;
+ skb->dev = netdev;
if (enic->vlan_group && vlan_stripped) {
- if (ENIC_SETTING(enic, LRO) && ipv4)
+ if ((netdev->features & NETIF_F_LRO) && ipv4)
lro_vlan_hwaccel_receive_skb(&enic->lro_mgr,
skb, enic->vlan_group,
vlan, cq_desc);
@@ -965,7 +967,7 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
} else {
- if (ENIC_SETTING(enic, LRO) && ipv4)
+ if ((netdev->features & NETIF_F_LRO) && ipv4)
lro_receive_skb(&enic->lro_mgr, skb, cq_desc);
else
netif_receive_skb(skb);
@@ -1063,10 +1065,10 @@ static int enic_poll(struct napi_struct *napi, int budget)
/* If no work done, flush all LROs and exit polling
*/
- if (ENIC_SETTING(enic, LRO))
+ if (netdev->features & NETIF_F_LRO)
lro_flush_all(&enic->lro_mgr);
- netif_rx_complete(netdev, napi);
+ netif_rx_complete(napi);
vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]);
}
@@ -1107,10 +1109,10 @@ static int enic_poll_msix(struct napi_struct *napi, int budget)
/* If no work done, flush all LROs and exit polling
*/
- if (ENIC_SETTING(enic, LRO))
+ if (netdev->features & NETIF_F_LRO)
lro_flush_all(&enic->lro_mgr);
- netif_rx_complete(netdev, napi);
+ netif_rx_complete(napi);
vnic_intr_unmask(&enic->intr[ENIC_MSIX_RQ]);
}
@@ -1591,6 +1593,23 @@ static void enic_iounmap(struct enic *enic)
iounmap(enic->bar0.vaddr);
}
+static const struct net_device_ops enic_netdev_ops = {
+ .ndo_open = enic_open,
+ .ndo_stop = enic_stop,
+ .ndo_start_xmit = enic_hard_start_xmit,
+ .ndo_get_stats = enic_get_stats,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_multicast_list = enic_set_multicast_list,
+ .ndo_change_mtu = enic_change_mtu,
+ .ndo_vlan_rx_register = enic_vlan_rx_register,
+ .ndo_vlan_rx_add_vid = enic_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = enic_vlan_rx_kill_vid,
+ .ndo_tx_timeout = enic_tx_timeout,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = enic_poll_controller,
+#endif
+};
+
static int __devinit enic_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -1746,13 +1765,13 @@ static int __devinit enic_probe(struct pci_dev *pdev,
}
/* Get available resource counts
- */
+ */
enic_get_res_counts(enic);
/* Set interrupt mode based on resource counts and system
* capabilities
- */
+ */
err = enic_set_intr_mode(enic);
if (err) {
@@ -1814,21 +1833,9 @@ static int __devinit enic_probe(struct pci_dev *pdev,
goto err_out_free_vnic_resources;
}
- netdev->open = enic_open;
- netdev->stop = enic_stop;
- netdev->hard_start_xmit = enic_hard_start_xmit;
- netdev->get_stats = enic_get_stats;
- netdev->set_multicast_list = enic_set_multicast_list;
- netdev->change_mtu = enic_change_mtu;
- netdev->vlan_rx_register = enic_vlan_rx_register;
- netdev->vlan_rx_add_vid = enic_vlan_rx_add_vid;
- netdev->vlan_rx_kill_vid = enic_vlan_rx_kill_vid;
- netdev->tx_timeout = enic_tx_timeout;
+ netdev->netdev_ops = &enic_netdev_ops;
netdev->watchdog_timeo = 2 * HZ;
netdev->ethtool_ops = &enic_ethtool_ops;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- netdev->poll_controller = enic_poll_controller;
-#endif
switch (vnic_dev_get_intr_mode(enic->vdev)) {
default:
@@ -1845,22 +1852,23 @@ static int __devinit enic_probe(struct pci_dev *pdev,
if (ENIC_SETTING(enic, TSO))
netdev->features |= NETIF_F_TSO |
NETIF_F_TSO6 | NETIF_F_TSO_ECN;
+ if (ENIC_SETTING(enic, LRO))
+ netdev->features |= NETIF_F_LRO;
if (using_dac)
netdev->features |= NETIF_F_HIGHDMA;
enic->csum_rx_enabled = ENIC_SETTING(enic, RXCSUM);
- if (ENIC_SETTING(enic, LRO)) {
- enic->lro_mgr.max_aggr = ENIC_LRO_MAX_AGGR;
- enic->lro_mgr.max_desc = ENIC_LRO_MAX_DESC;
- enic->lro_mgr.lro_arr = enic->lro_desc;
- enic->lro_mgr.get_skb_header = enic_get_skb_header;
- enic->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;
- enic->lro_mgr.dev = netdev;
- enic->lro_mgr.ip_summed = CHECKSUM_COMPLETE;
- enic->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
- }
+ enic->lro_mgr.max_aggr = ENIC_LRO_MAX_AGGR;
+ enic->lro_mgr.max_desc = ENIC_LRO_MAX_DESC;
+ enic->lro_mgr.lro_arr = enic->lro_desc;
+ enic->lro_mgr.get_skb_header = enic_get_skb_header;
+ enic->lro_mgr.features = LRO_F_NAPI | LRO_F_EXTRACT_VLAN_ID;
+ enic->lro_mgr.dev = netdev;
+ enic->lro_mgr.ip_summed = CHECKSUM_COMPLETE;
+ enic->lro_mgr.ip_summed_aggr = CHECKSUM_UNNECESSARY;
+
err = register_netdev(netdev);
if (err) {
diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c
index 95184b9108ef..e5fc9384f8f5 100644
--- a/drivers/net/enic/enic_res.c
+++ b/drivers/net/enic/enic_res.c
@@ -90,11 +90,8 @@ int enic_get_vnic_config(struct enic *enic)
c->intr_timer = min_t(u16, VNIC_INTR_TIMER_MAX, c->intr_timer);
- printk(KERN_INFO PFX "vNIC MAC addr %02x:%02x:%02x:%02x:%02x:%02x "
- "wq/rq %d/%d\n",
- enic->mac_addr[0], enic->mac_addr[1], enic->mac_addr[2],
- enic->mac_addr[3], enic->mac_addr[4], enic->mac_addr[5],
- c->wq_desc_count, c->rq_desc_count);
+ printk(KERN_INFO PFX "vNIC MAC addr %pM wq/rq %d/%d\n",
+ enic->mac_addr, c->wq_desc_count, c->rq_desc_count);
printk(KERN_INFO PFX "vNIC mtu %d csum tx/rx %d/%d tso/lro %d/%d "
"intr timer %d\n",
c->mtu, ENIC_SETTING(enic, TXCSUM),
diff --git a/drivers/net/enic/enic_res.h b/drivers/net/enic/enic_res.h
index 68534a29b7ac..7bf272fa859b 100644
--- a/drivers/net/enic/enic_res.h
+++ b/drivers/net/enic/enic_res.h
@@ -58,8 +58,6 @@ static inline void enic_queue_wq_desc_ex(struct vnic_wq *wq,
(u16)vlan_tag,
0 /* loopback */);
- wmb();
-
vnic_wq_post(wq, os_buf, dma_addr, len, sop, eop);
}
@@ -127,8 +125,6 @@ static inline void enic_queue_rq_desc(struct vnic_rq *rq,
(u64)dma_addr | VNIC_PADDR_TARGET,
type, (u16)len);
- wmb();
-
vnic_rq_post(rq, os_buf, os_buf_index, dma_addr, len);
}
diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c
index 4d104f5c30f9..11708579b6ce 100644
--- a/drivers/net/enic/vnic_dev.c
+++ b/drivers/net/enic/vnic_dev.c
@@ -43,6 +43,7 @@ struct vnic_dev {
struct vnic_devcmd_notify *notify;
struct vnic_devcmd_notify notify_copy;
dma_addr_t notify_pa;
+ u32 notify_sz;
u32 *linkstatus;
dma_addr_t linkstatus_pa;
struct vnic_stats *stats;
@@ -235,14 +236,6 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
struct vnic_devcmd __iomem *devcmd = vdev->devcmd;
int delay;
u32 status;
- int dev_cmd_err[] = {
- /* convert from fw's version of error.h to host's version */
- 0, /* ERR_SUCCESS */
- EINVAL, /* ERR_EINVAL */
- EFAULT, /* ERR_EFAULT */
- EPERM, /* ERR_EPERM */
- EBUSY, /* ERR_EBUSY */
- };
int err;
status = ioread32(&devcmd->status);
@@ -270,10 +263,12 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
if (!(status & STAT_BUSY)) {
if (status & STAT_ERROR) {
- err = dev_cmd_err[(int)readq(&devcmd->args[0])];
- printk(KERN_ERR "Error %d devcmd %d\n",
- err, _CMD_N(cmd));
- return -err;
+ err = (int)readq(&devcmd->args[0]);
+ if (err != ERR_ECMDUNKNOWN ||
+ cmd != CMD_CAPABILITY)
+ printk(KERN_ERR "Error %d devcmd %d\n",
+ err, _CMD_N(cmd));
+ return err;
}
if (_CMD_DIR(cmd) & _CMD_DIR_READ) {
@@ -290,6 +285,17 @@ int vnic_dev_cmd(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd,
return -ETIMEDOUT;
}
+static int vnic_dev_capable(struct vnic_dev *vdev, enum vnic_devcmd_cmd cmd)
+{
+ u64 a0 = (u32)cmd, a1 = 0;
+ int wait = 1000;
+ int err;
+
+ err = vnic_dev_cmd(vdev, CMD_CAPABILITY, &a0, &a1, wait);
+
+ return !(err || a0);
+}
+
int vnic_dev_fw_info(struct vnic_dev *vdev,
struct vnic_devcmd_fw_info **fw_info)
{
@@ -489,10 +495,7 @@ void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr)
err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
if (err)
- printk(KERN_ERR
- "Can't add addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n",
- addr[0], addr[1], addr[2], addr[3], addr[4], addr[5],
- err);
+ printk(KERN_ERR "Can't add addr [%pM], %d\n", addr, err);
}
void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr)
@@ -507,16 +510,14 @@ void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr)
err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait);
if (err)
- printk(KERN_ERR
- "Can't del addr [%02x:%02x:%02x:%02x:%02x:%02x], %d\n",
- addr[0], addr[1], addr[2], addr[3], addr[4], addr[5],
- err);
+ printk(KERN_ERR "Can't del addr [%pM], %d\n", addr, err);
}
int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr)
{
u64 a0, a1;
int wait = 1000;
+ int r;
if (!vdev->notify) {
vdev->notify = pci_alloc_consistent(vdev->pdev,
@@ -524,13 +525,16 @@ int vnic_dev_notify_set(struct vnic_dev *vdev, u16 intr)
&vdev->notify_pa);
if (!vdev->notify)
return -ENOMEM;
+ memset(vdev->notify, 0, sizeof(struct vnic_devcmd_notify));
}
a0 = vdev->notify_pa;
a1 = ((u64)intr << 32) & 0x0000ffff00000000ULL;
a1 += sizeof(struct vnic_devcmd_notify);
- return vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
+ r = vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
+ vdev->notify_sz = (r == 0) ? (u32)a1 : 0;
+ return r;
}
void vnic_dev_notify_unset(struct vnic_dev *vdev)
@@ -543,22 +547,22 @@ void vnic_dev_notify_unset(struct vnic_dev *vdev)
a1 += sizeof(struct vnic_devcmd_notify);
vnic_dev_cmd(vdev, CMD_NOTIFY, &a0, &a1, wait);
+ vdev->notify_sz = 0;
}
static int vnic_dev_notify_ready(struct vnic_dev *vdev)
{
u32 *words;
- unsigned int nwords = sizeof(struct vnic_devcmd_notify) / 4;
+ unsigned int nwords = vdev->notify_sz / 4;
unsigned int i;
u32 csum;
- if (!vdev->notify)
+ if (!vdev->notify || !vdev->notify_sz)
return 0;
do {
csum = 0;
- memcpy(&vdev->notify_copy, vdev->notify,
- sizeof(struct vnic_devcmd_notify));
+ memcpy(&vdev->notify_copy, vdev->notify, vdev->notify_sz);
words = (u32 *)&vdev->notify_copy;
for (i = 1; i < nwords; i++)
csum += words[i];
@@ -571,7 +575,20 @@ int vnic_dev_init(struct vnic_dev *vdev, int arg)
{
u64 a0 = (u32)arg, a1 = 0;
int wait = 1000;
- return vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait);
+ int r = 0;
+
+ if (vnic_dev_capable(vdev, CMD_INIT))
+ r = vnic_dev_cmd(vdev, CMD_INIT, &a0, &a1, wait);
+ else {
+ vnic_dev_cmd(vdev, CMD_INIT_v1, &a0, &a1, wait);
+ if (a0 & CMD_INITF_DEFAULT_MAC) {
+ // Emulate these for old CMD_INIT_v1 which
+ // didn't pass a0 so no CMD_INITF_*.
+ vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait);
+ vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
+ }
+ }
+ return r;
}
int vnic_dev_link_status(struct vnic_dev *vdev)
@@ -672,3 +689,4 @@ err_out:
return NULL;
}
+
diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/enic/vnic_devcmd.h
index d8617a3373b1..8062c75154e6 100644
--- a/drivers/net/enic/vnic_devcmd.h
+++ b/drivers/net/enic/vnic_devcmd.h
@@ -168,7 +168,8 @@ enum vnic_devcmd_cmd {
CMD_CLOSE = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 25),
/* initialize virtual link: (u32)a0=flags (see CMD_INITF_*) */
- CMD_INIT = _CMDCNW(_CMD_DIR_READ, _CMD_VTYPE_ALL, 26),
+/***** Replaced by CMD_INIT *****/
+ CMD_INIT_v1 = _CMDCNW(_CMD_DIR_READ, _CMD_VTYPE_ALL, 26),
/* variant of CMD_INIT, with provisioning info
* (u64)a0=paddr of vnic_devcmd_provinfo
@@ -198,6 +199,14 @@ enum vnic_devcmd_cmd {
/* undo initialize of virtual link */
CMD_DEINIT = _CMDCNW(_CMD_DIR_NONE, _CMD_VTYPE_ALL, 34),
+
+ /* initialize virtual link: (u32)a0=flags (see CMD_INITF_*) */
+ CMD_INIT = _CMDCNW(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 35),
+
+ /* check fw capability of a cmd:
+ * in: (u32)a0=cmd
+ * out: (u32)a0=errno, 0:valid cmd, a1=supported VNIC_STF_* bits */
+ CMD_CAPABILITY = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 36),
};
/* flags for CMD_OPEN */
@@ -249,8 +258,16 @@ struct vnic_devcmd_notify {
u32 uif; /* uplink interface */
u32 status; /* status bits (see VNIC_STF_*) */
u32 error; /* error code (see ERR_*) for first ERR */
+ u32 link_down_cnt; /* running count of link down transitions */
};
#define VNIC_STF_FATAL_ERR 0x0001 /* fatal fw error */
+#define VNIC_STF_STD_PAUSE 0x0002 /* standard link-level pause on */
+#define VNIC_STF_PFC_PAUSE 0x0004 /* priority flow control pause on */
+/* all supported status flags */
+#define VNIC_STF_ALL (VNIC_STF_FATAL_ERR |\
+ VNIC_STF_STD_PAUSE |\
+ VNIC_STF_PFC_PAUSE |\
+ 0)
struct vnic_devcmd_provinfo {
u8 oui[3];
diff --git a/drivers/net/enic/vnic_intr.h b/drivers/net/enic/vnic_intr.h
index ccc408116af8..ce633a5a7e3c 100644
--- a/drivers/net/enic/vnic_intr.h
+++ b/drivers/net/enic/vnic_intr.h
@@ -78,7 +78,7 @@ static inline void vnic_intr_return_credits(struct vnic_intr *intr,
static inline u32 vnic_intr_legacy_pba(u32 __iomem *legacy_pba)
{
- /* get and ack interrupt in one read (clear-and-ack-on-read) */
+ /* read PBA without clearing */
return ioread32(legacy_pba);
}
diff --git a/drivers/net/enic/vnic_resource.h b/drivers/net/enic/vnic_resource.h
index 144d2812f081..b61c22aec41a 100644
--- a/drivers/net/enic/vnic_resource.h
+++ b/drivers/net/enic/vnic_resource.h
@@ -38,7 +38,7 @@ enum vnic_res_type {
RES_TYPE_INTR_CTRL, /* Interrupt ctrl table */
RES_TYPE_INTR_TABLE, /* MSI/MSI-X Interrupt table */
RES_TYPE_INTR_PBA, /* MSI/MSI-X PBA table */
- RES_TYPE_INTR_PBA_LEGACY, /* Legacy intr status, r2c */
+ RES_TYPE_INTR_PBA_LEGACY, /* Legacy intr status */
RES_TYPE_RSVD6,
RES_TYPE_RSVD7,
RES_TYPE_DEVCMD, /* Device command region */
diff --git a/drivers/net/enic/vnic_rq.h b/drivers/net/enic/vnic_rq.h
index 82bfca67cc4d..fd0ef66d2e9f 100644
--- a/drivers/net/enic/vnic_rq.h
+++ b/drivers/net/enic/vnic_rq.h
@@ -132,8 +132,15 @@ static inline void vnic_rq_post(struct vnic_rq *rq,
#define VNIC_RQ_RETURN_RATE 0xf /* keep 2^n - 1 */
#endif
- if ((buf->index & VNIC_RQ_RETURN_RATE) == 0)
+ if ((buf->index & VNIC_RQ_RETURN_RATE) == 0) {
+ /* Adding write memory barrier prevents compiler and/or CPU
+ * reordering, thus avoiding descriptor posting before
+ * descriptor is initialized. Otherwise, hardware can read
+ * stale descriptor fields.
+ */
+ wmb();
iowrite32(buf->index, &rq->ctrl->posted_index);
+ }
}
static inline void vnic_rq_return_descs(struct vnic_rq *rq, unsigned int count)
diff --git a/drivers/net/enic/vnic_rss.h b/drivers/net/enic/vnic_rss.h
index e325d65d7c34..5fbb3c923bcd 100644
--- a/drivers/net/enic/vnic_rss.h
+++ b/drivers/net/enic/vnic_rss.h
@@ -1,6 +1,19 @@
/*
* Copyright 2008 Cisco Systems, Inc. All rights reserved.
* Copyright 2007 Nuova Systems, Inc. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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.
*/
#ifndef _VNIC_RSS_H_
diff --git a/drivers/net/enic/vnic_wq.h b/drivers/net/enic/vnic_wq.h
index 7081828d8a42..c826137dc651 100644
--- a/drivers/net/enic/vnic_wq.h
+++ b/drivers/net/enic/vnic_wq.h
@@ -108,8 +108,15 @@ static inline void vnic_wq_post(struct vnic_wq *wq,
buf->len = len;
buf = buf->next;
- if (eop)
+ if (eop) {
+ /* Adding write memory barrier prevents compiler and/or CPU
+ * reordering, thus avoiding descriptor posting before
+ * descriptor is initialized. Otherwise, hardware can read
+ * stale descriptor fields.
+ */
+ wmb();
iowrite32(buf->index, &wq->ctrl->posted_index);
+ }
wq->to_use = buf;
wq->ring.desc_avail--;
diff --git a/drivers/net/epic100.c b/drivers/net/epic100.c
index 76118ddd1042..f9b37c80dda6 100644
--- a/drivers/net/epic100.c
+++ b/drivers/net/epic100.c
@@ -322,7 +322,6 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
int i, ret, option = 0, duplex = 0;
void *ring_space;
dma_addr_t ring_dma;
- DECLARE_MAC_BUF(mac);
/* when built into the kernel, we only print version if device is found */
#ifndef MODULE
@@ -364,7 +363,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
ioaddr = pci_resource_start (pdev, 0);
#else
ioaddr = pci_resource_start (pdev, 1);
- ioaddr = (long) ioremap (ioaddr, pci_resource_len (pdev, 1));
+ ioaddr = (long) pci_ioremap_bar(pdev, 1);
if (!ioaddr) {
dev_err(&pdev->dev, "ioremap failed\n");
goto err_out_free_netdev;
@@ -372,7 +371,7 @@ static int __devinit epic_init_one (struct pci_dev *pdev,
#endif
pci_set_drvdata(pdev, dev);
- ep = dev->priv;
+ ep = netdev_priv(dev);
ep->mii.dev = dev;
ep->mii.mdio_read = mdio_read;
ep->mii.mdio_write = mdio_write;
@@ -499,9 +498,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, %s\n",
+ printk(KERN_INFO "%s: %s at %#lx, IRQ %d, %pM\n",
dev->name, pci_id_tbl[chip_idx].name, ioaddr, dev->irq,
- print_mac(mac, dev->dev_addr));
+ dev->dev_addr);
out:
return ret;
@@ -655,7 +654,7 @@ 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 = dev->priv;
+ struct epic_private *ep = netdev_priv(dev);
long ioaddr = dev->base_addr;
int i;
int retval;
@@ -767,7 +766,7 @@ static int epic_open(struct net_device *dev)
static void epic_pause(struct net_device *dev)
{
long ioaddr = dev->base_addr;
- struct epic_private *ep = dev->priv;
+ struct epic_private *ep = netdev_priv(dev);
netif_stop_queue (dev);
@@ -790,7 +789,7 @@ 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 = dev->priv;
+ struct epic_private *ep = netdev_priv(dev);
int i;
/* Soft reset the chip. */
@@ -842,7 +841,7 @@ static void epic_restart(struct net_device *dev)
static void check_media(struct net_device *dev)
{
- struct epic_private *ep = dev->priv;
+ struct epic_private *ep = netdev_priv(dev);
long ioaddr = dev->base_addr;
int mii_lpa = ep->mii_phy_cnt ? mdio_read(dev, ep->phys[0], MII_LPA) : 0;
int negotiated = mii_lpa & ep->mii.advertising;
@@ -864,7 +863,7 @@ static void check_media(struct net_device *dev)
static void epic_timer(unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
- struct epic_private *ep = dev->priv;
+ struct epic_private *ep = netdev_priv(dev);
long ioaddr = dev->base_addr;
int next_tick = 5*HZ;
@@ -885,7 +884,7 @@ static void epic_timer(unsigned long data)
static void epic_tx_timeout(struct net_device *dev)
{
- struct epic_private *ep = dev->priv;
+ struct epic_private *ep = netdev_priv(dev);
long ioaddr = dev->base_addr;
if (debug > 0) {
@@ -914,7 +913,7 @@ static void epic_tx_timeout(struct net_device *dev)
/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
static void epic_init_ring(struct net_device *dev)
{
- struct epic_private *ep = dev->priv;
+ struct epic_private *ep = netdev_priv(dev);
int i;
ep->tx_full = 0;
@@ -960,7 +959,7 @@ static void epic_init_ring(struct net_device *dev)
static int epic_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct epic_private *ep = dev->priv;
+ struct epic_private *ep = netdev_priv(dev);
int entry, free_count;
u32 ctrl_word;
unsigned long flags;
@@ -1088,7 +1087,7 @@ static void epic_tx(struct net_device *dev, struct epic_private *ep)
static irqreturn_t epic_interrupt(int irq, void *dev_instance)
{
struct net_device *dev = dev_instance;
- struct epic_private *ep = dev->priv;
+ struct epic_private *ep = netdev_priv(dev);
long ioaddr = dev->base_addr;
unsigned int handled = 0;
int status;
@@ -1110,9 +1109,9 @@ static irqreturn_t epic_interrupt(int irq, void *dev_instance)
if ((status & EpicNapiEvent) && !ep->reschedule_in_poll) {
spin_lock(&ep->napi_lock);
- if (netif_rx_schedule_prep(dev, &ep->napi)) {
+ if (netif_rx_schedule_prep(&ep->napi)) {
epic_napi_irq_off(dev, ep);
- __netif_rx_schedule(dev, &ep->napi);
+ __netif_rx_schedule(&ep->napi);
} else
ep->reschedule_in_poll++;
spin_unlock(&ep->napi_lock);
@@ -1156,7 +1155,7 @@ out:
static int epic_rx(struct net_device *dev, int budget)
{
- struct epic_private *ep = dev->priv;
+ struct epic_private *ep = netdev_priv(dev);
int entry = ep->cur_rx % RX_RING_SIZE;
int rx_work_limit = ep->dirty_rx + RX_RING_SIZE - ep->cur_rx;
int work_done = 0;
@@ -1223,7 +1222,6 @@ static int epic_rx(struct net_device *dev, int budget)
}
skb->protocol = eth_type_trans(skb, dev);
netif_receive_skb(skb);
- dev->last_rx = jiffies;
ep->stats.rx_packets++;
ep->stats.rx_bytes += pkt_len;
}
@@ -1290,7 +1288,7 @@ rx_action:
more = ep->reschedule_in_poll;
if (!more) {
- __netif_rx_complete(dev, napi);
+ __netif_rx_complete(napi);
outl(EpicNapiEvent, ioaddr + INTSTAT);
epic_napi_irq_on(dev, ep);
} else
@@ -1308,7 +1306,7 @@ rx_action:
static int epic_close(struct net_device *dev)
{
long ioaddr = dev->base_addr;
- struct epic_private *ep = dev->priv;
+ struct epic_private *ep = netdev_priv(dev);
struct sk_buff *skb;
int i;
@@ -1358,7 +1356,7 @@ static int epic_close(struct net_device *dev)
static struct net_device_stats *epic_get_stats(struct net_device *dev)
{
- struct epic_private *ep = dev->priv;
+ struct epic_private *ep = netdev_priv(dev);
long ioaddr = dev->base_addr;
if (netif_running(dev)) {
@@ -1379,7 +1377,7 @@ 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 = dev->priv;
+ struct epic_private *ep = netdev_priv(dev);
unsigned char mc_filter[8]; /* Multicast hash filter */
int i;
@@ -1418,7 +1416,7 @@ static void set_rx_mode(struct net_device *dev)
static void netdev_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info)
{
- struct epic_private *np = dev->priv;
+ struct epic_private *np = netdev_priv(dev);
strcpy (info->driver, DRV_NAME);
strcpy (info->version, DRV_VERSION);
@@ -1427,7 +1425,7 @@ static void netdev_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *
static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- struct epic_private *np = dev->priv;
+ struct epic_private *np = netdev_priv(dev);
int rc;
spin_lock_irq(&np->lock);
@@ -1439,7 +1437,7 @@ static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- struct epic_private *np = dev->priv;
+ struct epic_private *np = netdev_priv(dev);
int rc;
spin_lock_irq(&np->lock);
@@ -1451,13 +1449,13 @@ static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static int netdev_nway_reset(struct net_device *dev)
{
- struct epic_private *np = dev->priv;
+ struct epic_private *np = netdev_priv(dev);
return mii_nway_restart(&np->mii);
}
static u32 netdev_get_link(struct net_device *dev)
{
- struct epic_private *np = dev->priv;
+ struct epic_private *np = netdev_priv(dev);
return mii_link_ok(&np->mii);
}
@@ -1506,7 +1504,7 @@ 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 = dev->priv;
+ struct epic_private *np = netdev_priv(dev);
long ioaddr = dev->base_addr;
struct mii_ioctl_data *data = if_mii(rq);
int rc;
@@ -1534,7 +1532,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static void __devexit epic_remove_one (struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
- struct epic_private *ep = dev->priv;
+ struct epic_private *ep = netdev_priv(dev);
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);
diff --git a/drivers/net/eql.c b/drivers/net/eql.c
index 18f1364d3d5b..40125694bd9f 100644
--- a/drivers/net/eql.c
+++ b/drivers/net/eql.c
@@ -162,6 +162,13 @@ static void eql_timer(unsigned long param)
static char version[] __initdata =
"Equalizer2002: Simon Janes (simon@ncm.com) and David S. Miller (davem@redhat.com)\n";
+static const struct net_device_ops eql_netdev_ops = {
+ .ndo_open = eql_open,
+ .ndo_stop = eql_close,
+ .ndo_do_ioctl = eql_ioctl,
+ .ndo_start_xmit = eql_slave_xmit,
+};
+
static void __init eql_setup(struct net_device *dev)
{
equalizer_t *eql = netdev_priv(dev);
@@ -175,10 +182,7 @@ static void __init eql_setup(struct net_device *dev)
INIT_LIST_HEAD(&eql->queue.all_slaves);
eql->queue.master_dev = dev;
- dev->open = eql_open;
- dev->stop = eql_close;
- dev->do_ioctl = eql_ioctl;
- dev->hard_start_xmit = eql_slave_xmit;
+ dev->netdev_ops = &eql_netdev_ops;
/*
* Now we undo some of the things that eth_setup does
diff --git a/drivers/net/es3210.c b/drivers/net/es3210.c
index deefa51b8c31..5569f2ffb62c 100644
--- a/drivers/net/es3210.c
+++ b/drivers/net/es3210.c
@@ -64,9 +64,6 @@ static const char version[] =
static int es_probe1(struct net_device *dev, int ioaddr);
-static int es_open(struct net_device *dev);
-static int es_close(struct net_device *dev);
-
static void es_reset_8390(struct net_device *dev);
static void es_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page);
@@ -179,7 +176,6 @@ static int __init es_probe1(struct net_device *dev, int ioaddr)
{
int i, retval;
unsigned long eisa_id;
- DECLARE_MAC_BUF(mac);
if (!request_region(ioaddr + ES_SA_PROM, ES_IO_EXTENT, "es3210"))
return -ENODEV;
@@ -205,14 +201,14 @@ static int __init es_probe1(struct net_device *dev, int ioaddr)
if (dev->dev_addr[0] != ES_ADDR0 ||
dev->dev_addr[1] != ES_ADDR1 ||
dev->dev_addr[2] != ES_ADDR2) {
- printk("es3210.c: card not found %s (invalid_prefix).\n",
- print_mac(mac, dev->dev_addr));
+ printk("es3210.c: card not found %pM (invalid_prefix).\n",
+ dev->dev_addr);
retval = -ENODEV;
goto out;
}
- printk("es3210.c: ES3210 rev. %ld at %#x, node %s",
- eisa_id>>24, ioaddr, print_mac(mac, dev->dev_addr));
+ printk("es3210.c: ES3210 rev. %ld at %#x, node %pM",
+ eisa_id>>24, ioaddr, dev->dev_addr);
/* Snarf the interrupt now. */
if (dev->irq == 0) {
@@ -290,11 +286,7 @@ static int __init es_probe1(struct net_device *dev, int ioaddr)
ei_status.block_output = &es_block_output;
ei_status.get_8390_hdr = &es_get_8390_hdr;
- dev->open = &es_open;
- dev->stop = &es_close;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = ei_poll;
-#endif
+ dev->netdev_ops = &ei_netdev_ops;
NS8390_init(dev, 0);
retval = register_netdev(dev);
@@ -386,22 +378,6 @@ static void es_block_output(struct net_device *dev, int count,
memcpy_toio(shmem, buf, count);
}
-static int es_open(struct net_device *dev)
-{
- ei_open(dev);
- return 0;
-}
-
-static int es_close(struct net_device *dev)
-{
-
- if (ei_debug > 1)
- printk("%s: Shutting down ethercard.\n", dev->name);
-
- ei_close(dev);
- return 0;
-}
-
#ifdef MODULE
#define MAX_ES_CARDS 4 /* Max number of ES3210 cards per module */
#define NAMELEN 8 /* # of chars for storing dev->name */
diff --git a/drivers/net/eth16i.c b/drivers/net/eth16i.c
index bee8b3fbc565..5c048f2fd74f 100644
--- a/drivers/net/eth16i.c
+++ b/drivers/net/eth16i.c
@@ -1205,7 +1205,6 @@ static void eth16i_rx(struct net_device *dev)
printk(KERN_DEBUG ".\n");
}
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
@@ -1466,7 +1465,7 @@ void __exit cleanup_module(void)
for(this_dev = 0; this_dev < MAX_ETH16I_CARDS; this_dev++) {
struct net_device *dev = dev_eth16i[this_dev];
- if(dev->priv) {
+ if (netdev_priv(dev)) {
unregister_netdev(dev);
free_irq(dev->irq, dev);
release_region(dev->base_addr, ETH16I_IO_EXTENT);
@@ -1475,15 +1474,3 @@ void __exit cleanup_module(void)
}
}
#endif /* MODULE */
-
-/*
- * Local variables:
- * compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c eth16i.c"
- * alt-compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict -prototypes -O6 -c eth16i.c"
- * tab-width: 8
- * c-basic-offset: 8
- * c-indent-level: 8
- * End:
- */
-
-/* End of file eth16i.c */
diff --git a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
index 593a120e31b2..b852303c9362 100644
--- a/drivers/net/ewrk3.c
+++ b/drivers/net/ewrk3.c
@@ -396,7 +396,6 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase)
u_long mem_start, shmem_length;
u_char cr, cmr, icr, nicsr, lemac, hard_strapped = 0;
u_char eeprom_image[EEPROM_MAX], chksum, eisa_cr = 0;
- DECLARE_MAC_BUF(mac);
/*
** Stop the EWRK3. Enable the DBR ROM. Disable interrupts and remote boot.
@@ -461,7 +460,7 @@ ewrk3_hw_init(struct net_device *dev, u_long iobase)
if (lemac != LeMAC2)
DevicePresent(iobase); /* need after EWRK3_INIT */
status = get_hw_addr(dev, eeprom_image, lemac);
- printk("%s\n", print_mac(mac, dev->dev_addr));
+ printk("%pM\n", dev->dev_addr);
if (status) {
printk(" which has an EEPROM CRC error.\n");
@@ -646,10 +645,8 @@ static int ewrk3_open(struct net_device *dev)
ewrk3_init(dev);
if (ewrk3_debug > 1) {
- DECLARE_MAC_BUF(mac);
printk("%s: ewrk3 open with irq %d\n", dev->name, dev->irq);
- printk(" physical address: %s\n",
- print_mac(mac, dev->dev_addr));
+ printk(" physical address: %pM\n", dev->dev_addr);
if (lp->shmem_length == 0) {
printk(" no shared memory, I/O only mode\n");
} else {
@@ -1029,7 +1026,6 @@ static int ewrk3_rx(struct net_device *dev)
/*
** Update stats
*/
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
} else {
@@ -1971,13 +1967,3 @@ module_exit(ewrk3_exit_module);
module_init(ewrk3_init_module);
#endif /* MODULE */
MODULE_LICENSE("GPL");
-
-
-
-/*
- * Local variables:
- * compile-command: "gcc -D__KERNEL__ -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c ewrk3.c"
- *
- * compile-command: "gcc -D__KERNEL__ -DMODULE -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -c ewrk3.c"
- * End:
- */
diff --git a/drivers/net/fealnx.c b/drivers/net/fealnx.c
index b455ae931f7a..31ab1ff623fc 100644
--- a/drivers/net/fealnx.c
+++ b/drivers/net/fealnx.c
@@ -486,7 +486,6 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
#else
int bar = 1;
#endif
- DECLARE_MAC_BUF(mac);
/* when built into the kernel, we only print version if device is found */
#ifndef MODULE
@@ -665,9 +664,9 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
if (err)
goto err_out_free_tx;
- printk(KERN_INFO "%s: %s at %p, %s, IRQ %d.\n",
+ printk(KERN_INFO "%s: %s at %p, %pM, IRQ %d.\n",
dev->name, skel_netdrv_tbl[chip_id].chip_name, ioaddr,
- print_mac(mac, dev->dev_addr), irq);
+ dev->dev_addr, irq);
return 0;
@@ -1727,7 +1726,6 @@ static int netdev_rx(struct net_device *dev)
}
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
np->stats.rx_packets++;
np->stats.rx_bytes += pkt_len;
}
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index ecd5c71a7a8a..7e33c129d51c 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -1155,7 +1155,7 @@ static phy_info_t const phy_info_ks8721bl = {
static void mii_parse_dp8384x_sr2(uint mii_reg, struct net_device *dev)
{
- struct fec_enet_private *fep = dev->priv;
+ struct fec_enet_private *fep = netdev_priv(dev);
volatile uint *s = &(fep->phy_status);
*s &= ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC);
@@ -2562,7 +2562,6 @@ static int __init fec_enet_module_init(void)
{
struct net_device *dev;
int i, err;
- DECLARE_MAC_BUF(mac);
printk("FEC ENET Version 0.2\n");
@@ -2581,8 +2580,7 @@ static int __init fec_enet_module_init(void)
return -EIO;
}
- printk("%s: ethernet %s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ printk("%s: ethernet %pM\n", dev->name, dev->dev_addr);
}
return 0;
}
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c
index aec3b97e794d..cd8e98b45ec5 100644
--- a/drivers/net/fec_mpc52xx.c
+++ b/drivers/net/fec_mpc52xx.c
@@ -216,7 +216,7 @@ static int mpc52xx_fec_init_phy(struct net_device *dev)
struct phy_device *phydev;
char phy_id[BUS_ID_SIZE];
- snprintf(phy_id, BUS_ID_SIZE, "%x:%02x",
+ snprintf(phy_id, sizeof(phy_id), "%x:%02x",
(unsigned int)dev->base_addr, priv->phy_addr);
priv->link = PHY_DOWN;
@@ -487,7 +487,6 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id)
rskb->protocol = eth_type_trans(rskb, dev);
netif_rx(rskb);
- dev->last_rx = jiffies;
} else {
/* Can't get a new one : reuse the same & drop pkt */
dev_notice(&dev->dev, "Memory squeeze, dropping packet.\n");
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index cc7328b15521..5b68dc20168d 100644
--- a/drivers/net/forcedeth.c
+++ b/drivers/net/forcedeth.c
@@ -712,12 +712,12 @@ struct nv_skb_map {
/*
* SMP locking:
- * All hardware access under dev->priv->lock, except the performance
+ * All hardware access under netdev_priv(dev)->lock, except the performance
* critical parts:
* - rx is (pseudo-) lockless: it relies on the single-threading provided
* by the arch code for interrupts.
* - tx setup is lockless: it relies on netif_tx_lock. Actual submission
- * needs dev->priv->lock :-(
+ * needs netdev_priv(dev)->lock :-(
* - set_multicast_list: preparation lockless, relies on netif_tx_lock.
*/
@@ -818,7 +818,7 @@ struct fe_priv {
* Maximum number of loops until we assume that a bit in the irq mask
* is stuck. Overridable with module param.
*/
-static int max_interrupt_work = 5;
+static int max_interrupt_work = 15;
/*
* Optimization can be either throuput mode or cpu mode
@@ -1446,9 +1446,9 @@ static int phy_init(struct net_device *dev)
/* some phys clear out pause advertisment on reset, set it back */
mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg);
- /* restart auto negotiation */
+ /* restart auto negotiation, power down phy */
mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ);
- mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE);
+ mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE | BMCR_PDOWN);
if (mii_rw(dev, np->phyaddr, MII_BMCR, mii_control)) {
return PHY_ERROR;
}
@@ -1760,7 +1760,7 @@ static void nv_do_rx_refill(unsigned long data)
struct fe_priv *np = netdev_priv(dev);
/* Just reschedule NAPI rx processing */
- netif_rx_schedule(dev, &np->napi);
+ netif_rx_schedule(&np->napi);
}
#else
static void nv_do_rx_refill(unsigned long data)
@@ -2735,7 +2735,6 @@ static int nv_rx_process(struct net_device *dev, int limit)
#else
netif_rx(skb);
#endif
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
next_pkt:
@@ -2848,7 +2847,6 @@ static int nv_rx_process_optimized(struct net_device *dev, int limit)
}
}
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
} else {
@@ -3405,7 +3403,7 @@ static irqreturn_t nv_nic_irq(int foo, void *data)
#ifdef CONFIG_FORCEDETH_NAPI
if (events & NVREG_IRQ_RX_ALL) {
- netif_rx_schedule(dev, &np->napi);
+ netif_rx_schedule(&np->napi);
/* Disable furthur receive irq's */
spin_lock(&np->lock);
@@ -3522,7 +3520,7 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data)
#ifdef CONFIG_FORCEDETH_NAPI
if (events & NVREG_IRQ_RX_ALL) {
- netif_rx_schedule(dev, &np->napi);
+ netif_rx_schedule(&np->napi);
/* Disable furthur receive irq's */
spin_lock(&np->lock);
@@ -3680,7 +3678,7 @@ static int nv_napi_poll(struct napi_struct *napi, int budget)
/* re-enable receive interrupts */
spin_lock_irqsave(&np->lock, flags);
- __netif_rx_complete(dev, napi);
+ __netif_rx_complete(napi);
np->irqmask |= NVREG_IRQ_RX_ALL;
if (np->msi_flags & NV_MSI_X_ENABLED)
@@ -3706,7 +3704,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data)
writel(NVREG_IRQ_RX_ALL, base + NvRegMSIXIrqStatus);
if (events) {
- netif_rx_schedule(dev, &np->napi);
+ netif_rx_schedule(&np->napi);
/* disable receive interrupts on the nic */
writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask);
pci_push(base);
@@ -5210,6 +5208,10 @@ static int nv_open(struct net_device *dev)
dprintk(KERN_DEBUG "nv_open: begin\n");
+ /* power up phy */
+ mii_rw(dev, np->phyaddr, MII_BMCR,
+ mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ) & ~BMCR_PDOWN);
+
/* erase previous misconfiguration */
if (np->driver_data & DEV_HAS_POWER_CNTRL)
nv_mac_reset(dev);
@@ -5403,6 +5405,10 @@ static int nv_close(struct net_device *dev)
if (np->wolenabled) {
writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags);
nv_start_rx(dev);
+ } else {
+ /* power down phy */
+ mii_rw(dev, np->phyaddr, MII_BMCR,
+ mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ)|BMCR_PDOWN);
}
/* FIXME: power down nic */
@@ -5410,6 +5416,38 @@ static int nv_close(struct net_device *dev)
return 0;
}
+static const struct net_device_ops nv_netdev_ops = {
+ .ndo_open = nv_open,
+ .ndo_stop = nv_close,
+ .ndo_get_stats = nv_get_stats,
+ .ndo_start_xmit = nv_start_xmit,
+ .ndo_tx_timeout = nv_tx_timeout,
+ .ndo_change_mtu = nv_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = nv_set_mac_address,
+ .ndo_set_multicast_list = nv_set_multicast,
+ .ndo_vlan_rx_register = nv_vlan_rx_register,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = nv_poll_controller,
+#endif
+};
+
+static const struct net_device_ops nv_netdev_ops_optimized = {
+ .ndo_open = nv_open,
+ .ndo_stop = nv_close,
+ .ndo_get_stats = nv_get_stats,
+ .ndo_start_xmit = nv_start_xmit_optimized,
+ .ndo_tx_timeout = nv_tx_timeout,
+ .ndo_change_mtu = nv_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = nv_set_mac_address,
+ .ndo_set_multicast_list = nv_set_multicast,
+ .ndo_vlan_rx_register = nv_vlan_rx_register,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = nv_poll_controller,
+#endif
+};
+
static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
{
struct net_device *dev;
@@ -5420,7 +5458,6 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
u32 powerstate, txreg;
u32 phystate_orig = 0, phystate;
int phyinitialized = 0;
- DECLARE_MAC_BUF(mac);
static int printed_version;
if (!printed_version++)
@@ -5530,7 +5567,6 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
if (id->driver_data & DEV_HAS_VLAN) {
np->vlanctl_bits = NVREG_VLANCONTROL_ENABLE;
dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX;
- dev->vlan_rx_register = nv_vlan_rx_register;
}
np->msi_flags = 0;
@@ -5580,25 +5616,15 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
if (!np->rx_skb || !np->tx_skb)
goto out_freering;
- dev->open = nv_open;
- dev->stop = nv_close;
-
if (!nv_optimized(np))
- dev->hard_start_xmit = nv_start_xmit;
+ dev->netdev_ops = &nv_netdev_ops;
else
- dev->hard_start_xmit = nv_start_xmit_optimized;
- dev->get_stats = nv_get_stats;
- dev->change_mtu = nv_change_mtu;
- dev->set_mac_address = nv_set_mac_address;
- dev->set_multicast_list = nv_set_multicast;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = nv_poll_controller;
-#endif
+ dev->netdev_ops = &nv_netdev_ops_optimized;
+
#ifdef CONFIG_FORCEDETH_NAPI
netif_napi_add(dev, &np->napi, nv_napi_poll, RX_WORK_PER_LOOP);
#endif
SET_ETHTOOL_OPS(dev, &ops);
- dev->tx_timeout = nv_tx_timeout;
dev->watchdog_timeo = NV_WATCHDOG_TIMEO;
pci_set_drvdata(pci_dev, dev);
@@ -5653,8 +5679,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
* to 01:23:45:67:89:ab
*/
dev_printk(KERN_ERR, &pci_dev->dev,
- "Invalid Mac address detected: %s\n",
- print_mac(mac, dev->dev_addr));
+ "Invalid Mac address detected: %pM\n",
+ dev->dev_addr);
dev_printk(KERN_ERR, &pci_dev->dev,
"Please complain to your hardware vendor. Switching to a random MAC.\n");
dev->dev_addr[0] = 0x00;
@@ -5663,8 +5689,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i
get_random_bytes(&dev->dev_addr[3], 3);
}
- dprintk(KERN_DEBUG "%s: MAC Address %s\n",
- pci_name(pci_dev), print_mac(mac, dev->dev_addr));
+ dprintk(KERN_DEBUG "%s: MAC Address %pM\n",
+ pci_name(pci_dev), dev->dev_addr);
/* set mac address */
nv_copy_mac_to_hw(dev);
@@ -6141,7 +6167,7 @@ static struct pci_device_id pci_tbl[] = {
},
{ /* MCP79 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36),
- .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
+ .driver_data = DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V3|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE,
},
{ /* MCP79 Ethernet Controller */
PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37),
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index a6f49d025787..4e6a9195fe5f 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -209,7 +209,7 @@ static int fs_enet_rx_napi(struct napi_struct *napi, int budget)
if (received < budget) {
/* done */
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
(*fep->ops->napi_enable_rx)(dev);
}
return received;
@@ -478,7 +478,7 @@ fs_enet_interrupt(int irq, void *dev_id)
/* NOTE: it is possible for FCCs in NAPI mode */
/* to submit a spurious interrupt while in poll */
if (napi_ok)
- __netif_rx_schedule(dev, &fep->napi);
+ __netif_rx_schedule(&fep->napi);
}
}
@@ -1117,10 +1117,7 @@ static int __devinit fs_enet_probe(struct of_device *ofdev,
if (ret)
goto out_free_bd;
- printk(KERN_INFO "%s: fs_enet: %02x:%02x:%02x:%02x:%02x:%02x\n",
- ndev->name,
- ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
- ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
+ printk(KERN_INFO "%s: fs_enet: %pM\n", ndev->name, ndev->dev_addr);
return 0;
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index c4af949bf860..c672ecfc9595 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -25,11 +25,8 @@
*
* Theory of operation
*
- * The driver is initialized through platform_device. Structures which
- * define the configuration needed by the board are defined in a
- * board structure in arch/ppc/platforms (though I do not
- * discount the possibility that other architectures could one
- * day be supported.
+ * The driver is initialized through of_device. Configuration information
+ * is therefore conveyed through an OF-style device tree.
*
* The Gianfar Ethernet Controller uses a ring of buffer
* descriptors. The beginning is indicated by a register
@@ -78,7 +75,7 @@
#include <linux/if_vlan.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
-#include <linux/platform_device.h>
+#include <linux/of_platform.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
@@ -92,6 +89,8 @@
#include <linux/crc32.h>
#include <linux/mii.h>
#include <linux/phy.h>
+#include <linux/phy_fixed.h>
+#include <linux/of.h>
#include "gianfar.h"
#include "gianfar_mii.h"
@@ -119,8 +118,9 @@ static irqreturn_t gfar_interrupt(int irq, void *dev_id);
static void adjust_link(struct net_device *dev);
static void init_registers(struct net_device *dev);
static int init_phy(struct net_device *dev);
-static int gfar_probe(struct platform_device *pdev);
-static int gfar_remove(struct platform_device *pdev);
+static int gfar_probe(struct of_device *ofdev,
+ const struct of_device_id *match);
+static int gfar_remove(struct of_device *ofdev);
static void free_skb_resources(struct gfar_private *priv);
static void gfar_set_multi(struct net_device *dev);
static void gfar_set_hash_for_addr(struct net_device *dev, u8 *addr);
@@ -131,7 +131,8 @@ static void gfar_netpoll(struct net_device *dev);
#endif
int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit);
static int gfar_clean_tx_ring(struct net_device *dev);
-static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int length);
+static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
+ int amount_pull);
static void gfar_vlan_rx_register(struct net_device *netdev,
struct vlan_group *grp);
void gfar_halt(struct net_device *dev);
@@ -149,29 +150,163 @@ MODULE_LICENSE("GPL");
/* Returns 1 if incoming frames use an FCB */
static inline int gfar_uses_fcb(struct gfar_private *priv)
{
- return (priv->vlan_enable || priv->rx_csum_enable);
+ return priv->vlgrp || priv->rx_csum_enable;
+}
+
+static int gfar_of_init(struct net_device *dev)
+{
+ struct device_node *phy, *mdio;
+ const unsigned int *id;
+ const char *model;
+ const char *ctype;
+ const void *mac_addr;
+ const phandle *ph;
+ u64 addr, size;
+ int err = 0;
+ struct gfar_private *priv = netdev_priv(dev);
+ struct device_node *np = priv->node;
+ char bus_name[MII_BUS_ID_SIZE];
+
+ if (!np || !of_device_is_available(np))
+ return -ENODEV;
+
+ /* get a pointer to the register memory */
+ addr = of_translate_address(np, of_get_address(np, 0, &size, NULL));
+ priv->regs = ioremap(addr, size);
+
+ if (priv->regs == NULL)
+ return -ENOMEM;
+
+ priv->interruptTransmit = irq_of_parse_and_map(np, 0);
+
+ model = of_get_property(np, "model", NULL);
+
+ /* If we aren't the FEC we have multiple interrupts */
+ if (model && strcasecmp(model, "FEC")) {
+ priv->interruptReceive = irq_of_parse_and_map(np, 1);
+
+ priv->interruptError = irq_of_parse_and_map(np, 2);
+
+ if (priv->interruptTransmit < 0 ||
+ priv->interruptReceive < 0 ||
+ priv->interruptError < 0) {
+ err = -EINVAL;
+ goto err_out;
+ }
+ }
+
+ mac_addr = of_get_mac_address(np);
+ if (mac_addr)
+ memcpy(dev->dev_addr, mac_addr, MAC_ADDR_LEN);
+
+ if (model && !strcasecmp(model, "TSEC"))
+ priv->device_flags =
+ FSL_GIANFAR_DEV_HAS_GIGABIT |
+ FSL_GIANFAR_DEV_HAS_COALESCE |
+ FSL_GIANFAR_DEV_HAS_RMON |
+ FSL_GIANFAR_DEV_HAS_MULTI_INTR;
+ if (model && !strcasecmp(model, "eTSEC"))
+ priv->device_flags =
+ FSL_GIANFAR_DEV_HAS_GIGABIT |
+ FSL_GIANFAR_DEV_HAS_COALESCE |
+ FSL_GIANFAR_DEV_HAS_RMON |
+ FSL_GIANFAR_DEV_HAS_MULTI_INTR |
+ FSL_GIANFAR_DEV_HAS_PADDING |
+ FSL_GIANFAR_DEV_HAS_CSUM |
+ FSL_GIANFAR_DEV_HAS_VLAN |
+ FSL_GIANFAR_DEV_HAS_MAGIC_PACKET |
+ FSL_GIANFAR_DEV_HAS_EXTENDED_HASH;
+
+ ctype = of_get_property(np, "phy-connection-type", NULL);
+
+ /* We only care about rgmii-id. The rest are autodetected */
+ if (ctype && !strcmp(ctype, "rgmii-id"))
+ priv->interface = PHY_INTERFACE_MODE_RGMII_ID;
+ else
+ priv->interface = PHY_INTERFACE_MODE_MII;
+
+ if (of_get_property(np, "fsl,magic-packet", NULL))
+ priv->device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET;
+
+ ph = of_get_property(np, "phy-handle", NULL);
+ if (ph == NULL) {
+ u32 *fixed_link;
+
+ fixed_link = (u32 *)of_get_property(np, "fixed-link", NULL);
+ if (!fixed_link) {
+ err = -ENODEV;
+ goto err_out;
+ }
+
+ snprintf(priv->phy_bus_id, BUS_ID_SIZE, PHY_ID_FMT, "0",
+ fixed_link[0]);
+ } else {
+ phy = of_find_node_by_phandle(*ph);
+
+ if (phy == NULL) {
+ err = -ENODEV;
+ goto err_out;
+ }
+
+ mdio = of_get_parent(phy);
+
+ id = of_get_property(phy, "reg", NULL);
+
+ of_node_put(phy);
+ of_node_put(mdio);
+
+ gfar_mdio_bus_name(bus_name, mdio);
+ snprintf(priv->phy_bus_id, BUS_ID_SIZE, "%s:%02x",
+ bus_name, *id);
+ }
+
+ /* Find the TBI PHY. If it's not there, we don't support SGMII */
+ ph = of_get_property(np, "tbi-handle", NULL);
+ if (ph) {
+ struct device_node *tbi = of_find_node_by_phandle(*ph);
+ struct of_device *ofdev;
+ struct mii_bus *bus;
+
+ if (!tbi)
+ return 0;
+
+ mdio = of_get_parent(tbi);
+ if (!mdio)
+ return 0;
+
+ ofdev = of_find_device_by_node(mdio);
+
+ of_node_put(mdio);
+
+ id = of_get_property(tbi, "reg", NULL);
+ if (!id)
+ return 0;
+
+ of_node_put(tbi);
+
+ bus = dev_get_drvdata(&ofdev->dev);
+
+ priv->tbiphy = bus->phy_map[*id];
+ }
+
+ return 0;
+
+err_out:
+ iounmap(priv->regs);
+ return err;
}
/* Set up the ethernet device structure, private data,
* and anything else we need before we start */
-static int gfar_probe(struct platform_device *pdev)
+static int gfar_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
{
u32 tempval;
struct net_device *dev = NULL;
struct gfar_private *priv = NULL;
- struct gianfar_platform_data *einfo;
- struct resource *r;
- int err = 0, irq;
DECLARE_MAC_BUF(mac);
-
- einfo = (struct gianfar_platform_data *) pdev->dev.platform_data;
-
- if (NULL == einfo) {
- printk(KERN_ERR "gfar %d: Missing additional data!\n",
- pdev->id);
-
- return -ENODEV;
- }
+ int err = 0;
+ int len_devname;
/* Create an ethernet device instance */
dev = alloc_etherdev(sizeof (*priv));
@@ -181,64 +316,23 @@ static int gfar_probe(struct platform_device *pdev)
priv = netdev_priv(dev);
priv->dev = dev;
+ priv->node = ofdev->node;
- /* Set the info in the priv to the current info */
- priv->einfo = einfo;
-
- /* fill out IRQ fields */
- if (einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
- irq = platform_get_irq_byname(pdev, "tx");
- if (irq < 0)
- goto regs_fail;
- priv->interruptTransmit = irq;
-
- irq = platform_get_irq_byname(pdev, "rx");
- if (irq < 0)
- goto regs_fail;
- priv->interruptReceive = irq;
-
- irq = platform_get_irq_byname(pdev, "error");
- if (irq < 0)
- goto regs_fail;
- priv->interruptError = irq;
- } else {
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- goto regs_fail;
- priv->interruptTransmit = irq;
- }
-
- /* get a pointer to the register memory */
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- priv->regs = ioremap(r->start, sizeof (struct gfar));
+ err = gfar_of_init(dev);
- if (NULL == priv->regs) {
- err = -ENOMEM;
+ if (err)
goto regs_fail;
- }
spin_lock_init(&priv->txlock);
spin_lock_init(&priv->rxlock);
spin_lock_init(&priv->bflock);
INIT_WORK(&priv->reset_task, gfar_reset_task);
- platform_set_drvdata(pdev, dev);
+ dev_set_drvdata(&ofdev->dev, priv);
/* Stop the DMA engine now, in case it was running before */
/* (The firmware could have used it, and left it running). */
- /* To do this, we write Graceful Receive Stop and Graceful */
- /* Transmit Stop, and then wait until the corresponding bits */
- /* in IEVENT indicate the stops have completed. */
- tempval = gfar_read(&priv->regs->dmactrl);
- tempval &= ~(DMACTRL_GRS | DMACTRL_GTS);
- gfar_write(&priv->regs->dmactrl, tempval);
-
- tempval = gfar_read(&priv->regs->dmactrl);
- tempval |= (DMACTRL_GRS | DMACTRL_GTS);
- gfar_write(&priv->regs->dmactrl, tempval);
-
- while (!(gfar_read(&priv->regs->ievent) & (IEVENT_GRSC | IEVENT_GTSC)))
- cpu_relax();
+ gfar_halt(dev);
/* Reset MAC layer */
gfar_write(&priv->regs->maccfg1, MACCFG1_SOFT_RESET);
@@ -252,13 +346,10 @@ static int gfar_probe(struct platform_device *pdev)
/* Initialize ECNTRL */
gfar_write(&priv->regs->ecntrl, ECNTRL_INIT_SETTINGS);
- /* Copy the station address into the dev structure, */
- memcpy(dev->dev_addr, einfo->mac_addr, MAC_ADDR_LEN);
-
/* Set the dev->base_addr to the gfar reg region */
dev->base_addr = (unsigned long) (priv->regs);
- SET_NETDEV_DEV(dev, &pdev->dev);
+ SET_NETDEV_DEV(dev, &ofdev->dev);
/* Fill in the dev structure */
dev->open = gfar_enet_open;
@@ -276,23 +367,21 @@ static int gfar_probe(struct platform_device *pdev)
dev->ethtool_ops = &gfar_ethtool_ops;
- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) {
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM) {
priv->rx_csum_enable = 1;
- dev->features |= NETIF_F_IP_CSUM;
+ dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_HIGHDMA;
} else
priv->rx_csum_enable = 0;
priv->vlgrp = NULL;
- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
dev->vlan_rx_register = gfar_vlan_rx_register;
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-
- priv->vlan_enable = 1;
}
- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) {
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) {
priv->extended_hash = 1;
priv->hash_width = 9;
@@ -327,7 +416,7 @@ static int gfar_probe(struct platform_device *pdev)
priv->hash_regs[7] = &priv->regs->gaddr7;
}
- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_PADDING)
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_PADDING)
priv->padding = DEFAULT_PADDING;
else
priv->padding = 0;
@@ -338,13 +427,12 @@ static int gfar_probe(struct platform_device *pdev)
priv->rx_buffer_size = DEFAULT_RX_BUFFER_SIZE;
priv->tx_ring_size = DEFAULT_TX_RING_SIZE;
priv->rx_ring_size = DEFAULT_RX_RING_SIZE;
+ priv->num_txbdfree = DEFAULT_TX_RING_SIZE;
priv->txcoalescing = DEFAULT_TX_COALESCE;
- priv->txcount = DEFAULT_TXCOUNT;
- priv->txtime = DEFAULT_TXTIME;
+ priv->txic = DEFAULT_TXIC;
priv->rxcoalescing = DEFAULT_RX_COALESCE;
- priv->rxcount = DEFAULT_RXCOUNT;
- priv->rxtime = DEFAULT_RXTIME;
+ priv->rxic = DEFAULT_RXIC;
/* Enable most messages by default */
priv->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1;
@@ -360,12 +448,28 @@ static int gfar_probe(struct platform_device *pdev)
goto register_fail;
}
+ /* fill out IRQ number and name fields */
+ len_devname = strlen(dev->name);
+ strncpy(&priv->int_name_tx[0], dev->name, len_devname);
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
+ strncpy(&priv->int_name_tx[len_devname],
+ "_tx", sizeof("_tx") + 1);
+
+ strncpy(&priv->int_name_rx[0], dev->name, len_devname);
+ strncpy(&priv->int_name_rx[len_devname],
+ "_rx", sizeof("_rx") + 1);
+
+ strncpy(&priv->int_name_er[0], dev->name, len_devname);
+ strncpy(&priv->int_name_er[len_devname],
+ "_er", sizeof("_er") + 1);
+ } else
+ priv->int_name_tx[len_devname] = '\0';
+
/* Create all the sysfs files */
gfar_init_sysfs(dev);
/* Print out the device info */
- printk(KERN_INFO DEVICE_NAME "%s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO DEVICE_NAME "%pM\n", dev->name, dev->dev_addr);
/* Even more device info helps when determining which kernel */
/* provided which set of benchmarks. */
@@ -382,29 +486,28 @@ regs_fail:
return err;
}
-static int gfar_remove(struct platform_device *pdev)
+static int gfar_remove(struct of_device *ofdev)
{
- struct net_device *dev = platform_get_drvdata(pdev);
- struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_private *priv = dev_get_drvdata(&ofdev->dev);
- platform_set_drvdata(pdev, NULL);
+ dev_set_drvdata(&ofdev->dev, NULL);
iounmap(priv->regs);
- free_netdev(dev);
+ free_netdev(priv->dev);
return 0;
}
#ifdef CONFIG_PM
-static int gfar_suspend(struct platform_device *pdev, pm_message_t state)
+static int gfar_suspend(struct of_device *ofdev, pm_message_t state)
{
- struct net_device *dev = platform_get_drvdata(pdev);
- struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_private *priv = dev_get_drvdata(&ofdev->dev);
+ struct net_device *dev = priv->dev;
unsigned long flags;
u32 tempval;
int magic_packet = priv->wol_en &&
- (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+ (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
netif_device_detach(dev);
@@ -445,14 +548,14 @@ static int gfar_suspend(struct platform_device *pdev, pm_message_t state)
return 0;
}
-static int gfar_resume(struct platform_device *pdev)
+static int gfar_resume(struct of_device *ofdev)
{
- struct net_device *dev = platform_get_drvdata(pdev);
- struct gfar_private *priv = netdev_priv(dev);
+ struct gfar_private *priv = dev_get_drvdata(&ofdev->dev);
+ struct net_device *dev = priv->dev;
unsigned long flags;
u32 tempval;
int magic_packet = priv->wol_en &&
- (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
+ (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
if (!netif_running(dev)) {
netif_device_attach(dev);
@@ -511,7 +614,7 @@ static phy_interface_t gfar_get_interface(struct net_device *dev)
if (ecntrl & ECNTRL_REDUCED_MII_MODE)
return PHY_INTERFACE_MODE_RMII;
else {
- phy_interface_t interface = priv->einfo->interface;
+ phy_interface_t interface = priv->interface;
/*
* This isn't autodetected right now, so it must
@@ -524,7 +627,7 @@ static phy_interface_t gfar_get_interface(struct net_device *dev)
}
}
- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT)
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT)
return PHY_INTERFACE_MODE_GMII;
return PHY_INTERFACE_MODE_MII;
@@ -538,21 +641,18 @@ static int init_phy(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
uint gigabit_support =
- priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
+ priv->device_flags & FSL_GIANFAR_DEV_HAS_GIGABIT ?
SUPPORTED_1000baseT_Full : 0;
struct phy_device *phydev;
- char phy_id[BUS_ID_SIZE];
phy_interface_t interface;
priv->oldlink = 0;
priv->oldspeed = 0;
priv->oldduplex = -1;
- snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->einfo->bus_id, priv->einfo->phy_id);
-
interface = gfar_get_interface(dev);
- phydev = phy_connect(dev, phy_id, &adjust_link, 0, interface);
+ phydev = phy_connect(dev, priv->phy_bus_id, &adjust_link, 0, interface);
if (interface == PHY_INTERFACE_MODE_SGMII)
gfar_configure_serdes(dev);
@@ -583,35 +683,31 @@ static int init_phy(struct net_device *dev)
static void gfar_configure_serdes(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
- struct gfar_mii __iomem *regs =
- (void __iomem *)&priv->regs->gfar_mii_regs;
- int tbipa = gfar_read(&priv->regs->tbipa);
- struct mii_bus *bus = gfar_get_miibus(priv);
- if (bus)
- mutex_lock(&bus->mdio_lock);
+ if (!priv->tbiphy) {
+ printk(KERN_WARNING "SGMII mode requires that the device "
+ "tree specify a tbi-handle\n");
+ return;
+ }
- /* If the link is already up, we must already be ok, and don't need to
+ /*
+ * If the link is already up, we must already be ok, and don't need to
* configure and reset the TBI<->SerDes link. Maybe U-Boot configured
* everything for us? Resetting it takes the link down and requires
* several seconds for it to come back.
*/
- if (gfar_local_mdio_read(regs, tbipa, MII_BMSR) & BMSR_LSTATUS)
- goto done;
+ if (phy_read(priv->tbiphy, MII_BMSR) & BMSR_LSTATUS)
+ return;
/* Single clk mode, mii mode off(for serdes communication) */
- gfar_local_mdio_write(regs, tbipa, MII_TBICON, TBICON_CLK_SELECT);
+ phy_write(priv->tbiphy, MII_TBICON, TBICON_CLK_SELECT);
- gfar_local_mdio_write(regs, tbipa, MII_ADVERTISE,
+ phy_write(priv->tbiphy, MII_ADVERTISE,
ADVERTISE_1000XFULL | ADVERTISE_1000XPAUSE |
ADVERTISE_1000XPSE_ASYM);
- gfar_local_mdio_write(regs, tbipa, MII_BMCR, BMCR_ANENABLE |
+ phy_write(priv->tbiphy, MII_BMCR, BMCR_ANENABLE |
BMCR_ANRESTART | BMCR_FULLDPLX | BMCR_SPEED1000);
-
- done:
- if (bus)
- mutex_unlock(&bus->mdio_lock);
}
static void init_registers(struct net_device *dev)
@@ -644,7 +740,7 @@ static void init_registers(struct net_device *dev)
gfar_write(&priv->regs->gaddr7, 0);
/* Zero out the rmon mib registers if it has them */
- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
memset_io(&(priv->regs->rmon), 0, sizeof (struct rmon_mib));
/* Mask off the CAM interrupts */
@@ -719,7 +815,7 @@ void stop_gfar(struct net_device *dev)
spin_unlock_irqrestore(&priv->txlock, flags);
/* Free the IRQs */
- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
free_irq(priv->interruptError, dev);
free_irq(priv->interruptTransmit, dev);
free_irq(priv->interruptReceive, dev);
@@ -742,22 +838,26 @@ static void free_skb_resources(struct gfar_private *priv)
{
struct rxbd8 *rxbdp;
struct txbd8 *txbdp;
- int i;
+ int i, j;
/* Go through all the buffer descriptors and free their data buffers */
txbdp = priv->tx_bd_base;
for (i = 0; i < priv->tx_ring_size; i++) {
-
- if (priv->tx_skbuff[i]) {
- dma_unmap_single(&priv->dev->dev, txbdp->bufPtr,
- txbdp->length,
- DMA_TO_DEVICE);
- dev_kfree_skb_any(priv->tx_skbuff[i]);
- priv->tx_skbuff[i] = NULL;
+ if (!priv->tx_skbuff[i])
+ continue;
+
+ dma_unmap_single(&priv->dev->dev, txbdp->bufPtr,
+ txbdp->length, DMA_TO_DEVICE);
+ txbdp->lstatus = 0;
+ for (j = 0; j < skb_shinfo(priv->tx_skbuff[i])->nr_frags; j++) {
+ txbdp++;
+ dma_unmap_page(&priv->dev->dev, txbdp->bufPtr,
+ txbdp->length, DMA_TO_DEVICE);
}
-
txbdp++;
+ dev_kfree_skb_any(priv->tx_skbuff[i]);
+ priv->tx_skbuff[i] = NULL;
}
kfree(priv->tx_skbuff);
@@ -777,8 +877,7 @@ static void free_skb_resources(struct gfar_private *priv)
priv->rx_skbuff[i] = NULL;
}
- rxbdp->status = 0;
- rxbdp->length = 0;
+ rxbdp->lstatus = 0;
rxbdp->bufPtr = 0;
rxbdp++;
@@ -815,6 +914,8 @@ void gfar_start(struct net_device *dev)
/* Unmask the interrupts we look for */
gfar_write(&regs->imask, IMASK_DEFAULT);
+
+ dev->trans_start = jiffies;
}
/* Bring the controller up and running */
@@ -889,6 +990,7 @@ int startup_gfar(struct net_device *dev)
priv->rx_skbuff[i] = NULL;
/* Initialize some variables in our dev structure */
+ priv->num_txbdfree = priv->tx_ring_size;
priv->dirty_tx = priv->cur_tx = priv->tx_bd_base;
priv->cur_rx = priv->rx_bd_base;
priv->skb_curtx = priv->skb_dirtytx = 0;
@@ -897,8 +999,7 @@ int startup_gfar(struct net_device *dev)
/* Initialize Transmit Descriptor Ring */
txbdp = priv->tx_bd_base;
for (i = 0; i < priv->tx_ring_size; i++) {
- txbdp->status = 0;
- txbdp->length = 0;
+ txbdp->lstatus = 0;
txbdp->bufPtr = 0;
txbdp++;
}
@@ -933,11 +1034,11 @@ int startup_gfar(struct net_device *dev)
/* If the device has multiple interrupts, register for
* them. Otherwise, only register for the one */
- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
/* Install our interrupt handlers for Error,
* Transmit, and Receive */
if (request_irq(priv->interruptError, gfar_error,
- 0, "enet_error", dev) < 0) {
+ 0, priv->int_name_er, dev) < 0) {
if (netif_msg_intr(priv))
printk(KERN_ERR "%s: Can't get IRQ %d\n",
dev->name, priv->interruptError);
@@ -947,7 +1048,7 @@ int startup_gfar(struct net_device *dev)
}
if (request_irq(priv->interruptTransmit, gfar_transmit,
- 0, "enet_tx", dev) < 0) {
+ 0, priv->int_name_tx, dev) < 0) {
if (netif_msg_intr(priv))
printk(KERN_ERR "%s: Can't get IRQ %d\n",
dev->name, priv->interruptTransmit);
@@ -958,7 +1059,7 @@ int startup_gfar(struct net_device *dev)
}
if (request_irq(priv->interruptReceive, gfar_receive,
- 0, "enet_rx", dev) < 0) {
+ 0, priv->int_name_rx, dev) < 0) {
if (netif_msg_intr(priv))
printk(KERN_ERR "%s: Can't get IRQ %d (receive0)\n",
dev->name, priv->interruptReceive);
@@ -968,10 +1069,10 @@ int startup_gfar(struct net_device *dev)
}
} else {
if (request_irq(priv->interruptTransmit, gfar_interrupt,
- 0, "gfar_interrupt", dev) < 0) {
+ 0, priv->int_name_tx, dev) < 0) {
if (netif_msg_intr(priv))
printk(KERN_ERR "%s: Can't get IRQ %d\n",
- dev->name, priv->interruptError);
+ dev->name, priv->interruptTransmit);
err = -1;
goto err_irq_fail;
@@ -981,17 +1082,13 @@ int startup_gfar(struct net_device *dev)
phy_start(priv->phydev);
/* Configure the coalescing support */
+ gfar_write(&regs->txic, 0);
if (priv->txcoalescing)
- gfar_write(&regs->txic,
- mk_ic_value(priv->txcount, priv->txtime));
- else
- gfar_write(&regs->txic, 0);
+ gfar_write(&regs->txic, priv->txic);
+ gfar_write(&regs->rxic, 0);
if (priv->rxcoalescing)
- gfar_write(&regs->rxic,
- mk_ic_value(priv->rxcount, priv->rxtime));
- else
- gfar_write(&regs->rxic, 0);
+ gfar_write(&regs->rxic, priv->rxic);
if (priv->rx_csum_enable)
rctrl |= RCTRL_CHECKSUMMING;
@@ -1003,9 +1100,6 @@ int startup_gfar(struct net_device *dev)
rctrl |= RCTRL_EMEN;
}
- if (priv->vlan_enable)
- rctrl |= RCTRL_VLAN;
-
if (priv->padding) {
rctrl &= ~RCTRL_PAL_MASK;
rctrl |= RCTRL_PADDING(priv->padding);
@@ -1094,11 +1188,11 @@ static int gfar_enet_open(struct net_device *dev)
return err;
}
-static inline struct txfcb *gfar_add_fcb(struct sk_buff *skb, struct txbd8 *bdp)
+static inline struct txfcb *gfar_add_fcb(struct sk_buff *skb)
{
struct txfcb *fcb = (struct txfcb *)skb_push (skb, GMAC_FCB_LEN);
- memset(fcb, 0, GMAC_FCB_LEN);
+ cacheable_memzero(fcb, GMAC_FCB_LEN);
return fcb;
}
@@ -1137,96 +1231,140 @@ void inline gfar_tx_vlan(struct sk_buff *skb, struct txfcb *fcb)
fcb->vlctl = vlan_tx_tag_get(skb);
}
+static inline struct txbd8 *skip_txbd(struct txbd8 *bdp, int stride,
+ struct txbd8 *base, int ring_size)
+{
+ struct txbd8 *new_bd = bdp + stride;
+
+ return (new_bd >= (base + ring_size)) ? (new_bd - ring_size) : new_bd;
+}
+
+static inline struct txbd8 *next_txbd(struct txbd8 *bdp, struct txbd8 *base,
+ int ring_size)
+{
+ return skip_txbd(bdp, 1, base, ring_size);
+}
+
/* This is called by the kernel when a frame is ready for transmission. */
/* It is pointed to by the dev->hard_start_xmit function pointer */
static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
struct txfcb *fcb = NULL;
- struct txbd8 *txbdp;
- u16 status;
+ struct txbd8 *txbdp, *txbdp_start, *base;
+ u32 lstatus;
+ int i;
+ u32 bufaddr;
unsigned long flags;
+ unsigned int nr_frags, length;
+
+ base = priv->tx_bd_base;
+
+ /* total number of fragments in the SKB */
+ nr_frags = skb_shinfo(skb)->nr_frags;
+
+ spin_lock_irqsave(&priv->txlock, flags);
+
+ /* check if there is space to queue this packet */
+ if (nr_frags > priv->num_txbdfree) {
+ /* no space, stop the queue */
+ netif_stop_queue(dev);
+ dev->stats.tx_fifo_errors++;
+ spin_unlock_irqrestore(&priv->txlock, flags);
+ return NETDEV_TX_BUSY;
+ }
/* Update transmit stats */
dev->stats.tx_bytes += skb->len;
- /* Lock priv now */
- spin_lock_irqsave(&priv->txlock, flags);
+ txbdp = txbdp_start = priv->cur_tx;
- /* Point at the first free tx descriptor */
- txbdp = priv->cur_tx;
+ if (nr_frags == 0) {
+ lstatus = txbdp->lstatus | BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT);
+ } else {
+ /* Place the fragment addresses and lengths into the TxBDs */
+ for (i = 0; i < nr_frags; i++) {
+ /* Point at the next BD, wrapping as needed */
+ txbdp = next_txbd(txbdp, base, priv->tx_ring_size);
+
+ length = skb_shinfo(skb)->frags[i].size;
- /* Clear all but the WRAP status flags */
- status = txbdp->status & TXBD_WRAP;
+ lstatus = txbdp->lstatus | length |
+ BD_LFLAG(TXBD_READY);
+
+ /* Handle the last BD specially */
+ if (i == nr_frags - 1)
+ lstatus |= BD_LFLAG(TXBD_LAST | TXBD_INTERRUPT);
+
+ bufaddr = dma_map_page(&dev->dev,
+ skb_shinfo(skb)->frags[i].page,
+ skb_shinfo(skb)->frags[i].page_offset,
+ length,
+ DMA_TO_DEVICE);
+
+ /* set the TxBD length and buffer pointer */
+ txbdp->bufPtr = bufaddr;
+ txbdp->lstatus = lstatus;
+ }
+
+ lstatus = txbdp_start->lstatus;
+ }
/* Set up checksumming */
- if (likely((dev->features & NETIF_F_IP_CSUM)
- && (CHECKSUM_PARTIAL == skb->ip_summed))) {
- fcb = gfar_add_fcb(skb, txbdp);
- status |= TXBD_TOE;
+ if (CHECKSUM_PARTIAL == skb->ip_summed) {
+ fcb = gfar_add_fcb(skb);
+ lstatus |= BD_LFLAG(TXBD_TOE);
gfar_tx_checksum(skb, fcb);
}
- if (priv->vlan_enable &&
- unlikely(priv->vlgrp && vlan_tx_tag_present(skb))) {
+ if (priv->vlgrp && vlan_tx_tag_present(skb)) {
if (unlikely(NULL == fcb)) {
- fcb = gfar_add_fcb(skb, txbdp);
- status |= TXBD_TOE;
+ fcb = gfar_add_fcb(skb);
+ lstatus |= BD_LFLAG(TXBD_TOE);
}
gfar_tx_vlan(skb, fcb);
}
- /* Set buffer length and pointer */
- txbdp->length = skb->len;
- txbdp->bufPtr = dma_map_single(&dev->dev, skb->data,
- skb->len, DMA_TO_DEVICE);
-
- /* Save the skb pointer so we can free it later */
+ /* setup the TxBD length and buffer pointer for the first BD */
priv->tx_skbuff[priv->skb_curtx] = skb;
+ txbdp_start->bufPtr = dma_map_single(&dev->dev, skb->data,
+ skb_headlen(skb), DMA_TO_DEVICE);
- /* Update the current skb pointer (wrapping if this was the last) */
- priv->skb_curtx =
- (priv->skb_curtx + 1) & TX_RING_MOD_MASK(priv->tx_ring_size);
-
- /* Flag the BD as interrupt-causing */
- status |= TXBD_INTERRUPT;
+ lstatus |= BD_LFLAG(TXBD_CRC | TXBD_READY) | skb_headlen(skb);
- /* Flag the BD as ready to go, last in frame, and */
- /* in need of CRC */
- status |= (TXBD_READY | TXBD_LAST | TXBD_CRC);
-
- dev->trans_start = jiffies;
-
- /* The powerpc-specific eieio() is used, as wmb() has too strong
+ /*
+ * The powerpc-specific eieio() is used, as wmb() has too strong
* semantics (it requires synchronization between cacheable and
* uncacheable mappings, which eieio doesn't provide and which we
* don't need), thus requiring a more expensive sync instruction. At
* some point, the set of architecture-independent barrier functions
* should be expanded to include weaker barriers.
*/
-
eieio();
- txbdp->status = status;
- /* If this was the last BD in the ring, the next one */
- /* is at the beginning of the ring */
- if (txbdp->status & TXBD_WRAP)
- txbdp = priv->tx_bd_base;
- else
- txbdp++;
+ txbdp_start->lstatus = lstatus;
+
+ /* Update the current skb pointer to the next entry we will use
+ * (wrapping if necessary) */
+ priv->skb_curtx = (priv->skb_curtx + 1) &
+ TX_RING_MOD_MASK(priv->tx_ring_size);
+
+ priv->cur_tx = next_txbd(txbdp, base, priv->tx_ring_size);
+
+ /* reduce TxBD free count */
+ priv->num_txbdfree -= (nr_frags + 1);
+
+ dev->trans_start = jiffies;
/* If the next BD still needs to be cleaned up, then the bds
are full. We need to tell the kernel to stop sending us stuff. */
- if (txbdp == priv->dirty_tx) {
+ if (!priv->num_txbdfree) {
netif_stop_queue(dev);
dev->stats.tx_fifo_errors++;
}
- /* Update the current txbd to the next one */
- priv->cur_tx = txbdp;
-
/* Tell the DMA to go go go */
gfar_write(&priv->regs->tstat, TSTAT_CLEAR_THALT);
@@ -1270,11 +1408,15 @@ static void gfar_vlan_rx_register(struct net_device *dev,
{
struct gfar_private *priv = netdev_priv(dev);
unsigned long flags;
+ struct vlan_group *old_grp;
u32 tempval;
spin_lock_irqsave(&priv->rxlock, flags);
- priv->vlgrp = grp;
+ old_grp = priv->vlgrp;
+
+ if (old_grp == grp)
+ return;
if (grp) {
/* Enable VLAN tag insertion */
@@ -1286,6 +1428,7 @@ static void gfar_vlan_rx_register(struct net_device *dev,
/* Enable VLAN tag extraction */
tempval = gfar_read(&priv->regs->rctrl);
tempval |= RCTRL_VLEX;
+ tempval |= (RCTRL_VLEX | RCTRL_PRSDEP_INIT);
gfar_write(&priv->regs->rctrl, tempval);
} else {
/* Disable VLAN tag insertion */
@@ -1296,9 +1439,16 @@ static void gfar_vlan_rx_register(struct net_device *dev,
/* Disable VLAN tag extraction */
tempval = gfar_read(&priv->regs->rctrl);
tempval &= ~RCTRL_VLEX;
+ /* If parse is no longer required, then disable parser */
+ if (tempval & RCTRL_REQ_PARSER)
+ tempval |= RCTRL_PRSDEP_INIT;
+ else
+ tempval &= ~RCTRL_PRSDEP_INIT;
gfar_write(&priv->regs->rctrl, tempval);
}
+ gfar_change_mtu(dev, dev->mtu);
+
spin_unlock_irqrestore(&priv->rxlock, flags);
}
@@ -1309,14 +1459,9 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu)
int oldsize = priv->rx_buffer_size;
int frame_size = new_mtu + ETH_HLEN;
- if (priv->vlan_enable)
+ if (priv->vlgrp)
frame_size += VLAN_HLEN;
- if (gfar_uses_fcb(priv))
- frame_size += GMAC_FCB_LEN;
-
- frame_size += priv->padding;
-
if ((frame_size < 64) || (frame_size > JUMBO_FRAME_SIZE)) {
if (netif_msg_drv(priv))
printk(KERN_ERR "%s: Invalid MTU setting\n",
@@ -1324,6 +1469,11 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu)
return -EINVAL;
}
+ if (gfar_uses_fcb(priv))
+ frame_size += GMAC_FCB_LEN;
+
+ frame_size += priv->padding;
+
tempsize =
(frame_size & ~(INCREMENTAL_BUFFER_SIZE - 1)) +
INCREMENTAL_BUFFER_SIZE;
@@ -1388,83 +1538,85 @@ static void gfar_timeout(struct net_device *dev)
/* Interrupt Handler for Transmit complete */
static int gfar_clean_tx_ring(struct net_device *dev)
{
- struct txbd8 *bdp;
struct gfar_private *priv = netdev_priv(dev);
+ struct txbd8 *bdp;
+ struct txbd8 *lbdp = NULL;
+ struct txbd8 *base = priv->tx_bd_base;
+ struct sk_buff *skb;
+ int skb_dirtytx;
+ int tx_ring_size = priv->tx_ring_size;
+ int frags = 0;
+ int i;
int howmany = 0;
+ u32 lstatus;
bdp = priv->dirty_tx;
- while ((bdp->status & TXBD_READY) == 0) {
- /* If dirty_tx and cur_tx are the same, then either the */
- /* ring is empty or full now (it could only be full in the beginning, */
- /* obviously). If it is empty, we are done. */
- if ((bdp == priv->cur_tx) && (netif_queue_stopped(dev) == 0))
- break;
+ skb_dirtytx = priv->skb_dirtytx;
- howmany++;
+ while ((skb = priv->tx_skbuff[skb_dirtytx])) {
+ frags = skb_shinfo(skb)->nr_frags;
+ lbdp = skip_txbd(bdp, frags, base, tx_ring_size);
- /* Deferred means some collisions occurred during transmit, */
- /* but we eventually sent the packet. */
- if (bdp->status & TXBD_DEF)
- dev->stats.collisions++;
+ lstatus = lbdp->lstatus;
- /* Unmap the DMA memory */
- dma_unmap_single(&priv->dev->dev, bdp->bufPtr,
- bdp->length, DMA_TO_DEVICE);
+ /* Only clean completed frames */
+ if ((lstatus & BD_LFLAG(TXBD_READY)) &&
+ (lstatus & BD_LENGTH_MASK))
+ break;
+
+ dma_unmap_single(&dev->dev,
+ bdp->bufPtr,
+ bdp->length,
+ DMA_TO_DEVICE);
- /* Free the sk buffer associated with this TxBD */
- dev_kfree_skb_irq(priv->tx_skbuff[priv->skb_dirtytx]);
+ bdp->lstatus &= BD_LFLAG(TXBD_WRAP);
+ bdp = next_txbd(bdp, base, tx_ring_size);
- priv->tx_skbuff[priv->skb_dirtytx] = NULL;
- priv->skb_dirtytx =
- (priv->skb_dirtytx +
- 1) & TX_RING_MOD_MASK(priv->tx_ring_size);
+ for (i = 0; i < frags; i++) {
+ dma_unmap_page(&dev->dev,
+ bdp->bufPtr,
+ bdp->length,
+ DMA_TO_DEVICE);
+ bdp->lstatus &= BD_LFLAG(TXBD_WRAP);
+ bdp = next_txbd(bdp, base, tx_ring_size);
+ }
- /* Clean BD length for empty detection */
- bdp->length = 0;
+ dev_kfree_skb_any(skb);
+ priv->tx_skbuff[skb_dirtytx] = NULL;
- /* update bdp to point at next bd in the ring (wrapping if necessary) */
- if (bdp->status & TXBD_WRAP)
- bdp = priv->tx_bd_base;
- else
- bdp++;
+ skb_dirtytx = (skb_dirtytx + 1) &
+ TX_RING_MOD_MASK(tx_ring_size);
- /* Move dirty_tx to be the next bd */
- priv->dirty_tx = bdp;
+ howmany++;
+ priv->num_txbdfree += frags + 1;
+ }
+
+ /* If we freed a buffer, we can restart transmission, if necessary */
+ if (netif_queue_stopped(dev) && priv->num_txbdfree)
+ netif_wake_queue(dev);
- /* We freed a buffer, so now we can restart transmission */
- if (netif_queue_stopped(dev))
- netif_wake_queue(dev);
- } /* while ((bdp->status & TXBD_READY) == 0) */
+ /* Update dirty indicators */
+ priv->skb_dirtytx = skb_dirtytx;
+ priv->dirty_tx = bdp;
dev->stats.tx_packets += howmany;
return howmany;
}
-/* Interrupt Handler for Transmit complete */
-static irqreturn_t gfar_transmit(int irq, void *dev_id)
+static void gfar_schedule_cleanup(struct net_device *dev)
{
- struct net_device *dev = (struct net_device *) dev_id;
struct gfar_private *priv = netdev_priv(dev);
-
- /* Clear IEVENT */
- gfar_write(&priv->regs->ievent, IEVENT_TX_MASK);
-
- /* Lock priv */
- spin_lock(&priv->txlock);
-
- gfar_clean_tx_ring(dev);
-
- /* If we are coalescing the interrupts, reset the timer */
- /* Otherwise, clear it */
- if (likely(priv->txcoalescing)) {
- gfar_write(&priv->regs->txic, 0);
- gfar_write(&priv->regs->txic,
- mk_ic_value(priv->txcount, priv->txtime));
+ if (netif_rx_schedule_prep(&priv->napi)) {
+ gfar_write(&priv->regs->imask, IMASK_RTX_DISABLED);
+ __netif_rx_schedule(&priv->napi);
}
+}
- spin_unlock(&priv->txlock);
-
+/* Interrupt Handler for Transmit complete */
+static irqreturn_t gfar_transmit(int irq, void *dev_id)
+{
+ gfar_schedule_cleanup((struct net_device *)dev_id);
return IRQ_HANDLED;
}
@@ -1472,20 +1624,19 @@ static void gfar_new_rxbdp(struct net_device *dev, struct rxbd8 *bdp,
struct sk_buff *skb)
{
struct gfar_private *priv = netdev_priv(dev);
- u32 * status_len = (u32 *)bdp;
- u16 flags;
+ u32 lstatus;
bdp->bufPtr = dma_map_single(&dev->dev, skb->data,
priv->rx_buffer_size, DMA_FROM_DEVICE);
- flags = RXBD_EMPTY | RXBD_INTERRUPT;
+ lstatus = BD_LFLAG(RXBD_EMPTY | RXBD_INTERRUPT);
if (bdp == priv->rx_bd_base + priv->rx_ring_size - 1)
- flags |= RXBD_WRAP;
+ lstatus |= BD_LFLAG(RXBD_WRAP);
eieio();
- *status_len = (u32)flags << 16;
+ bdp->lstatus = lstatus;
}
@@ -1552,28 +1703,7 @@ static inline void count_errors(unsigned short status, struct net_device *dev)
irqreturn_t gfar_receive(int irq, void *dev_id)
{
- struct net_device *dev = (struct net_device *) dev_id;
- struct gfar_private *priv = netdev_priv(dev);
- u32 tempval;
-
- /* support NAPI */
- /* Clear IEVENT, so interrupts aren't called again
- * because of the packets that have already arrived */
- gfar_write(&priv->regs->ievent, IEVENT_RTX_MASK);
-
- if (netif_rx_schedule_prep(dev, &priv->napi)) {
- tempval = gfar_read(&priv->regs->imask);
- tempval &= IMASK_RTX_DISABLED;
- gfar_write(&priv->regs->imask, tempval);
-
- __netif_rx_schedule(dev, &priv->napi);
- } else {
- if (netif_msg_rx_err(priv))
- printk(KERN_DEBUG "%s: receive called twice (%x)[%x]\n",
- dev->name, gfar_read(&priv->regs->ievent),
- gfar_read(&priv->regs->imask));
- }
-
+ gfar_schedule_cleanup((struct net_device *)dev_id);
return IRQ_HANDLED;
}
@@ -1589,59 +1719,38 @@ static inline void gfar_rx_checksum(struct sk_buff *skb, struct rxfcb *fcb)
}
-static inline struct rxfcb *gfar_get_fcb(struct sk_buff *skb)
-{
- struct rxfcb *fcb = (struct rxfcb *)skb->data;
-
- /* Remove the FCB from the skb */
- skb_pull(skb, GMAC_FCB_LEN);
-
- return 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 length)
+ int amount_pull)
{
struct gfar_private *priv = netdev_priv(dev);
struct rxfcb *fcb = NULL;
- if (NULL == skb) {
- if (netif_msg_rx_err(priv))
- printk(KERN_WARNING "%s: Missing skb!!.\n", dev->name);
- dev->stats.rx_dropped++;
- priv->extra_stats.rx_skbmissing++;
- } else {
- int ret;
-
- /* Prep the skb for the packet */
- skb_put(skb, length);
+ int ret;
- /* Grab the FCB if there is one */
- if (gfar_uses_fcb(priv))
- fcb = gfar_get_fcb(skb);
+ /* fcb is at the beginning if exists */
+ fcb = (struct rxfcb *)skb->data;
- /* Remove the padded bytes, if there are any */
- if (priv->padding)
- skb_pull(skb, priv->padding);
+ /* Remove the FCB from the skb */
+ /* Remove the padded bytes, if there are any */
+ if (amount_pull)
+ skb_pull(skb, amount_pull);
- if (priv->rx_csum_enable)
- gfar_rx_checksum(skb, fcb);
+ if (priv->rx_csum_enable)
+ gfar_rx_checksum(skb, fcb);
- /* Tell the skb what kind of packet this is */
- skb->protocol = eth_type_trans(skb, dev);
+ /* Tell the skb what kind of packet this is */
+ skb->protocol = eth_type_trans(skb, dev);
- /* Send the packet up the stack */
- if (unlikely(priv->vlgrp && (fcb->flags & RXFCB_VLN))) {
- ret = vlan_hwaccel_receive_skb(skb, priv->vlgrp,
- fcb->vlctl);
- } else
- ret = netif_receive_skb(skb);
+ /* Send the packet up the stack */
+ if (unlikely(priv->vlgrp && (fcb->flags & RXFCB_VLN)))
+ ret = vlan_hwaccel_receive_skb(skb, priv->vlgrp, fcb->vlctl);
+ else
+ ret = netif_receive_skb(skb);
- if (NET_RX_DROP == ret)
- priv->extra_stats.kernel_dropped++;
- }
+ if (NET_RX_DROP == ret)
+ priv->extra_stats.kernel_dropped++;
return 0;
}
@@ -1652,14 +1761,19 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb,
*/
int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
{
- struct rxbd8 *bdp;
+ struct rxbd8 *bdp, *base;
struct sk_buff *skb;
- u16 pkt_len;
+ int pkt_len;
+ int amount_pull;
int howmany = 0;
struct gfar_private *priv = netdev_priv(dev);
/* Get the first full descriptor */
bdp = priv->cur_rx;
+ base = priv->rx_bd_base;
+
+ amount_pull = (gfar_uses_fcb(priv) ? GMAC_FCB_LEN : 0) +
+ priv->padding;
while (!((bdp->status & RXBD_EMPTY) || (--rx_work_limit < 0))) {
struct sk_buff *newskb;
@@ -1680,23 +1794,30 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
if (unlikely(!newskb))
newskb = skb;
-
- if (skb)
+ else if (skb)
dev_kfree_skb_any(skb);
} else {
/* Increment the number of packets */
dev->stats.rx_packets++;
howmany++;
- /* Remove the FCS from the packet length */
- pkt_len = bdp->length - 4;
+ if (likely(skb)) {
+ pkt_len = bdp->length - ETH_FCS_LEN;
+ /* Remove the FCS from the packet length */
+ skb_put(skb, pkt_len);
+ dev->stats.rx_bytes += pkt_len;
- gfar_process_frame(dev, skb, pkt_len);
+ gfar_process_frame(dev, skb, amount_pull);
- dev->stats.rx_bytes += pkt_len;
- }
+ } else {
+ if (netif_msg_rx_err(priv))
+ printk(KERN_WARNING
+ "%s: Missing skb!\n", dev->name);
+ dev->stats.rx_dropped++;
+ priv->extra_stats.rx_skbmissing++;
+ }
- dev->last_rx = jiffies;
+ }
priv->rx_skbuff[priv->skb_currx] = newskb;
@@ -1704,10 +1825,7 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit)
gfar_new_rxbdp(dev, bdp, newskb);
/* Update to the next pointer */
- if (bdp->status & RXBD_WRAP)
- bdp = priv->rx_bd_base;
- else
- bdp++;
+ bdp = next_bd(bdp, base, priv->rx_ring_size);
/* update to point at the next skb */
priv->skb_currx =
@@ -1725,19 +1843,27 @@ static int gfar_poll(struct napi_struct *napi, int budget)
{
struct gfar_private *priv = container_of(napi, struct gfar_private, napi);
struct net_device *dev = priv->dev;
- int howmany;
+ int tx_cleaned = 0;
+ int rx_cleaned = 0;
unsigned long flags;
+ /* Clear IEVENT, so interrupts aren't called again
+ * because of the packets that have already arrived */
+ gfar_write(&priv->regs->ievent, IEVENT_RTX_MASK);
+
/* If we fail to get the lock, don't bother with the TX BDs */
if (spin_trylock_irqsave(&priv->txlock, flags)) {
- gfar_clean_tx_ring(dev);
+ tx_cleaned = gfar_clean_tx_ring(dev);
spin_unlock_irqrestore(&priv->txlock, flags);
}
- howmany = gfar_clean_rx_ring(dev, budget);
+ rx_cleaned = gfar_clean_rx_ring(dev, budget);
+
+ if (tx_cleaned)
+ return budget;
- if (howmany < budget) {
- netif_rx_complete(dev, napi);
+ if (rx_cleaned < budget) {
+ netif_rx_complete(napi);
/* Clear the halt bit in RSTAT */
gfar_write(&priv->regs->rstat, RSTAT_CLEAR_RHALT);
@@ -1748,12 +1874,15 @@ static int gfar_poll(struct napi_struct *napi, int budget)
/* Otherwise, clear it */
if (likely(priv->rxcoalescing)) {
gfar_write(&priv->regs->rxic, 0);
- gfar_write(&priv->regs->rxic,
- mk_ic_value(priv->rxcount, priv->rxtime));
+ gfar_write(&priv->regs->rxic, priv->rxic);
+ }
+ if (likely(priv->txcoalescing)) {
+ gfar_write(&priv->regs->txic, 0);
+ gfar_write(&priv->regs->txic, priv->txic);
}
}
- return howmany;
+ return rx_cleaned;
}
#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1767,7 +1896,7 @@ static void gfar_netpoll(struct net_device *dev)
struct gfar_private *priv = netdev_priv(dev);
/* If the device has multiple interrupts, run tx/rx */
- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MULTI_INTR) {
disable_irq(priv->interruptTransmit);
disable_irq(priv->interruptReceive);
disable_irq(priv->interruptError);
@@ -2061,7 +2190,7 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
gfar_write(&priv->regs->ievent, events & IEVENT_ERR_MASK);
/* Magic Packet is not an error. */
- if ((priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
+ if ((priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
(events & IEVENT_MAG))
events &= ~IEVENT_MAG;
@@ -2127,16 +2256,24 @@ static irqreturn_t gfar_error(int irq, void *dev_id)
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:fsl-gianfar");
+static struct of_device_id gfar_match[] =
+{
+ {
+ .type = "network",
+ .compatible = "gianfar",
+ },
+ {},
+};
+
/* Structure for a device driver */
-static struct platform_driver gfar_driver = {
+static struct of_platform_driver gfar_driver = {
+ .name = "fsl-gianfar",
+ .match_table = gfar_match,
+
.probe = gfar_probe,
.remove = gfar_remove,
.suspend = gfar_suspend,
.resume = gfar_resume,
- .driver = {
- .name = "fsl-gianfar",
- .owner = THIS_MODULE,
- },
};
static int __init gfar_init(void)
@@ -2146,7 +2283,7 @@ static int __init gfar_init(void)
if (err)
return err;
- err = platform_driver_register(&gfar_driver);
+ err = of_register_platform_driver(&gfar_driver);
if (err)
gfar_mdio_exit();
@@ -2156,7 +2293,7 @@ static int __init gfar_init(void)
static void __exit gfar_exit(void)
{
- platform_driver_unregister(&gfar_driver);
+ of_unregister_platform_driver(&gfar_driver);
gfar_mdio_exit();
}
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h
index f46e9b63af13..b1a83344acc7 100644
--- a/drivers/net/gianfar.h
+++ b/drivers/net/gianfar.h
@@ -189,6 +189,18 @@ extern const char gfar_driver_version[];
#define mk_ic_value(count, time) (IC_ICEN | \
mk_ic_icft(count) | \
mk_ic_ictt(time))
+#define get_icft_value(ic) (((unsigned long)ic & IC_ICFT_MASK) >> \
+ IC_ICFT_SHIFT)
+#define get_ictt_value(ic) ((unsigned long)ic & IC_ICTT_MASK)
+
+#define DEFAULT_TXIC mk_ic_value(DEFAULT_TXCOUNT, DEFAULT_TXTIME)
+#define DEFAULT_RXIC mk_ic_value(DEFAULT_RXCOUNT, DEFAULT_RXTIME)
+
+#define skip_bd(bdp, stride, base, ring_size) ({ \
+ typeof(bdp) new_bd = (bdp) + (stride); \
+ (new_bd >= (base) + (ring_size)) ? (new_bd - (ring_size)) : new_bd; })
+
+#define next_bd(bdp, base, ring_size) skip_bd(bdp, 1, base, ring_size)
#define RCTRL_PAL_MASK 0x001f0000
#define RCTRL_VLEX 0x00002000
@@ -200,8 +212,10 @@ extern const char gfar_driver_version[];
#define RCTRL_PRSDEP_INIT 0x000000c0
#define RCTRL_PROM 0x00000008
#define RCTRL_EMEN 0x00000002
-#define RCTRL_CHECKSUMMING (RCTRL_IPCSEN \
- | RCTRL_TUCSEN | RCTRL_PRSDEP_INIT)
+#define RCTRL_REQ_PARSER (RCTRL_VLEX | RCTRL_IPCSEN | \
+ RCTRL_TUCSEN)
+#define RCTRL_CHECKSUMMING (RCTRL_IPCSEN | RCTRL_TUCSEN | \
+ RCTRL_PRSDEP_INIT)
#define RCTRL_EXTHASH (RCTRL_GHTX)
#define RCTRL_VLAN (RCTRL_PRSDEP_INIT)
#define RCTRL_PADDING(x) ((x << 16) & RCTRL_PAL_MASK)
@@ -237,7 +251,7 @@ extern const char gfar_driver_version[];
#define IEVENT_FIQ 0x00000004
#define IEVENT_DPE 0x00000002
#define IEVENT_PERR 0x00000001
-#define IEVENT_RX_MASK (IEVENT_RXB0 | IEVENT_RXF0)
+#define IEVENT_RX_MASK (IEVENT_RXB0 | IEVENT_RXF0 | IEVENT_BSY)
#define IEVENT_TX_MASK (IEVENT_TXB | IEVENT_TXF)
#define IEVENT_RTX_MASK (IEVENT_RX_MASK | IEVENT_TX_MASK)
#define IEVENT_ERR_MASK \
@@ -297,6 +311,8 @@ extern const char gfar_driver_version[];
#define ATTRELI_EI_MASK 0x00003fff
#define ATTRELI_EI(x) (x)
+#define BD_LFLAG(flags) ((flags) << 16)
+#define BD_LENGTH_MASK 0x00ff
/* TxBD status field bits */
#define TXBD_READY 0x8000
@@ -358,10 +374,17 @@ extern const char gfar_driver_version[];
#define RXFCB_PERR_MASK 0x000c
#define RXFCB_PERR_BADL3 0x0008
+#define GFAR_INT_NAME_MAX IFNAMSIZ + 4
+
struct txbd8
{
- u16 status; /* Status Fields */
- u16 length; /* Buffer length */
+ union {
+ struct {
+ u16 status; /* Status Fields */
+ u16 length; /* Buffer length */
+ };
+ u32 lstatus;
+ };
u32 bufPtr; /* Buffer Pointer */
};
@@ -376,8 +399,13 @@ struct txfcb {
struct rxbd8
{
- u16 status; /* Status Fields */
- u16 length; /* Buffer Length */
+ union {
+ struct {
+ u16 status; /* Status Fields */
+ u16 length; /* Buffer Length */
+ };
+ u32 lstatus;
+ };
u32 bufPtr; /* Buffer Pointer */
};
@@ -657,6 +685,19 @@ struct gfar {
};
+/* Flags related to gianfar device features */
+#define FSL_GIANFAR_DEV_HAS_GIGABIT 0x00000001
+#define FSL_GIANFAR_DEV_HAS_COALESCE 0x00000002
+#define FSL_GIANFAR_DEV_HAS_RMON 0x00000004
+#define FSL_GIANFAR_DEV_HAS_MULTI_INTR 0x00000008
+#define FSL_GIANFAR_DEV_HAS_CSUM 0x00000010
+#define FSL_GIANFAR_DEV_HAS_VLAN 0x00000020
+#define FSL_GIANFAR_DEV_HAS_EXTENDED_HASH 0x00000040
+#define FSL_GIANFAR_DEV_HAS_PADDING 0x00000080
+#define FSL_GIANFAR_DEV_HAS_MAGIC_PACKET 0x00000100
+#define FSL_GIANFAR_DEV_HAS_BD_STASHING 0x00000200
+#define FSL_GIANFAR_DEV_HAS_BUF_STASHING 0x00000400
+
/* Struct stolen almost completely (and shamelessly) from the FCC enet source
* (Ok, that's not so true anymore, but there is a family resemblence)
* The GFAR buffer descriptors track the ring buffers. The rx_bd_base
@@ -681,8 +722,7 @@ struct gfar_private {
/* Configuration info for the coalescing features */
unsigned char txcoalescing;
- unsigned short txcount;
- unsigned short txtime;
+ unsigned long txic;
/* Buffer descriptor pointers */
struct txbd8 *tx_bd_base; /* First tx buffer descriptor */
@@ -690,10 +730,12 @@ struct gfar_private {
struct txbd8 *dirty_tx; /* First buffer in line
to be transmitted */
unsigned int tx_ring_size;
+ unsigned int num_txbdfree; /* number of TxBDs free */
/* RX Locked fields */
spinlock_t rxlock;
+ struct device_node *node;
struct net_device *dev;
struct napi_struct napi;
@@ -703,8 +745,7 @@ struct gfar_private {
/* RX Coalescing values */
unsigned char rxcoalescing;
- unsigned short rxcount;
- unsigned short rxtime;
+ unsigned long rxic;
struct rxbd8 *rx_bd_base; /* First Rx buffers */
struct rxbd8 *cur_rx; /* Next free rx ring entry */
@@ -733,8 +774,10 @@ struct gfar_private {
/* Bitfield update lock */
spinlock_t bflock;
- unsigned char vlan_enable:1,
- rx_csum_enable:1,
+ phy_interface_t interface;
+ char phy_bus_id[BUS_ID_SIZE];
+ u32 device_flags;
+ unsigned char rx_csum_enable:1,
extended_hash:1,
bd_stash_en:1,
wol_en:1; /* Wake-on-LAN enabled */
@@ -744,11 +787,9 @@ struct gfar_private {
unsigned int interruptReceive;
unsigned int interruptError;
- /* info structure initialized by platform code */
- struct gianfar_platform_data *einfo;
-
/* PHY stuff */
struct phy_device *phydev;
+ struct phy_device *tbiphy;
struct mii_bus *mii_bus;
int oldspeed;
int oldduplex;
@@ -757,6 +798,11 @@ struct gfar_private {
uint32_t msg_enable;
struct work_struct reset_task;
+
+ char int_name_tx[GFAR_INT_NAME_MAX];
+ char int_name_rx[GFAR_INT_NAME_MAX];
+ char int_name_er[GFAR_INT_NAME_MAX];
+
/* Network Statistics */
struct gfar_extra_stats extra_stats;
};
diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c
index fb7d3ccc0fdc..59b3b5d98efe 100644
--- a/drivers/net/gianfar_ethtool.c
+++ b/drivers/net/gianfar_ethtool.c
@@ -121,7 +121,7 @@ static void gfar_gstrings(struct net_device *dev, u32 stringset, u8 * buf)
{
struct gfar_private *priv = netdev_priv(dev);
- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON)
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON)
memcpy(buf, stat_gstrings, GFAR_STATS_LEN * ETH_GSTRING_LEN);
else
memcpy(buf, stat_gstrings,
@@ -138,7 +138,7 @@ static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
struct gfar_private *priv = netdev_priv(dev);
u64 *extra = (u64 *) & priv->extra_stats;
- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON) {
u32 __iomem *rmon = (u32 __iomem *) & priv->regs->rmon;
struct gfar_stats *stats = (struct gfar_stats *) buf;
@@ -158,7 +158,7 @@ static int gfar_sset_count(struct net_device *dev, int sset)
switch (sset) {
case ETH_SS_STATS:
- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_RMON)
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_RMON)
return GFAR_STATS_LEN;
else
return GFAR_EXTRA_STATS_LEN;
@@ -201,8 +201,8 @@ static int gfar_gsettings(struct net_device *dev, struct ethtool_cmd *cmd)
if (NULL == phydev)
return -ENODEV;
- cmd->maxtxpkt = priv->txcount;
- cmd->maxrxpkt = priv->rxcount;
+ cmd->maxtxpkt = get_icft_value(priv->txic);
+ cmd->maxrxpkt = get_icft_value(priv->rxic);
return phy_ethtool_gset(phydev, cmd);
}
@@ -279,18 +279,26 @@ static unsigned int gfar_ticks2usecs(struct gfar_private *priv, unsigned int tic
static int gfar_gcoalesce(struct net_device *dev, struct ethtool_coalesce *cvals)
{
struct gfar_private *priv = netdev_priv(dev);
+ unsigned long rxtime;
+ unsigned long rxcount;
+ unsigned long txtime;
+ unsigned long txcount;
- if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
+ if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
return -EOPNOTSUPP;
if (NULL == priv->phydev)
return -ENODEV;
- cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, priv->rxtime);
- cvals->rx_max_coalesced_frames = priv->rxcount;
+ rxtime = get_ictt_value(priv->rxic);
+ rxcount = get_icft_value(priv->rxic);
+ txtime = get_ictt_value(priv->txic);
+ txcount = get_icft_value(priv->txic);;
+ cvals->rx_coalesce_usecs = gfar_ticks2usecs(priv, rxtime);
+ cvals->rx_max_coalesced_frames = rxcount;
- cvals->tx_coalesce_usecs = gfar_ticks2usecs(priv, priv->txtime);
- cvals->tx_max_coalesced_frames = priv->txcount;
+ cvals->tx_coalesce_usecs = gfar_ticks2usecs(priv, txtime);
+ cvals->tx_max_coalesced_frames = txcount;
cvals->use_adaptive_rx_coalesce = 0;
cvals->use_adaptive_tx_coalesce = 0;
@@ -332,7 +340,7 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
{
struct gfar_private *priv = netdev_priv(dev);
- if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
+ if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
return -EOPNOTSUPP;
/* Set up rx coalescing */
@@ -358,8 +366,9 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
return -EINVAL;
}
- priv->rxtime = gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs);
- priv->rxcount = cvals->rx_max_coalesced_frames;
+ priv->rxic = mk_ic_value(
+ gfar_usecs2ticks(priv, cvals->rx_coalesce_usecs),
+ cvals->rx_max_coalesced_frames);
/* Set up tx coalescing */
if ((cvals->tx_coalesce_usecs == 0) ||
@@ -381,20 +390,17 @@ static int gfar_scoalesce(struct net_device *dev, struct ethtool_coalesce *cvals
return -EINVAL;
}
- priv->txtime = gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs);
- priv->txcount = cvals->tx_max_coalesced_frames;
+ priv->txic = mk_ic_value(
+ gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs),
+ cvals->tx_max_coalesced_frames);
+ gfar_write(&priv->regs->rxic, 0);
if (priv->rxcoalescing)
- gfar_write(&priv->regs->rxic,
- mk_ic_value(priv->rxcount, priv->rxtime));
- else
- gfar_write(&priv->regs->rxic, 0);
+ gfar_write(&priv->regs->rxic, priv->rxic);
+ gfar_write(&priv->regs->txic, 0);
if (priv->txcoalescing)
- gfar_write(&priv->regs->txic,
- mk_ic_value(priv->txcount, priv->txtime));
- else
- gfar_write(&priv->regs->txic, 0);
+ gfar_write(&priv->regs->txic, priv->txic);
return 0;
}
@@ -456,11 +462,12 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva
spin_lock(&priv->rxlock);
gfar_halt(dev);
- gfar_clean_rx_ring(dev, priv->rx_ring_size);
spin_unlock(&priv->rxlock);
spin_unlock_irqrestore(&priv->txlock, flags);
+ gfar_clean_rx_ring(dev, priv->rx_ring_size);
+
/* Now we take down the rings to rebuild them */
stop_gfar(dev);
}
@@ -468,11 +475,13 @@ static int gfar_sringparam(struct net_device *dev, struct ethtool_ringparam *rva
/* Change the size */
priv->rx_ring_size = rvals->rx_pending;
priv->tx_ring_size = rvals->tx_pending;
+ priv->num_txbdfree = priv->tx_ring_size;
/* Rebuild the rings with the new size */
- if (dev->flags & IFF_UP)
+ if (dev->flags & IFF_UP) {
err = startup_gfar(dev);
-
+ netif_wake_queue(dev);
+ }
return err;
}
@@ -482,7 +491,7 @@ static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
unsigned long flags;
int err = 0;
- if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
+ if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
return -EOPNOTSUPP;
if (dev->flags & IFF_UP) {
@@ -492,11 +501,12 @@ static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
spin_lock(&priv->rxlock);
gfar_halt(dev);
- gfar_clean_rx_ring(dev, priv->rx_ring_size);
spin_unlock(&priv->rxlock);
spin_unlock_irqrestore(&priv->txlock, flags);
+ gfar_clean_rx_ring(dev, priv->rx_ring_size);
+
/* Now we take down the rings to rebuild them */
stop_gfar(dev);
}
@@ -505,9 +515,10 @@ static int gfar_set_rx_csum(struct net_device *dev, uint32_t data)
priv->rx_csum_enable = data;
spin_unlock_irqrestore(&priv->bflock, flags);
- if (dev->flags & IFF_UP)
+ if (dev->flags & IFF_UP) {
err = startup_gfar(dev);
-
+ netif_wake_queue(dev);
+ }
return err;
}
@@ -515,7 +526,7 @@ static uint32_t gfar_get_rx_csum(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
- if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
+ if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
return 0;
return priv->rx_csum_enable;
@@ -523,22 +534,19 @@ static uint32_t gfar_get_rx_csum(struct net_device *dev)
static int gfar_set_tx_csum(struct net_device *dev, uint32_t data)
{
- unsigned long flags;
struct gfar_private *priv = netdev_priv(dev);
- if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
+ if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
return -EOPNOTSUPP;
- spin_lock_irqsave(&priv->txlock, flags);
- gfar_halt(dev);
+ netif_tx_lock_bh(dev);
if (data)
dev->features |= NETIF_F_IP_CSUM;
else
dev->features &= ~NETIF_F_IP_CSUM;
- gfar_start(dev);
- spin_unlock_irqrestore(&priv->txlock, flags);
+ netif_tx_unlock_bh(dev);
return 0;
}
@@ -547,7 +555,7 @@ static uint32_t gfar_get_tx_csum(struct net_device *dev)
{
struct gfar_private *priv = netdev_priv(dev);
- if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
+ if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_CSUM))
return 0;
return (dev->features & NETIF_F_IP_CSUM) != 0;
@@ -570,7 +578,7 @@ static void gfar_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct gfar_private *priv = netdev_priv(dev);
- if (priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) {
+ if (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) {
wol->supported = WAKE_MAGIC;
wol->wolopts = priv->wol_en ? WAKE_MAGIC : 0;
} else {
@@ -583,7 +591,7 @@ static int gfar_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
struct gfar_private *priv = netdev_priv(dev);
unsigned long flags;
- if (!(priv->einfo->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
+ if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET) &&
wol->wolopts != 0)
return -EINVAL;
@@ -616,6 +624,7 @@ const struct ethtool_ops gfar_ethtool_ops = {
.get_tx_csum = gfar_get_tx_csum,
.set_rx_csum = gfar_set_rx_csum,
.set_tx_csum = gfar_set_tx_csum,
+ .set_sg = ethtool_op_set_sg,
.get_msglevel = gfar_get_msglevel,
.set_msglevel = gfar_set_msglevel,
#ifdef CONFIG_PM
diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c
index 0e2595d24933..f3706e415b45 100644
--- a/drivers/net/gianfar_mii.c
+++ b/drivers/net/gianfar_mii.c
@@ -34,6 +34,8 @@
#include <linux/crc32.h>
#include <linux/mii.h>
#include <linux/phy.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -150,19 +152,83 @@ static int gfar_mdio_reset(struct mii_bus *bus)
return 0;
}
+/* Allocate an array which provides irq #s for each PHY on the given bus */
+static int *create_irq_map(struct device_node *np)
+{
+ int *irqs;
+ int i;
+ struct device_node *child = NULL;
+
+ irqs = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL);
+
+ if (!irqs)
+ return NULL;
+
+ for (i = 0; i < PHY_MAX_ADDR; i++)
+ irqs[i] = PHY_POLL;
+
+ while ((child = of_get_next_child(np, child)) != NULL) {
+ int irq = irq_of_parse_and_map(child, 0);
+ const u32 *id;
+
+ if (irq == NO_IRQ)
+ continue;
+
+ id = of_get_property(child, "reg", NULL);
+
+ if (!id)
+ continue;
+
+ if (*id < PHY_MAX_ADDR && *id >= 0)
+ irqs[*id] = irq;
+ else
+ printk(KERN_WARNING "%s: "
+ "%d is not a valid PHY address\n",
+ np->full_name, *id);
+ }
+
+ return irqs;
+}
+
+
+void gfar_mdio_bus_name(char *name, struct device_node *np)
+{
+ const u32 *reg;
+
+ reg = of_get_property(np, "reg", NULL);
-static int gfar_mdio_probe(struct device *dev)
+ snprintf(name, MII_BUS_ID_SIZE, "%s@%x", np->name, reg ? *reg : 0);
+}
+
+/* Scan the bus in reverse, looking for an empty spot */
+static int gfar_mdio_find_free(struct mii_bus *new_bus)
+{
+ int i;
+
+ for (i = PHY_MAX_ADDR; i > 0; i--) {
+ u32 phy_id;
+
+ if (get_phy_id(new_bus, i, &phy_id))
+ return -1;
+
+ if (phy_id == 0xffffffff)
+ break;
+ }
+
+ return i;
+}
+
+static int gfar_mdio_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
{
- struct platform_device *pdev = to_platform_device(dev);
- struct gianfar_mdio_data *pdata;
struct gfar_mii __iomem *regs;
struct gfar __iomem *enet_regs;
struct mii_bus *new_bus;
- struct resource *r;
- int i, err = 0;
-
- if (NULL == dev)
- return -EINVAL;
+ int err = 0;
+ u64 addr, size;
+ struct device_node *np = ofdev->node;
+ struct device_node *tbi;
+ int tbiaddr = -1;
new_bus = mdiobus_alloc();
if (NULL == new_bus)
@@ -172,31 +238,28 @@ static int gfar_mdio_probe(struct device *dev)
new_bus->read = &gfar_mdio_read,
new_bus->write = &gfar_mdio_write,
new_bus->reset = &gfar_mdio_reset,
- snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
-
- pdata = (struct gianfar_mdio_data *)pdev->dev.platform_data;
-
- if (NULL == pdata) {
- printk(KERN_ERR "gfar mdio %d: Missing platform data!\n", pdev->id);
- return -ENODEV;
- }
-
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ gfar_mdio_bus_name(new_bus->id, np);
/* Set the PHY base address */
- regs = ioremap(r->start, sizeof (struct gfar_mii));
+ addr = of_translate_address(np, of_get_address(np, 0, &size, NULL));
+ regs = ioremap(addr, size);
if (NULL == regs) {
err = -ENOMEM;
- goto reg_map_fail;
+ goto err_free_bus;
}
new_bus->priv = (void __force *)regs;
- new_bus->irq = pdata->irq;
+ new_bus->irq = create_irq_map(np);
+
+ if (new_bus->irq == NULL) {
+ err = -ENOMEM;
+ goto err_unmap_regs;
+ }
- new_bus->parent = dev;
- dev_set_drvdata(dev, new_bus);
+ new_bus->parent = &ofdev->dev;
+ dev_set_drvdata(&ofdev->dev, new_bus);
/*
* This is mildly evil, but so is our hardware for doing this.
@@ -206,96 +269,109 @@ static int gfar_mdio_probe(struct device *dev)
enet_regs = (struct gfar __iomem *)
((char *)regs - offsetof(struct gfar, gfar_mii_regs));
- /* Scan the bus, looking for an empty spot for TBIPA */
- gfar_write(&enet_regs->tbipa, 0);
- for (i = PHY_MAX_ADDR; i > 0; i--) {
- u32 phy_id;
+ for_each_child_of_node(np, tbi) {
+ if (!strncmp(tbi->type, "tbi-phy", 8))
+ break;
+ }
- err = get_phy_id(new_bus, i, &phy_id);
- if (err)
- goto bus_register_fail;
+ if (tbi) {
+ const u32 *prop = of_get_property(tbi, "reg", NULL);
- if (phy_id == 0xffffffff)
- break;
+ if (prop)
+ tbiaddr = *prop;
}
- /* The bus is full. We don't support using 31 PHYs, sorry */
- if (i == 0) {
+ if (tbiaddr == -1) {
+ gfar_write(&enet_regs->tbipa, 0);
+
+ tbiaddr = gfar_mdio_find_free(new_bus);
+ }
+
+ /*
+ * We define TBIPA at 0 to be illegal, opting to fail for boards that
+ * have PHYs at 1-31, rather than change tbipa and rescan.
+ */
+ if (tbiaddr == 0) {
err = -EBUSY;
- goto bus_register_fail;
+ goto err_free_irqs;
}
- gfar_write(&enet_regs->tbipa, i);
+ gfar_write(&enet_regs->tbipa, tbiaddr);
+
+ /*
+ * The TBIPHY-only buses will find PHYs at every address,
+ * so we mask them all but the TBI
+ */
+ if (!of_device_is_compatible(np, "fsl,gianfar-mdio"))
+ new_bus->phy_mask = ~(1 << tbiaddr);
err = mdiobus_register(new_bus);
- if (0 != err) {
+ if (err != 0) {
printk (KERN_ERR "%s: Cannot register as MDIO bus\n",
new_bus->name);
- goto bus_register_fail;
+ goto err_free_irqs;
}
return 0;
-bus_register_fail:
+err_free_irqs:
+ kfree(new_bus->irq);
+err_unmap_regs:
iounmap(regs);
-reg_map_fail:
+err_free_bus:
mdiobus_free(new_bus);
return err;
}
-static int gfar_mdio_remove(struct device *dev)
+static int gfar_mdio_remove(struct of_device *ofdev)
{
- struct mii_bus *bus = dev_get_drvdata(dev);
+ struct mii_bus *bus = dev_get_drvdata(&ofdev->dev);
mdiobus_unregister(bus);
- dev_set_drvdata(dev, NULL);
+ dev_set_drvdata(&ofdev->dev, NULL);
iounmap((void __iomem *)bus->priv);
bus->priv = NULL;
+ kfree(bus->irq);
mdiobus_free(bus);
return 0;
}
-static struct device_driver gianfar_mdio_driver = {
+static struct of_device_id gfar_mdio_match[] =
+{
+ {
+ .compatible = "fsl,gianfar-mdio",
+ },
+ {
+ .compatible = "fsl,gianfar-tbi",
+ },
+ {
+ .type = "mdio",
+ .compatible = "gianfar",
+ },
+ {},
+};
+
+static struct of_platform_driver gianfar_mdio_driver = {
.name = "fsl-gianfar_mdio",
- .bus = &platform_bus_type,
+ .match_table = gfar_mdio_match,
+
.probe = gfar_mdio_probe,
.remove = gfar_mdio_remove,
};
-static int match_mdio_bus(struct device *dev, void *data)
-{
- const struct gfar_private *priv = data;
- const struct platform_device *pdev = to_platform_device(dev);
-
- return !strcmp(pdev->name, gianfar_mdio_driver.name) &&
- pdev->id == priv->einfo->mdio_bus;
-}
-
-/* Given a gfar_priv structure, find the mii_bus controlled by this device (not
- * necessarily the same as the bus the gfar's PHY is on), if one exists.
- * Normally only the first gianfar controls a mii_bus. */
-struct mii_bus *gfar_get_miibus(const struct gfar_private *priv)
-{
- /*const*/ struct device *d;
-
- d = bus_find_device(gianfar_mdio_driver.bus, NULL, (void *)priv,
- match_mdio_bus);
- return d ? dev_get_drvdata(d) : NULL;
-}
-
int __init gfar_mdio_init(void)
{
- return driver_register(&gianfar_mdio_driver);
+ return of_register_platform_driver(&gianfar_mdio_driver);
}
void gfar_mdio_exit(void)
{
- driver_unregister(&gianfar_mdio_driver);
+ of_unregister_platform_driver(&gianfar_mdio_driver);
}
diff --git a/drivers/net/gianfar_mii.h b/drivers/net/gianfar_mii.h
index 02dc970ca1ff..65c242cd468a 100644
--- a/drivers/net/gianfar_mii.h
+++ b/drivers/net/gianfar_mii.h
@@ -49,4 +49,6 @@ int gfar_local_mdio_read(struct gfar_mii __iomem *regs, int mii_id, int regnum);
struct mii_bus *gfar_get_miibus(const struct gfar_private *priv);
int __init gfar_mdio_init(void);
void gfar_mdio_exit(void);
+
+void gfar_mdio_bus_name(char *name, struct device_node *np);
#endif /* GIANFAR_PHY_H */
diff --git a/drivers/net/hamachi.c b/drivers/net/hamachi.c
index 3199526bcecb..32200227c923 100644
--- a/drivers/net/hamachi.c
+++ b/drivers/net/hamachi.c
@@ -568,6 +568,19 @@ static void set_rx_mode(struct net_device *dev);
static const struct ethtool_ops ethtool_ops;
static const struct ethtool_ops ethtool_ops_no_mii;
+static const struct net_device_ops hamachi_netdev_ops = {
+ .ndo_open = hamachi_open,
+ .ndo_stop = hamachi_close,
+ .ndo_start_xmit = hamachi_start_xmit,
+ .ndo_get_stats = hamachi_get_stats,
+ .ndo_set_multicast_list = set_rx_mode,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_tx_timeout = hamachi_tx_timeout,
+ .ndo_do_ioctl = netdev_ioctl,
+};
+
+
static int __devinit hamachi_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -582,7 +595,6 @@ static int __devinit hamachi_init_one (struct pci_dev *pdev,
void *ring_space;
dma_addr_t ring_dma;
int ret = -ENOMEM;
- DECLARE_MAC_BUF(mac);
/* when built into the kernel, we only print version if device is found */
#ifndef MODULE
@@ -723,17 +735,11 @@ static int __devinit hamachi_init_one (struct pci_dev *pdev,
/* The Hamachi-specific entries in the device structure. */
- dev->open = &hamachi_open;
- dev->hard_start_xmit = &hamachi_start_xmit;
- dev->stop = &hamachi_close;
- dev->get_stats = &hamachi_get_stats;
- dev->set_multicast_list = &set_rx_mode;
- dev->do_ioctl = &netdev_ioctl;
+ dev->netdev_ops = &hamachi_netdev_ops;
if (chip_tbl[hmp->chip_id].flags & CanHaveMII)
SET_ETHTOOL_OPS(dev, &ethtool_ops);
else
SET_ETHTOOL_OPS(dev, &ethtool_ops_no_mii);
- dev->tx_timeout = &hamachi_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
if (mtu)
dev->mtu = mtu;
@@ -744,9 +750,9 @@ static int __devinit hamachi_init_one (struct pci_dev *pdev,
goto err_out_unmap_rx;
}
- printk(KERN_INFO "%s: %s type %x at %p, %s, IRQ %d.\n",
+ printk(KERN_INFO "%s: %s type %x at %p, %pM, IRQ %d.\n",
dev->name, chip_tbl[chip_id].name, readl(ioaddr + ChipRev),
- ioaddr, print_mac(mac, dev->dev_addr), irq);
+ ioaddr, dev->dev_addr, irq);
i = readb(ioaddr + PCIClkMeas);
printk(KERN_INFO "%s: %d-bit %d Mhz PCI bus (%d), Virtual Jumpers "
"%2.2x, LPA %4.4x.\n",
@@ -1646,7 +1652,6 @@ static int hamachi_rx(struct net_device *dev)
#endif /* RX_CHECKSUM */
netif_rx(skb);
- dev->last_rx = jiffies;
hmp->stats.rx_packets++;
}
entry = (++hmp->cur_rx) % RX_RING_SIZE;
diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
index 0f501d2ca935..50f1e172ee8f 100644
--- a/drivers/net/hamradio/6pack.c
+++ b/drivers/net/hamradio/6pack.c
@@ -373,7 +373,6 @@ static void sp_bump(struct sixpack *sp, char cmd)
memcpy(ptr, sp->cooked_buf + 1, count);
skb->protocol = ax25_type_trans(skb, sp->dev);
netif_rx(skb);
- sp->dev->last_rx = jiffies;
sp->dev->stats.rx_packets++;
return;
diff --git a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
index 00bc7fbb6b37..81a65e3a1c05 100644
--- a/drivers/net/hamradio/baycom_epp.c
+++ b/drivers/net/hamradio/baycom_epp.c
@@ -555,7 +555,6 @@ static void do_rxpacket(struct net_device *dev)
memcpy(cp, bc->hdlcrx.buf, pktlen - 1);
skb->protocol = ax25_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
bc->stats.rx_packets++;
}
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 58f4b1d7bf1f..46f8f3390e7d 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -230,7 +230,6 @@ static int bpq_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
skb->protocol = ax25_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
unlock:
rcu_read_unlock();
@@ -441,16 +440,15 @@ static int bpq_seq_show(struct seq_file *seq, void *v)
"dev ether destination accept from\n");
else {
const struct bpqdev *bpqdev = v;
- DECLARE_MAC_BUF(mac);
- seq_printf(seq, "%-5s %-10s %s ",
+ seq_printf(seq, "%-5s %-10s %pM ",
bpqdev->axdev->name, bpqdev->ethdev->name,
- print_mac(mac, bpqdev->dest_addr));
+ bpqdev->dest_addr);
if (is_multicast_ether_addr(bpqdev->acpt_addr))
seq_printf(seq, "*\n");
else
- seq_printf(seq, "%s\n", print_mac(mac, bpqdev->acpt_addr));
+ seq_printf(seq, "%pM\n", bpqdev->acpt_addr);
}
return 0;
diff --git a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
index e8cfadefa4b6..e67103396ed7 100644
--- a/drivers/net/hamradio/dmascc.c
+++ b/drivers/net/hamradio/dmascc.c
@@ -572,7 +572,7 @@ static int __init setup_adapter(int card_base, int type, int n)
priv->param.persist = 256;
priv->param.dma = -1;
INIT_WORK(&priv->rx_work, rx_bh);
- dev->priv = priv;
+ dev->ml_priv = priv;
sprintf(dev->name, "dmascc%i", 2 * n + i);
dev->base_addr = card_base;
dev->irq = irq;
@@ -720,7 +720,7 @@ static int read_scc_data(struct scc_priv *priv)
static int scc_open(struct net_device *dev)
{
- struct scc_priv *priv = dev->priv;
+ struct scc_priv *priv = dev->ml_priv;
struct scc_info *info = priv->info;
int card_base = priv->card_base;
@@ -862,7 +862,7 @@ static int scc_open(struct net_device *dev)
static int scc_close(struct net_device *dev)
{
- struct scc_priv *priv = dev->priv;
+ struct scc_priv *priv = dev->ml_priv;
struct scc_info *info = priv->info;
int card_base = priv->card_base;
@@ -891,7 +891,7 @@ static int scc_close(struct net_device *dev)
static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
- struct scc_priv *priv = dev->priv;
+ struct scc_priv *priv = dev->ml_priv;
switch (cmd) {
case SIOCGSCCPARAM:
@@ -918,7 +918,7 @@ static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
static int scc_send_packet(struct sk_buff *skb, struct net_device *dev)
{
- struct scc_priv *priv = dev->priv;
+ struct scc_priv *priv = dev->ml_priv;
unsigned long flags;
int i;
@@ -963,7 +963,7 @@ static int scc_send_packet(struct sk_buff *skb, struct net_device *dev)
static struct net_device_stats *scc_get_stats(struct net_device *dev)
{
- struct scc_priv *priv = dev->priv;
+ struct scc_priv *priv = dev->ml_priv;
return &priv->stats;
}
@@ -1283,7 +1283,6 @@ static void rx_bh(struct work_struct *ugli_api)
memcpy(&data[1], priv->rx_buf[i], cb);
skb->protocol = ax25_type_trans(skb, priv->dev);
netif_rx(skb);
- priv->dev->last_rx = jiffies;
priv->stats.rx_packets++;
priv->stats.rx_bytes += cb;
}
diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
index c258a0586e61..8eba61a1d4ab 100644
--- a/drivers/net/hamradio/hdlcdrv.c
+++ b/drivers/net/hamradio/hdlcdrv.c
@@ -162,7 +162,6 @@ static void hdlc_rx_flag(struct net_device *dev, struct hdlcdrv_state *s)
memcpy(cp, s->hdlcrx.buffer, pkt_len - 1);
skb->protocol = ax25_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
s->stats.rx_packets++;
}
diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
index b8e25c4624d2..bbdb311b8420 100644
--- a/drivers/net/hamradio/mkiss.c
+++ b/drivers/net/hamradio/mkiss.c
@@ -303,7 +303,6 @@ static void ax_bump(struct mkiss *ax)
memcpy(skb_put(skb,count), ax->rbuff, count);
skb->protocol = ax25_type_trans(skb, ax->dev);
netif_rx(skb);
- ax->dev->last_rx = jiffies;
ax->stats.rx_packets++;
ax->stats.rx_bytes += count;
spin_unlock_bh(&ax->buflock);
@@ -847,12 +846,13 @@ static int mkiss_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct mkiss *ax = mkiss_get(tty);
- struct net_device *dev = ax->dev;
+ struct net_device *dev;
unsigned int tmp, err;
/* First make sure we're connected. */
if (ax == NULL)
return -ENXIO;
+ dev = ax->dev;
switch (cmd) {
case SIOCGIFNAME:
diff --git a/drivers/net/hamradio/scc.c b/drivers/net/hamradio/scc.c
index c17e39bc5460..c011af7088ea 100644
--- a/drivers/net/hamradio/scc.c
+++ b/drivers/net/hamradio/scc.c
@@ -1518,7 +1518,7 @@ static int scc_net_alloc(const char *name, struct scc_channel *scc)
if (!dev)
return -ENOMEM;
- dev->priv = scc;
+ dev->ml_priv = scc;
scc->dev = dev;
spin_lock_init(&scc->lock);
init_timer(&scc->tx_t);
@@ -1575,7 +1575,7 @@ static void scc_net_setup(struct net_device *dev)
static int scc_net_open(struct net_device *dev)
{
- struct scc_channel *scc = (struct scc_channel *) dev->priv;
+ struct scc_channel *scc = (struct scc_channel *) dev->ml_priv;
if (!scc->init)
return -EINVAL;
@@ -1593,7 +1593,7 @@ static int scc_net_open(struct net_device *dev)
static int scc_net_close(struct net_device *dev)
{
- struct scc_channel *scc = (struct scc_channel *) dev->priv;
+ struct scc_channel *scc = (struct scc_channel *) dev->ml_priv;
unsigned long flags;
netif_stop_queue(dev);
@@ -1627,7 +1627,6 @@ static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb)
skb->protocol = ax25_type_trans(skb, scc->dev);
netif_rx(skb);
- scc->dev->last_rx = jiffies;
return;
}
@@ -1635,7 +1634,7 @@ static void scc_net_rx(struct scc_channel *scc, struct sk_buff *skb)
static int scc_net_tx(struct sk_buff *skb, struct net_device *dev)
{
- struct scc_channel *scc = (struct scc_channel *) dev->priv;
+ struct scc_channel *scc = (struct scc_channel *) dev->ml_priv;
unsigned long flags;
char kisscmd;
@@ -1705,7 +1704,7 @@ static int scc_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
struct scc_mem_config memcfg;
struct scc_hw_config hwcfg;
struct scc_calibrate cal;
- struct scc_channel *scc = (struct scc_channel *) dev->priv;
+ struct scc_channel *scc = (struct scc_channel *) dev->ml_priv;
int chan;
unsigned char device_name[IFNAMSIZ];
void __user *arg = ifr->ifr_data;
@@ -1952,7 +1951,7 @@ static int scc_net_set_mac_address(struct net_device *dev, void *addr)
static struct net_device_stats *scc_net_get_stats(struct net_device *dev)
{
- struct scc_channel *scc = (struct scc_channel *) dev->priv;
+ struct scc_channel *scc = (struct scc_channel *) dev->ml_priv;
scc->dev_stat.rx_errors = scc->stat.rxerrs + scc->stat.rx_over;
scc->dev_stat.tx_errors = scc->stat.txerrs + scc->stat.tx_under;
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
index 1c942862a3f4..5407f7486c9c 100644
--- a/drivers/net/hamradio/yam.c
+++ b/drivers/net/hamradio/yam.c
@@ -515,7 +515,6 @@ static inline void yam_rx_flag(struct net_device *dev, struct yam_port *yp)
memcpy(cp, yp->rx_buf, pkt_len - 1);
skb->protocol = ax25_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
++yp->stats.rx_packets;
}
}
diff --git a/drivers/net/hp-plus.c b/drivers/net/hp-plus.c
index c01e290d09d2..b507dbc16e62 100644
--- a/drivers/net/hp-plus.c
+++ b/drivers/net/hp-plus.c
@@ -158,6 +158,21 @@ out:
}
#endif
+static const struct net_device_ops hpp_netdev_ops = {
+ .ndo_open = hpp_open,
+ .ndo_stop = hpp_close,
+ .ndo_start_xmit = eip_start_xmit,
+ .ndo_tx_timeout = eip_tx_timeout,
+ .ndo_get_stats = eip_get_stats,
+ .ndo_set_multicast_list = eip_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = eip_poll,
+#endif
+};
+
+
/* Do the interesting part of the probe at a single address. */
static int __init hpp_probe1(struct net_device *dev, int ioaddr)
{
@@ -166,7 +181,6 @@ static int __init hpp_probe1(struct net_device *dev, int ioaddr)
const char name[] = "HP-PC-LAN+";
int mem_start;
static unsigned version_printed;
- DECLARE_MAC_BUF(mac);
if (!request_region(ioaddr, HP_IO_EXTENT, DRV_NAME))
return -EBUSY;
@@ -193,7 +207,7 @@ static int __init hpp_probe1(struct net_device *dev, int ioaddr)
}
checksum += inb(ioaddr + 14);
- printk("%s", print_mac(mac, dev->dev_addr));
+ printk("%pM", dev->dev_addr);
if (checksum != 0xff) {
printk(" bad checksum %2.2x.\n", checksum);
@@ -227,11 +241,7 @@ static int __init hpp_probe1(struct net_device *dev, int ioaddr)
/* Set the base address to point to the NIC, not the "real" base! */
dev->base_addr = ioaddr + NIC_OFFSET;
- dev->open = &hpp_open;
- dev->stop = &hpp_close;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = eip_poll;
-#endif
+ dev->netdev_ops = &hpp_netdev_ops;
ei_status.name = name;
ei_status.word16 = 0; /* Agggghhhhh! Debug time: 2 days! */
@@ -302,8 +312,7 @@ hpp_open(struct net_device *dev)
/* Select the operational page. */
outw(Perf_Page, ioaddr + HP_PAGING);
- eip_open(dev);
- return 0;
+ return eip_open(dev);
}
static int
diff --git a/drivers/net/hp.c b/drivers/net/hp.c
index 0a8c64930ad3..5c4d78c1ff42 100644
--- a/drivers/net/hp.c
+++ b/drivers/net/hp.c
@@ -59,8 +59,6 @@ static unsigned int hppclan_portlist[] __initdata =
static int hp_probe1(struct net_device *dev, int ioaddr);
-static int hp_open(struct net_device *dev);
-static int hp_close(struct net_device *dev);
static void hp_reset_8390(struct net_device *dev);
static void hp_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
int ring_page);
@@ -127,7 +125,6 @@ static int __init hp_probe1(struct net_device *dev, int ioaddr)
int i, retval, board_id, wordmode;
const char *name;
static unsigned version_printed;
- DECLARE_MAC_BUF(mac);
if (!request_region(ioaddr, HP_IO_EXTENT, DRV_NAME))
return -EBUSY;
@@ -161,7 +158,7 @@ static int __init hp_probe1(struct net_device *dev, int ioaddr)
for(i = 0; i < ETHER_ADDR_LEN; i++)
dev->dev_addr[i] = inb(ioaddr + i);
- printk(" %s", print_mac(mac, dev->dev_addr));
+ printk(" %pM", dev->dev_addr);
/* Snarf the interrupt now. Someday this could be moved to open(). */
if (dev->irq < 2) {
@@ -199,11 +196,7 @@ static int __init hp_probe1(struct net_device *dev, int ioaddr)
/* Set the base address to point to the NIC, not the "real" base! */
dev->base_addr = ioaddr + NIC_OFFSET;
- dev->open = &hp_open;
- dev->stop = &hp_close;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = eip_poll;
-#endif
+ dev->netdev_ops = &eip_netdev_ops;
ei_status.name = name;
ei_status.word16 = wordmode;
@@ -228,20 +221,6 @@ out:
return retval;
}
-static int
-hp_open(struct net_device *dev)
-{
- eip_open(dev);
- return 0;
-}
-
-static int
-hp_close(struct net_device *dev)
-{
- eip_close(dev);
- return 0;
-}
-
static void
hp_reset_8390(struct net_device *dev)
{
diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c
index 571dd80fb850..ebe7651fcb86 100644
--- a/drivers/net/hp100.c
+++ b/drivers/net/hp100.c
@@ -1212,7 +1212,7 @@ static int hp100_init_rxpdl(struct net_device *dev,
*(pdlptr + 2) = (u_int) virt_to_whatever(dev, pdlptr); /* Address Frag 1 */
*(pdlptr + 3) = 4; /* Length Frag 1 */
- return ((((MAX_RX_FRAG * 2 + 2) + 3) / 4) * 4);
+ return roundup(MAX_RX_FRAG * 2 + 2, 4);
}
@@ -1227,7 +1227,7 @@ static int hp100_init_txpdl(struct net_device *dev,
ringptr->pdl_paddr = virt_to_whatever(dev, pdlptr); /* +1 */
ringptr->skb = (void *) NULL;
- return ((((MAX_TX_FRAG * 2 + 2) + 3) / 4) * 4);
+ return roundup(MAX_TX_FRAG * 2 + 2, 4);
}
/*
@@ -1256,7 +1256,7 @@ static int hp100_build_rx_pdl(hp100_ring_t * ringptr,
/* Note: This depends on the alloc_skb functions allocating more
* space than requested, i.e. aligning to 16bytes */
- ringptr->skb = dev_alloc_skb(((MAX_ETHER_SIZE + 2 + 3) / 4) * 4);
+ ringptr->skb = dev_alloc_skb(roundup(MAX_ETHER_SIZE + 2, 4));
if (NULL != ringptr->skb) {
/*
@@ -1279,7 +1279,7 @@ static int hp100_build_rx_pdl(hp100_ring_t * ringptr,
#ifdef HP100_DEBUG_BM
printk("hp100: %s: build_rx_pdl: PDH@0x%x, skb->data (len %d) at 0x%x\n",
dev->name, (u_int) ringptr->pdl,
- ((MAX_ETHER_SIZE + 2 + 3) / 4) * 4,
+ roundup(MAX_ETHER_SIZE + 2, 4),
(unsigned int) ringptr->skb->data);
#endif
@@ -1834,7 +1834,6 @@ static void hp100_rx(struct net_device *dev)
ptr[9], ptr[10], ptr[11]);
#endif
netif_rx(skb);
- dev->last_rx = jiffies;
lp->stats.rx_packets++;
lp->stats.rx_bytes += pkt_len;
}
@@ -1925,7 +1924,6 @@ static void hp100_rx_bm(struct net_device *dev)
netif_rx(ptr->skb); /* Up and away... */
- dev->last_rx = jiffies;
lp->stats.rx_packets++;
lp->stats.rx_bytes += pkt_len;
}
@@ -2093,9 +2091,8 @@ static void hp100_set_multicast_list(struct net_device *dev)
addrs = dmi->dmi_addr;
if ((*addrs & 0x01) == 0x01) { /* multicast address? */
#ifdef HP100_DEBUG
- DECLARE_MAC_BUF(mac);
- printk("hp100: %s: multicast = %s, ",
- dev->name, print_mac(mac, addrs));
+ printk("hp100: %s: multicast = %pM, ",
+ dev->name, addrs);
#endif
for (j = idx = 0; j < 6; j++) {
idx ^= *addrs++ & 0x3f;
@@ -3057,12 +3054,3 @@ static void __exit hp100_module_exit(void)
module_init(hp100_module_init)
module_exit(hp100_module_exit)
-
-
-/*
- * Local variables:
- * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c hp100.c"
- * c-indent-level: 2
- * tab-width: 8
- * End:
- */
diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c
index b96cf2dcb109..9cb38a8d4387 100644
--- a/drivers/net/hydra.c
+++ b/drivers/net/hydra.c
@@ -94,6 +94,21 @@ static int __devinit hydra_init_one(struct zorro_dev *z,
return 0;
}
+static const struct net_device_ops hydra_netdev_ops = {
+ .ndo_open = hydra_open,
+ .ndo_stop = hydra_close,
+
+ .ndo_start_xmit = ei_start_xmit,
+ .ndo_tx_timeout = ei_tx_timeout,
+ .ndo_get_stats = ei_get_stats,
+ .ndo_set_multicast_list = ei_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = ei_poll,
+#endif
+};
+
static int __devinit hydra_init(struct zorro_dev *z)
{
struct net_device *dev;
@@ -103,14 +118,13 @@ static int __devinit hydra_init(struct zorro_dev *z)
int start_page, stop_page;
int j;
int err;
- DECLARE_MAC_BUF(mac);
static u32 hydra_offsets[16] = {
0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
};
- dev = ____alloc_ei_netdev(0);
+ dev = alloc_ei_netdev();
if (!dev)
return -ENOMEM;
@@ -145,12 +159,8 @@ static int __devinit hydra_init(struct zorro_dev *z)
ei_status.block_output = &hydra_block_output;
ei_status.get_8390_hdr = &hydra_get_8390_hdr;
ei_status.reg_offset = hydra_offsets;
- dev->open = &hydra_open;
- dev->stop = &hydra_close;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = __ei_poll;
-#endif
+ dev->netdev_ops = &hydra_netdev_ops;
__NS8390_init(dev, 0);
err = register_netdev(dev);
@@ -163,8 +173,8 @@ static int __devinit hydra_init(struct zorro_dev *z)
zorro_set_drvdata(z, dev);
printk(KERN_INFO "%s: Hydra at 0x%08lx, address "
- "%s (hydra.c " HYDRA_VERSION ")\n",
- dev->name, z->resource.start, print_mac(mac, dev->dev_addr));
+ "%pM (hydra.c " HYDRA_VERSION ")\n",
+ dev->name, z->resource.start, dev->dev_addr);
return 0;
}
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index 901212aa37cb..87a706694fb3 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -396,9 +396,7 @@ static void emac_hash_mc(struct emac_instance *dev)
for (dmi = dev->ndev->mc_list; dmi; dmi = dmi->next) {
int slot, reg, mask;
- DBG2(dev, "mc %02x:%02x:%02x:%02x:%02x:%02x" NL,
- dmi->dmi_addr[0], dmi->dmi_addr[1], dmi->dmi_addr[2],
- dmi->dmi_addr[3], dmi->dmi_addr[4], dmi->dmi_addr[5]);
+ DBG2(dev, "mc %pM" NL, dmi->dmi_addr);
slot = EMAC_XAHT_CRC_TO_SLOT(dev, ether_crc(ETH_ALEN, dmi->dmi_addr));
reg = EMAC_XAHT_SLOT_TO_REG(dev, slot);
@@ -2865,11 +2863,8 @@ static int __devinit emac_probe(struct of_device *ofdev,
wake_up_all(&emac_probe_wait);
- printk(KERN_INFO
- "%s: EMAC-%d %s, MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
- ndev->name, dev->cell_index, np->full_name,
- ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
- ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
+ printk(KERN_INFO "%s: EMAC-%d %s, MAC %pM\n",
+ ndev->name, dev->cell_index, np->full_name, ndev->dev_addr);
if (dev->phy_mode == PHY_MODE_SGMII)
printk(KERN_NOTICE "%s: in SGMII mode\n", ndev->name);
diff --git a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c
index f02764725a22..5b5bf9f9861a 100644
--- a/drivers/net/ibmlana.c
+++ b/drivers/net/ibmlana.c
@@ -605,7 +605,6 @@ static void irqrx_handler(struct net_device *dev)
skb->ip_summed = CHECKSUM_NONE;
/* bookkeeping */
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += rda.length;
@@ -914,7 +913,6 @@ static int __devinit ibmlana_init_one(struct device *kdev)
int base = 0, irq = 0, iobase = 0, memlen = 0;
ibmlana_priv *priv;
ibmlana_medium medium;
- DECLARE_MAC_BUF(mac);
dev = alloc_etherdev(sizeof(ibmlana_priv));
if (!dev)
@@ -990,10 +988,10 @@ static int __devinit ibmlana_init_one(struct device *kdev)
/* print config */
printk(KERN_INFO "%s: IRQ %d, I/O %#lx, memory %#lx-%#lx, "
- "MAC address %s.\n",
+ "MAC address %pM.\n",
dev->name, priv->realirq, dev->base_addr,
dev->mem_start, dev->mem_end - 1,
- print_mac(mac, dev->dev_addr));
+ dev->dev_addr);
printk(KERN_INFO "%s: %s medium\n", dev->name, MediaNames[priv->medium]);
/* reset board */
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c
index c2d57f836088..9bc0f178f24b 100644
--- a/drivers/net/ibmveth.c
+++ b/drivers/net/ibmveth.c
@@ -527,7 +527,7 @@ retry:
static int ibmveth_open(struct net_device *netdev)
{
- struct ibmveth_adapter *adapter = netdev->priv;
+ struct ibmveth_adapter *adapter = netdev_priv(netdev);
u64 mac_address = 0;
int rxq_entries = 1;
unsigned long lpar_rc;
@@ -666,7 +666,7 @@ static int ibmveth_open(struct net_device *netdev)
static int ibmveth_close(struct net_device *netdev)
{
- struct ibmveth_adapter *adapter = netdev->priv;
+ struct ibmveth_adapter *adapter = netdev_priv(netdev);
long lpar_rc;
ibmveth_debug_printk("close starting\n");
@@ -722,7 +722,7 @@ static u32 netdev_get_link(struct net_device *dev) {
static void ibmveth_set_rx_csum_flags(struct net_device *dev, u32 data)
{
- struct ibmveth_adapter *adapter = dev->priv;
+ struct ibmveth_adapter *adapter = netdev_priv(dev);
if (data)
adapter->rx_csum = 1;
@@ -741,7 +741,7 @@ static void ibmveth_set_rx_csum_flags(struct net_device *dev, u32 data)
static void ibmveth_set_tx_csum_flags(struct net_device *dev, u32 data)
{
- struct ibmveth_adapter *adapter = dev->priv;
+ struct ibmveth_adapter *adapter = netdev_priv(dev);
if (data) {
dev->features |= NETIF_F_IP_CSUM;
@@ -753,7 +753,7 @@ static void ibmveth_set_tx_csum_flags(struct net_device *dev, u32 data)
static int ibmveth_set_csum_offload(struct net_device *dev, u32 data,
void (*done) (struct net_device *, u32))
{
- struct ibmveth_adapter *adapter = dev->priv;
+ struct ibmveth_adapter *adapter = netdev_priv(dev);
u64 set_attr, clr_attr, ret_attr;
long ret;
int rc1 = 0, rc2 = 0;
@@ -805,7 +805,7 @@ static int ibmveth_set_csum_offload(struct net_device *dev, u32 data,
static int ibmveth_set_rx_csum(struct net_device *dev, u32 data)
{
- struct ibmveth_adapter *adapter = dev->priv;
+ struct ibmveth_adapter *adapter = netdev_priv(dev);
if ((data && adapter->rx_csum) || (!data && !adapter->rx_csum))
return 0;
@@ -815,7 +815,7 @@ static int ibmveth_set_rx_csum(struct net_device *dev, u32 data)
static int ibmveth_set_tx_csum(struct net_device *dev, u32 data)
{
- struct ibmveth_adapter *adapter = dev->priv;
+ struct ibmveth_adapter *adapter = netdev_priv(dev);
int rc = 0;
if (data && (dev->features & NETIF_F_IP_CSUM))
@@ -833,7 +833,7 @@ static int ibmveth_set_tx_csum(struct net_device *dev, u32 data)
static u32 ibmveth_get_rx_csum(struct net_device *dev)
{
- struct ibmveth_adapter *adapter = dev->priv;
+ struct ibmveth_adapter *adapter = netdev_priv(dev);
return adapter->rx_csum;
}
@@ -862,7 +862,7 @@ static void ibmveth_get_ethtool_stats(struct net_device *dev,
struct ethtool_stats *stats, u64 *data)
{
int i;
- struct ibmveth_adapter *adapter = dev->priv;
+ struct ibmveth_adapter *adapter = netdev_priv(dev);
for (i = 0; i < ARRAY_SIZE(ibmveth_stats); i++)
data[i] = IBMVETH_GET_STAT(adapter, ibmveth_stats[i].offset);
@@ -889,7 +889,7 @@ static int ibmveth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev)
{
- struct ibmveth_adapter *adapter = netdev->priv;
+ struct ibmveth_adapter *adapter = netdev_priv(netdev);
union ibmveth_buf_desc desc;
unsigned long lpar_rc;
unsigned long correlator;
@@ -1014,7 +1014,6 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
netdev->stats.rx_packets++;
netdev->stats.rx_bytes += length;
frames_processed++;
- netdev->last_rx = jiffies;
}
} while (frames_processed < budget);
@@ -1029,10 +1028,10 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
ibmveth_assert(lpar_rc == H_SUCCESS);
- netif_rx_complete(netdev, napi);
+ netif_rx_complete(napi);
if (ibmveth_rxq_pending_buffer(adapter) &&
- netif_rx_reschedule(netdev, napi)) {
+ netif_rx_reschedule(napi)) {
lpar_rc = h_vio_signal(adapter->vdev->unit_address,
VIO_IRQ_DISABLE);
goto restart_poll;
@@ -1045,21 +1044,21 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
static irqreturn_t ibmveth_interrupt(int irq, void *dev_instance)
{
struct net_device *netdev = dev_instance;
- struct ibmveth_adapter *adapter = netdev->priv;
+ struct ibmveth_adapter *adapter = netdev_priv(netdev);
unsigned long lpar_rc;
- if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
+ if (netif_rx_schedule_prep(&adapter->napi)) {
lpar_rc = h_vio_signal(adapter->vdev->unit_address,
VIO_IRQ_DISABLE);
ibmveth_assert(lpar_rc == H_SUCCESS);
- __netif_rx_schedule(netdev, &adapter->napi);
+ __netif_rx_schedule(&adapter->napi);
}
return IRQ_HANDLED;
}
static void ibmveth_set_multicast_list(struct net_device *netdev)
{
- struct ibmveth_adapter *adapter = netdev->priv;
+ struct ibmveth_adapter *adapter = netdev_priv(netdev);
unsigned long lpar_rc;
if((netdev->flags & IFF_PROMISC) || (netdev->mc_count > adapter->mcastFilterSize)) {
@@ -1107,7 +1106,7 @@ static void ibmveth_set_multicast_list(struct net_device *netdev)
static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
{
- struct ibmveth_adapter *adapter = dev->priv;
+ struct ibmveth_adapter *adapter = netdev_priv(dev);
struct vio_dev *viodev = adapter->vdev;
int new_mtu_oh = new_mtu + IBMVETH_BUFF_OH;
int i;
@@ -1159,7 +1158,7 @@ static int ibmveth_change_mtu(struct net_device *dev, int new_mtu)
#ifdef CONFIG_NET_POLL_CONTROLLER
static void ibmveth_poll_controller(struct net_device *dev)
{
- ibmveth_replenish_task(dev->priv);
+ ibmveth_replenish_task(netdev_priv(dev));
ibmveth_interrupt(dev->irq, dev);
}
#endif
@@ -1241,7 +1240,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
if(!netdev)
return -ENOMEM;
- adapter = netdev->priv;
+ adapter = netdev_priv(netdev);
dev->dev.driver_data = netdev;
adapter->vdev = dev;
@@ -1337,7 +1336,7 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_
static int __devexit ibmveth_remove(struct vio_dev *dev)
{
struct net_device *netdev = dev->dev.driver_data;
- struct ibmveth_adapter *adapter = netdev->priv;
+ struct ibmveth_adapter *adapter = netdev_priv(netdev);
int i;
for(i = 0; i<IbmVethNumBufferPools; i++)
@@ -1371,13 +1370,12 @@ static int ibmveth_show(struct seq_file *seq, void *v)
struct ibmveth_adapter *adapter = seq->private;
char *current_mac = ((char*) &adapter->netdev->dev_addr);
char *firmware_mac = ((char*) &adapter->mac_addr) ;
- DECLARE_MAC_BUF(mac);
seq_printf(seq, "%s %s\n\n", ibmveth_driver_string, ibmveth_driver_version);
seq_printf(seq, "Unit Address: 0x%x\n", adapter->vdev->unit_address);
- seq_printf(seq, "Current MAC: %s\n", print_mac(mac, current_mac));
- seq_printf(seq, "Firmware MAC: %s\n", print_mac(mac, firmware_mac));
+ seq_printf(seq, "Current MAC: %pM\n", current_mac);
+ seq_printf(seq, "Firmware MAC: %pM\n", firmware_mac);
seq_printf(seq, "\nAdapter Statistics:\n");
seq_printf(seq, " TX: vio_map_single failres: %ld\n", adapter->tx_map_failed);
@@ -1472,7 +1470,7 @@ const char * buf, size_t count)
kobj);
struct net_device *netdev =
container_of(kobj->parent, struct device, kobj)->driver_data;
- struct ibmveth_adapter *adapter = netdev->priv;
+ struct ibmveth_adapter *adapter = netdev_priv(netdev);
long value = simple_strtol(buf, NULL, 10);
long rc;
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index e4fbefc8c82f..60a263001933 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -137,18 +137,23 @@ resched:
}
+static const struct net_device_ops ifb_netdev_ops = {
+ .ndo_open = ifb_open,
+ .ndo_stop = ifb_close,
+ .ndo_start_xmit = ifb_xmit,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
static void ifb_setup(struct net_device *dev)
{
/* Initialize the device structure. */
- dev->hard_start_xmit = ifb_xmit;
- dev->open = &ifb_open;
- dev->stop = &ifb_close;
dev->destructor = free_netdev;
+ dev->netdev_ops = &ifb_netdev_ops;
/* Fill in device structure with ethernet-generic values. */
ether_setup(dev);
dev->tx_queue_len = TX_Q_LIMIT;
- dev->change_mtu = NULL;
+
dev->flags |= IFF_NOARP;
dev->flags &= ~IFF_MULTICAST;
random_ether_addr(dev->dev_addr);
diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h
index ce700689fb57..40d03426c122 100644
--- a/drivers/net/igb/e1000_defines.h
+++ b/drivers/net/igb/e1000_defines.h
@@ -168,18 +168,12 @@
#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */
#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */
#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */
-/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */
#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */
#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */
#define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */
#define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */
-/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */
-#define E1000_RCTL_SZ_16384 0x00010000 /* rx buffer size 16384 */
-#define E1000_RCTL_SZ_8192 0x00020000 /* rx buffer size 8192 */
-#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */
#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */
#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */
-#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */
#define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */
/*
@@ -329,6 +323,7 @@
#define E1000_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */
#define E1000_TXD_CMD_RS 0x08000000 /* Report Status */
#define E1000_TXD_CMD_DEXT 0x20000000 /* Descriptor extension (0 = legacy) */
+#define E1000_TXD_STAT_DD 0x00000001 /* Descriptor Done */
/* Extended desc bits for Linksec and timesync */
/* Transmit Control */
diff --git a/drivers/net/igb/e1000_mac.c b/drivers/net/igb/e1000_mac.c
index e18747c70bec..97f0049a5d6b 100644
--- a/drivers/net/igb/e1000_mac.c
+++ b/drivers/net/igb/e1000_mac.c
@@ -50,13 +50,6 @@ void igb_remove_device(struct e1000_hw *hw)
kfree(hw->dev_spec);
}
-static void igb_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value)
-{
- struct igb_adapter *adapter = hw->back;
-
- pci_read_config_word(adapter->pdev, reg, value);
-}
-
static s32 igb_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value)
{
struct igb_adapter *adapter = hw->back;
@@ -83,8 +76,8 @@ s32 igb_get_bus_info_pcie(struct e1000_hw *hw)
{
struct e1000_bus_info *bus = &hw->bus;
s32 ret_val;
- u32 status;
- u16 pcie_link_status, pci_header_type;
+ u32 reg;
+ u16 pcie_link_status;
bus->type = e1000_bus_type_pci_express;
bus->speed = e1000_bus_speed_2500;
@@ -99,14 +92,8 @@ s32 igb_get_bus_info_pcie(struct e1000_hw *hw)
PCIE_LINK_WIDTH_MASK) >>
PCIE_LINK_WIDTH_SHIFT);
- igb_read_pci_cfg(hw, PCI_HEADER_TYPE_REGISTER, &pci_header_type);
- if (pci_header_type & PCI_HEADER_TYPE_MULTIFUNC) {
- status = rd32(E1000_STATUS);
- bus->func = (status & E1000_STATUS_FUNC_MASK)
- >> E1000_STATUS_FUNC_SHIFT;
- } else {
- bus->func = 0;
- }
+ reg = rd32(E1000_STATUS);
+ bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT;
return 0;
}
@@ -229,8 +216,8 @@ void igb_rar_set(struct e1000_hw *hw, u8 *addr, u32 index)
if (!hw->mac.disable_av)
rar_high |= E1000_RAH_AV;
- array_wr32(E1000_RA, (index << 1), rar_low);
- array_wr32(E1000_RA, ((index << 1) + 1), rar_high);
+ wr32(E1000_RAL(index), rar_low);
+ wr32(E1000_RAH(index), rar_high);
}
/**
diff --git a/drivers/net/igb/e1000_regs.h b/drivers/net/igb/e1000_regs.h
index 95523af26056..bdf5d839c4bf 100644
--- a/drivers/net/igb/e1000_regs.h
+++ b/drivers/net/igb/e1000_regs.h
@@ -221,6 +221,10 @@
#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */
#define E1000_RA 0x05400 /* Receive Address - RW Array */
#define E1000_RA2 0x054E0 /* 2nd half of receive address array - RW Array */
+#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \
+ (0x054E0 + ((_i - 16) * 8)))
+#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \
+ (0x054E4 + ((_i - 16) * 8)))
#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */
#define E1000_VMD_CTL 0x0581C /* VMDq Control - RW */
#define E1000_WUC 0x05800 /* Wakeup Control - RW */
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index 4ff6f0567f3f..5a27825cc48a 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -43,8 +43,6 @@ struct igb_adapter;
#endif
/* Interrupt defines */
-#define IGB_MAX_TX_CLEAN 72
-
#define IGB_MIN_DYN_ITR 3000
#define IGB_MAX_DYN_ITR 96000
@@ -127,7 +125,8 @@ struct igb_buffer {
/* TX */
struct {
unsigned long time_stamp;
- u32 length;
+ u16 length;
+ u16 next_to_watch;
};
/* RX */
struct {
@@ -160,7 +159,8 @@ struct igb_ring {
u16 itr_register;
u16 cpu;
- int queue_index;
+ u16 queue_index;
+ u16 reg_idx;
unsigned int total_bytes;
unsigned int total_packets;
@@ -294,6 +294,8 @@ struct igb_adapter {
unsigned int lro_flushed;
unsigned int lro_no_desc;
#endif
+ unsigned int tx_ring_count;
+ unsigned int rx_ring_count;
};
#define IGB_FLAG_HAS_MSI (1 << 0)
@@ -325,7 +327,41 @@ extern void igb_reset(struct igb_adapter *);
extern int igb_set_spd_dplx(struct igb_adapter *, u16);
extern int igb_setup_tx_resources(struct igb_adapter *, struct igb_ring *);
extern int igb_setup_rx_resources(struct igb_adapter *, struct igb_ring *);
+extern void igb_free_tx_resources(struct igb_ring *);
+extern void igb_free_rx_resources(struct igb_ring *);
extern void igb_update_stats(struct igb_adapter *);
extern void igb_set_ethtool_ops(struct net_device *);
+static inline s32 igb_reset_phy(struct e1000_hw *hw)
+{
+ if (hw->phy.ops.reset_phy)
+ return hw->phy.ops.reset_phy(hw);
+
+ return 0;
+}
+
+static inline s32 igb_read_phy_reg(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ if (hw->phy.ops.read_phy_reg)
+ return hw->phy.ops.read_phy_reg(hw, offset, data);
+
+ return 0;
+}
+
+static inline s32 igb_write_phy_reg(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ if (hw->phy.ops.write_phy_reg)
+ return hw->phy.ops.write_phy_reg(hw, offset, data);
+
+ return 0;
+}
+
+static inline s32 igb_get_phy_info(struct e1000_hw *hw)
+{
+ if (hw->phy.ops.get_phy_info)
+ return hw->phy.ops.get_phy_info(hw);
+
+ return 0;
+}
+
#endif /* _IGB_H_ */
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index 89964fa739a0..3c831f1472ad 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -101,8 +101,8 @@ static const struct igb_stats igb_gstrings_stats[] = {
};
#define IGB_QUEUE_STATS_LEN \
- ((((struct igb_adapter *)netdev->priv)->num_rx_queues + \
- ((struct igb_adapter *)netdev->priv)->num_tx_queues) * \
+ ((((struct igb_adapter *)netdev_priv(netdev))->num_rx_queues + \
+ ((struct igb_adapter *)netdev_priv(netdev))->num_tx_queues) * \
(sizeof(struct igb_queue_stats) / sizeof(u64)))
#define IGB_GLOBAL_STATS_LEN \
sizeof(igb_gstrings_stats) / sizeof(struct igb_stats)
@@ -494,8 +494,6 @@ static void igb_get_regs(struct net_device *netdev,
/* These should probably be added to e1000_regs.h instead */
#define E1000_PSRTYPE_REG(_i) (0x05480 + ((_i) * 4))
- #define E1000_RAL(_i) (0x05400 + ((_i) * 8))
- #define E1000_RAH(_i) (0x05404 + ((_i) * 8))
#define E1000_IP4AT_REG(_i) (0x05840 + ((_i) * 8))
#define E1000_IP6AT_REG(_i) (0x05880 + ((_i) * 4))
#define E1000_WUPM_REG(_i) (0x05A00 + ((_i) * 4))
@@ -714,15 +712,13 @@ static void igb_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
struct igb_adapter *adapter = netdev_priv(netdev);
- struct igb_ring *tx_ring = adapter->tx_ring;
- struct igb_ring *rx_ring = adapter->rx_ring;
ring->rx_max_pending = IGB_MAX_RXD;
ring->tx_max_pending = IGB_MAX_TXD;
ring->rx_mini_max_pending = 0;
ring->rx_jumbo_max_pending = 0;
- ring->rx_pending = rx_ring->count;
- ring->tx_pending = tx_ring->count;
+ ring->rx_pending = adapter->rx_ring_count;
+ ring->tx_pending = adapter->tx_ring_count;
ring->rx_mini_pending = 0;
ring->rx_jumbo_pending = 0;
}
@@ -731,12 +727,9 @@ static int igb_set_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ring)
{
struct igb_adapter *adapter = netdev_priv(netdev);
- struct igb_buffer *old_buf;
- struct igb_buffer *old_rx_buf;
- void *old_desc;
+ struct igb_ring *temp_ring;
int i, err;
- u32 new_rx_count, new_tx_count, old_size;
- dma_addr_t old_dma;
+ u32 new_rx_count, new_tx_count;
if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
return -EINVAL;
@@ -749,12 +742,19 @@ static int igb_set_ringparam(struct net_device *netdev,
new_tx_count = min(new_tx_count, (u32)IGB_MAX_TXD);
new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE);
- if ((new_tx_count == adapter->tx_ring->count) &&
- (new_rx_count == adapter->rx_ring->count)) {
+ if ((new_tx_count == adapter->tx_ring_count) &&
+ (new_rx_count == adapter->rx_ring_count)) {
/* nothing to do */
return 0;
}
+ if (adapter->num_tx_queues > adapter->num_rx_queues)
+ temp_ring = vmalloc(adapter->num_tx_queues * sizeof(struct igb_ring));
+ else
+ temp_ring = vmalloc(adapter->num_rx_queues * sizeof(struct igb_ring));
+ if (!temp_ring)
+ return -ENOMEM;
+
while (test_and_set_bit(__IGB_RESETTING, &adapter->state))
msleep(1);
@@ -766,62 +766,55 @@ static int igb_set_ringparam(struct net_device *netdev,
* because the ISRs in MSI-X mode get passed pointers
* to the tx and rx ring structs.
*/
- if (new_tx_count != adapter->tx_ring->count) {
+ if (new_tx_count != adapter->tx_ring_count) {
+ memcpy(temp_ring, adapter->tx_ring,
+ adapter->num_tx_queues * sizeof(struct igb_ring));
+
for (i = 0; i < adapter->num_tx_queues; i++) {
- /* Save existing descriptor ring */
- old_buf = adapter->tx_ring[i].buffer_info;
- old_desc = adapter->tx_ring[i].desc;
- old_size = adapter->tx_ring[i].size;
- old_dma = adapter->tx_ring[i].dma;
- /* Try to allocate a new one */
- adapter->tx_ring[i].buffer_info = NULL;
- adapter->tx_ring[i].desc = NULL;
- adapter->tx_ring[i].count = new_tx_count;
- err = igb_setup_tx_resources(adapter,
- &adapter->tx_ring[i]);
+ temp_ring[i].count = new_tx_count;
+ err = igb_setup_tx_resources(adapter, &temp_ring[i]);
if (err) {
- /* Restore the old one so at least
- the adapter still works, even if
- we failed the request */
- adapter->tx_ring[i].buffer_info = old_buf;
- adapter->tx_ring[i].desc = old_desc;
- adapter->tx_ring[i].size = old_size;
- adapter->tx_ring[i].dma = old_dma;
+ while (i) {
+ i--;
+ igb_free_tx_resources(&temp_ring[i]);
+ }
goto err_setup;
}
- /* Free the old buffer manually */
- vfree(old_buf);
- pci_free_consistent(adapter->pdev, old_size,
- old_desc, old_dma);
}
+
+ for (i = 0; i < adapter->num_tx_queues; i++)
+ igb_free_tx_resources(&adapter->tx_ring[i]);
+
+ memcpy(adapter->tx_ring, temp_ring,
+ adapter->num_tx_queues * sizeof(struct igb_ring));
+
+ adapter->tx_ring_count = new_tx_count;
}
if (new_rx_count != adapter->rx_ring->count) {
- for (i = 0; i < adapter->num_rx_queues; i++) {
+ memcpy(temp_ring, adapter->rx_ring,
+ adapter->num_rx_queues * sizeof(struct igb_ring));
- old_rx_buf = adapter->rx_ring[i].buffer_info;
- old_desc = adapter->rx_ring[i].desc;
- old_size = adapter->rx_ring[i].size;
- old_dma = adapter->rx_ring[i].dma;
-
- adapter->rx_ring[i].buffer_info = NULL;
- adapter->rx_ring[i].desc = NULL;
- adapter->rx_ring[i].dma = 0;
- adapter->rx_ring[i].count = new_rx_count;
- err = igb_setup_rx_resources(adapter,
- &adapter->rx_ring[i]);
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ temp_ring[i].count = new_rx_count;
+ err = igb_setup_rx_resources(adapter, &temp_ring[i]);
if (err) {
- adapter->rx_ring[i].buffer_info = old_rx_buf;
- adapter->rx_ring[i].desc = old_desc;
- adapter->rx_ring[i].size = old_size;
- adapter->rx_ring[i].dma = old_dma;
+ while (i) {
+ i--;
+ igb_free_rx_resources(&temp_ring[i]);
+ }
goto err_setup;
}
- vfree(old_rx_buf);
- pci_free_consistent(adapter->pdev, old_size, old_desc,
- old_dma);
}
+
+ for (i = 0; i < adapter->num_rx_queues; i++)
+ igb_free_rx_resources(&adapter->rx_ring[i]);
+
+ memcpy(adapter->rx_ring, temp_ring,
+ adapter->num_rx_queues * sizeof(struct igb_ring));
+
+ adapter->rx_ring_count = new_rx_count;
}
err = 0;
@@ -830,6 +823,7 @@ err_setup:
igb_up(adapter);
clear_bit(__IGB_RESETTING, &adapter->state);
+ vfree(temp_ring);
return err;
}
@@ -1343,8 +1337,9 @@ static int igb_setup_desc_rings(struct igb_adapter *adapter)
wr32(E1000_RDLEN(0), rx_ring->size);
wr32(E1000_RDH(0), 0);
wr32(E1000_RDT(0), 0);
+ rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 |
- E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
+ E1000_RCTL_RDMTS_HALF |
(adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
wr32(E1000_RCTL, rctl);
wr32(E1000_SRRCTL(0), 0);
@@ -1380,10 +1375,10 @@ static void igb_phy_disable_receiver(struct igb_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
/* Write out to PHY registers 29 and 30 to disable the Receiver. */
- hw->phy.ops.write_phy_reg(hw, 29, 0x001F);
- hw->phy.ops.write_phy_reg(hw, 30, 0x8FFC);
- hw->phy.ops.write_phy_reg(hw, 29, 0x001A);
- hw->phy.ops.write_phy_reg(hw, 30, 0x8FF0);
+ igb_write_phy_reg(hw, 29, 0x001F);
+ igb_write_phy_reg(hw, 30, 0x8FFC);
+ igb_write_phy_reg(hw, 29, 0x001A);
+ igb_write_phy_reg(hw, 30, 0x8FF0);
}
static int igb_integrated_phy_loopback(struct igb_adapter *adapter)
@@ -1396,17 +1391,17 @@ static int igb_integrated_phy_loopback(struct igb_adapter *adapter)
if (hw->phy.type == e1000_phy_m88) {
/* Auto-MDI/MDIX Off */
- hw->phy.ops.write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, 0x0808);
+ igb_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, 0x0808);
/* reset to update Auto-MDI/MDIX */
- hw->phy.ops.write_phy_reg(hw, PHY_CONTROL, 0x9140);
+ igb_write_phy_reg(hw, PHY_CONTROL, 0x9140);
/* autoneg off */
- hw->phy.ops.write_phy_reg(hw, PHY_CONTROL, 0x8140);
+ igb_write_phy_reg(hw, PHY_CONTROL, 0x8140);
}
ctrl_reg = rd32(E1000_CTRL);
/* force 1000, set loopback */
- hw->phy.ops.write_phy_reg(hw, PHY_CONTROL, 0x4140);
+ igb_write_phy_reg(hw, PHY_CONTROL, 0x4140);
/* Now set up the MAC to the same speed/duplex as the PHY. */
ctrl_reg = rd32(E1000_CTRL);
@@ -1500,10 +1495,10 @@ static void igb_loopback_cleanup(struct igb_adapter *adapter)
wr32(E1000_RCTL, rctl);
hw->mac.autoneg = true;
- hw->phy.ops.read_phy_reg(hw, PHY_CONTROL, &phy_reg);
+ igb_read_phy_reg(hw, PHY_CONTROL, &phy_reg);
if (phy_reg & MII_CR_LOOPBACK) {
phy_reg &= ~MII_CR_LOOPBACK;
- hw->phy.ops.write_phy_reg(hw, PHY_CONTROL, phy_reg);
+ igb_write_phy_reg(hw, PHY_CONTROL, phy_reg);
igb_phy_sw_reset(hw);
}
}
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 20d27e622ec1..022794e579c7 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -42,6 +42,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/if_ether.h>
+#include <linux/aer.h>
#ifdef CONFIG_IGB_DCA
#include <linux/dca.h>
#endif
@@ -76,8 +77,6 @@ static int igb_setup_all_tx_resources(struct igb_adapter *);
static int igb_setup_all_rx_resources(struct igb_adapter *);
static void igb_free_all_tx_resources(struct igb_adapter *);
static void igb_free_all_rx_resources(struct igb_adapter *);
-static void igb_free_tx_resources(struct igb_ring *);
-static void igb_free_rx_resources(struct igb_ring *);
void igb_update_stats(struct igb_adapter *);
static int igb_probe(struct pci_dev *, const struct pci_device_id *);
static void __devexit igb_remove(struct pci_dev *pdev);
@@ -232,6 +231,40 @@ static void __exit igb_exit_module(void)
module_exit(igb_exit_module);
+#define Q_IDX_82576(i) (((i & 0x1) << 3) + (i >> 1))
+/**
+ * igb_cache_ring_register - Descriptor ring to register mapping
+ * @adapter: board private structure to initialize
+ *
+ * Once we know the feature-set enabled for the device, we'll cache
+ * the register offset the descriptor ring is assigned to.
+ **/
+static void igb_cache_ring_register(struct igb_adapter *adapter)
+{
+ int i;
+
+ switch (adapter->hw.mac.type) {
+ case e1000_82576:
+ /* The queues are allocated for virtualization such that VF 0
+ * is allocated queues 0 and 8, VF 1 queues 1 and 9, etc.
+ * In order to avoid collision we start at the first free queue
+ * and continue consuming queues in the same sequence
+ */
+ for (i = 0; i < adapter->num_rx_queues; i++)
+ adapter->rx_ring[i].reg_idx = Q_IDX_82576(i);
+ for (i = 0; i < adapter->num_tx_queues; i++)
+ adapter->tx_ring[i].reg_idx = Q_IDX_82576(i);
+ break;
+ case e1000_82575:
+ default:
+ for (i = 0; i < adapter->num_rx_queues; i++)
+ adapter->rx_ring[i].reg_idx = i;
+ for (i = 0; i < adapter->num_tx_queues; i++)
+ adapter->tx_ring[i].reg_idx = i;
+ break;
+ }
+}
+
/**
* igb_alloc_queues - Allocate memory for all rings
* @adapter: board private structure to initialize
@@ -259,11 +292,13 @@ static int igb_alloc_queues(struct igb_adapter *adapter)
for (i = 0; i < adapter->num_tx_queues; i++) {
struct igb_ring *ring = &(adapter->tx_ring[i]);
+ ring->count = adapter->tx_ring_count;
ring->adapter = adapter;
ring->queue_index = i;
}
for (i = 0; i < adapter->num_rx_queues; i++) {
struct igb_ring *ring = &(adapter->rx_ring[i]);
+ ring->count = adapter->rx_ring_count;
ring->adapter = adapter;
ring->queue_index = i;
ring->itr_register = E1000_ITR;
@@ -271,6 +306,8 @@ static int igb_alloc_queues(struct igb_adapter *adapter)
/* set a default napi handler for each rx_ring */
netif_napi_add(adapter->netdev, &ring->napi, igb_poll, 64);
}
+
+ igb_cache_ring_register(adapter);
return 0;
}
@@ -311,36 +348,36 @@ static void igb_assign_vector(struct igb_adapter *adapter, int rx_queue,
array_wr32(E1000_MSIXBM(0), msix_vector, msixbm);
break;
case e1000_82576:
- /* The 82576 uses a table-based method for assigning vectors.
+ /* 82576 uses a table-based method for assigning vectors.
Each queue has a single entry in the table to which we write
a vector number along with a "valid" bit. Sadly, the layout
of the table is somewhat counterintuitive. */
if (rx_queue > IGB_N0_QUEUE) {
- index = (rx_queue & 0x7);
+ index = (rx_queue >> 1);
ivar = array_rd32(E1000_IVAR0, index);
- if (rx_queue < 8) {
- /* vector goes into low byte of register */
- ivar = ivar & 0xFFFFFF00;
- ivar |= msix_vector | E1000_IVAR_VALID;
- } else {
+ if (rx_queue & 0x1) {
/* vector goes into third byte of register */
ivar = ivar & 0xFF00FFFF;
ivar |= (msix_vector | E1000_IVAR_VALID) << 16;
+ } else {
+ /* vector goes into low byte of register */
+ ivar = ivar & 0xFFFFFF00;
+ ivar |= msix_vector | E1000_IVAR_VALID;
}
adapter->rx_ring[rx_queue].eims_value= 1 << msix_vector;
array_wr32(E1000_IVAR0, index, ivar);
}
if (tx_queue > IGB_N0_QUEUE) {
- index = (tx_queue & 0x7);
+ index = (tx_queue >> 1);
ivar = array_rd32(E1000_IVAR0, index);
- if (tx_queue < 8) {
- /* vector goes into second byte of register */
- ivar = ivar & 0xFFFF00FF;
- ivar |= (msix_vector | E1000_IVAR_VALID) << 8;
- } else {
+ if (tx_queue & 0x1) {
/* vector goes into high byte of register */
ivar = ivar & 0x00FFFFFF;
ivar |= (msix_vector | E1000_IVAR_VALID) << 24;
+ } else {
+ /* vector goes into second byte of register */
+ ivar = ivar & 0xFFFF00FF;
+ ivar |= (msix_vector | E1000_IVAR_VALID) << 8;
}
adapter->tx_ring[tx_queue].eims_value= 1 << msix_vector;
array_wr32(E1000_IVAR0, index, ivar);
@@ -445,7 +482,7 @@ static int igb_request_msix(struct igb_adapter *adapter)
for (i = 0; i < adapter->num_tx_queues; i++) {
struct igb_ring *ring = &(adapter->tx_ring[i]);
- sprintf(ring->name, "%s-tx%d", netdev->name, i);
+ sprintf(ring->name, "%s-tx-%d", netdev->name, i);
err = request_irq(adapter->msix_entries[vector].vector,
&igb_msix_tx, 0, ring->name,
&(adapter->tx_ring[i]));
@@ -458,7 +495,7 @@ static int igb_request_msix(struct igb_adapter *adapter)
for (i = 0; i < adapter->num_rx_queues; i++) {
struct igb_ring *ring = &(adapter->rx_ring[i]);
if (strlen(netdev->name) < (IFNAMSIZ - 5))
- sprintf(ring->name, "%s-rx%d", netdev->name, i);
+ sprintf(ring->name, "%s-rx-%d", netdev->name, i);
else
memcpy(ring->name, netdev->name, IFNAMSIZ);
err = request_irq(adapter->msix_entries[vector].vector,
@@ -931,8 +968,7 @@ void igb_reset(struct igb_adapter *adapter)
wr32(E1000_VET, ETHERNET_IEEE_VLAN_TYPE);
igb_reset_adaptive(&adapter->hw);
- if (adapter->hw.phy.ops.get_phy_info)
- adapter->hw.phy.ops.get_phy_info(&adapter->hw);
+ igb_get_phy_info(&adapter->hw);
}
/**
@@ -950,6 +986,25 @@ static int igb_is_need_ioport(struct pci_dev *pdev)
}
}
+static const struct net_device_ops igb_netdev_ops = {
+ .ndo_open = igb_open,
+ .ndo_stop = igb_close,
+ .ndo_start_xmit = igb_xmit_frame_adv,
+ .ndo_get_stats = igb_get_stats,
+ .ndo_set_multicast_list = igb_set_multi,
+ .ndo_set_mac_address = igb_set_mac,
+ .ndo_change_mtu = igb_change_mtu,
+ .ndo_do_ioctl = igb_ioctl,
+ .ndo_tx_timeout = igb_tx_timeout,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_vlan_rx_register = igb_vlan_rx_register,
+ .ndo_vlan_rx_add_vid = igb_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = igb_vlan_rx_kill_vid,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = igb_netpoll,
+#endif
+};
+
/**
* igb_probe - Device Initialization Routine
* @pdev: PCI device information struct
@@ -1031,6 +1086,13 @@ static int __devinit igb_probe(struct pci_dev *pdev,
if (err)
goto err_pci_reg;
+ err = pci_enable_pcie_error_reporting(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "pci_enable_pcie_error_reporting failed "
+ "0x%x\n", err);
+ /* non-fatal, continue */
+ }
+
pci_set_master(pdev);
pci_save_state(pdev);
@@ -1059,23 +1121,9 @@ static int __devinit igb_probe(struct pci_dev *pdev,
if (!adapter->hw.hw_addr)
goto err_ioremap;
- netdev->open = &igb_open;
- netdev->stop = &igb_close;
- netdev->get_stats = &igb_get_stats;
- netdev->set_multicast_list = &igb_set_multi;
- netdev->set_mac_address = &igb_set_mac;
- netdev->change_mtu = &igb_change_mtu;
- netdev->do_ioctl = &igb_ioctl;
+ netdev->netdev_ops = &igb_netdev_ops;
igb_set_ethtool_ops(netdev);
- netdev->tx_timeout = &igb_tx_timeout;
netdev->watchdog_timeo = 5 * HZ;
- netdev->vlan_rx_register = igb_vlan_rx_register;
- netdev->vlan_rx_add_vid = igb_vlan_rx_add_vid;
- netdev->vlan_rx_kill_vid = igb_vlan_rx_kill_vid;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- netdev->poll_controller = igb_netpoll;
-#endif
- netdev->hard_start_xmit = &igb_xmit_frame_adv;
strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
@@ -1275,16 +1323,14 @@ static int __devinit igb_probe(struct pci_dev *pdev,
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) %02x:%02x:%02x:%02x:%02x:%02x\n",
+ dev_info(&pdev->dev, "%s: (PCIe:%s:%s) %pM\n",
netdev->name,
((hw->bus.speed == e1000_bus_speed_2500)
? "2.5Gb/s" : "unknown"),
((hw->bus.width == e1000_bus_width_pcie_x4)
? "Width x4" : (hw->bus.width == e1000_bus_width_pcie_x1)
? "Width x1" : "unknown"),
- netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
- netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
+ netdev->dev_addr);
igb_read_part_num(hw, &part_num);
dev_info(&pdev->dev, "%s: PBA No: %06x-%03x\n", netdev->name,
@@ -1302,7 +1348,7 @@ err_register:
igb_release_hw_control(adapter);
err_eeprom:
if (!igb_check_reset_block(hw))
- hw->phy.ops.reset_phy(hw);
+ igb_reset_phy(hw);
if (hw->flash_address)
iounmap(hw->flash_address);
@@ -1338,6 +1384,7 @@ static void __devexit igb_remove(struct pci_dev *pdev)
#ifdef CONFIG_IGB_DCA
struct e1000_hw *hw = &adapter->hw;
#endif
+ int err;
/* flush_scheduled work may reschedule our watchdog task, so
* explicitly disable watchdog tasks from being rescheduled */
@@ -1362,9 +1409,8 @@ static void __devexit igb_remove(struct pci_dev *pdev)
unregister_netdev(netdev);
- if (adapter->hw.phy.ops.reset_phy &&
- !igb_check_reset_block(&adapter->hw))
- adapter->hw.phy.ops.reset_phy(&adapter->hw);
+ if (!igb_check_reset_block(&adapter->hw))
+ igb_reset_phy(&adapter->hw);
igb_remove_device(&adapter->hw);
igb_reset_interrupt_capability(adapter);
@@ -1378,6 +1424,11 @@ static void __devexit igb_remove(struct pci_dev *pdev)
free_netdev(netdev);
+ err = pci_disable_pcie_error_reporting(pdev);
+ if (err)
+ dev_err(&pdev->dev,
+ "pci_disable_pcie_error_reporting failed 0x%x\n", err);
+
pci_disable_device(pdev);
}
@@ -1397,6 +1448,8 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
pci_read_config_word(pdev, PCI_COMMAND, &hw->bus.pci_cmd_word);
+ adapter->tx_ring_count = IGB_DEFAULT_TXD;
+ adapter->rx_ring_count = IGB_DEFAULT_RXD;
adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE;
adapter->rx_ps_hdr_size = 0; /* disable packet split */
adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
@@ -1558,8 +1611,7 @@ int igb_setup_tx_resources(struct igb_adapter *adapter,
memset(tx_ring->buffer_info, 0, size);
/* round up to nearest 4K */
- tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc)
- + sizeof(u32);
+ tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc);
tx_ring->size = ALIGN(tx_ring->size, 4096);
tx_ring->desc = pci_alloc_consistent(pdev, tx_ring->size,
@@ -1618,43 +1670,37 @@ static int igb_setup_all_tx_resources(struct igb_adapter *adapter)
**/
static void igb_configure_tx(struct igb_adapter *adapter)
{
- u64 tdba, tdwba;
+ u64 tdba;
struct e1000_hw *hw = &adapter->hw;
u32 tctl;
u32 txdctl, txctrl;
- int i;
+ int i, j;
for (i = 0; i < adapter->num_tx_queues; i++) {
struct igb_ring *ring = &(adapter->tx_ring[i]);
-
- wr32(E1000_TDLEN(i),
+ j = ring->reg_idx;
+ wr32(E1000_TDLEN(j),
ring->count * sizeof(struct e1000_tx_desc));
tdba = ring->dma;
- wr32(E1000_TDBAL(i),
+ wr32(E1000_TDBAL(j),
tdba & 0x00000000ffffffffULL);
- wr32(E1000_TDBAH(i), tdba >> 32);
-
- tdwba = ring->dma + ring->count * sizeof(struct e1000_tx_desc);
- tdwba |= 1; /* enable head wb */
- wr32(E1000_TDWBAL(i),
- tdwba & 0x00000000ffffffffULL);
- wr32(E1000_TDWBAH(i), tdwba >> 32);
+ wr32(E1000_TDBAH(j), tdba >> 32);
- ring->head = E1000_TDH(i);
- ring->tail = E1000_TDT(i);
+ ring->head = E1000_TDH(j);
+ ring->tail = E1000_TDT(j);
writel(0, hw->hw_addr + ring->tail);
writel(0, hw->hw_addr + ring->head);
- txdctl = rd32(E1000_TXDCTL(i));
+ txdctl = rd32(E1000_TXDCTL(j));
txdctl |= E1000_TXDCTL_QUEUE_ENABLE;
- wr32(E1000_TXDCTL(i), txdctl);
+ wr32(E1000_TXDCTL(j), txdctl);
/* Turn off Relaxed Ordering on head write-backs. The
* writebacks MUST be delivered in order or it will
* completely screw up our bookeeping.
*/
- txctrl = rd32(E1000_DCA_TXCTRL(i));
+ txctrl = rd32(E1000_DCA_TXCTRL(j));
txctrl &= ~E1000_DCA_TXCTRL_TX_WB_RO_EN;
- wr32(E1000_DCA_TXCTRL(i), txctrl);
+ wr32(E1000_DCA_TXCTRL(j), txctrl);
}
@@ -1771,14 +1817,14 @@ static void igb_setup_rctl(struct igb_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
u32 rctl;
u32 srrctl = 0;
- int i;
+ int i, j;
rctl = rd32(E1000_RCTL);
rctl &= ~(3 << E1000_RCTL_MO_SHIFT);
+ rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC);
- rctl |= E1000_RCTL_EN | E1000_RCTL_BAM |
- E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF |
+ rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_RDMTS_HALF |
(adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT);
/*
@@ -1788,38 +1834,26 @@ static void igb_setup_rctl(struct igb_adapter *adapter)
*/
rctl |= E1000_RCTL_SECRC;
- rctl &= ~E1000_RCTL_SBP;
+ /*
+ * disable store bad packets, long packet enable, and clear size bits.
+ */
+ rctl &= ~(E1000_RCTL_SBP | E1000_RCTL_LPE | E1000_RCTL_SZ_256);
- if (adapter->netdev->mtu <= ETH_DATA_LEN)
- rctl &= ~E1000_RCTL_LPE;
- else
+ if (adapter->netdev->mtu > ETH_DATA_LEN)
rctl |= E1000_RCTL_LPE;
- if (adapter->rx_buffer_len <= IGB_RXBUFFER_2048) {
- /* Setup buffer sizes */
- rctl &= ~E1000_RCTL_SZ_4096;
- rctl |= E1000_RCTL_BSEX;
- switch (adapter->rx_buffer_len) {
- case IGB_RXBUFFER_256:
- rctl |= E1000_RCTL_SZ_256;
- rctl &= ~E1000_RCTL_BSEX;
- break;
- case IGB_RXBUFFER_512:
- rctl |= E1000_RCTL_SZ_512;
- rctl &= ~E1000_RCTL_BSEX;
- break;
- case IGB_RXBUFFER_1024:
- rctl |= E1000_RCTL_SZ_1024;
- rctl &= ~E1000_RCTL_BSEX;
- break;
- case IGB_RXBUFFER_2048:
- default:
- rctl |= E1000_RCTL_SZ_2048;
- rctl &= ~E1000_RCTL_BSEX;
- break;
- }
- } else {
- rctl &= ~E1000_RCTL_BSEX;
- srrctl = adapter->rx_buffer_len >> E1000_SRRCTL_BSIZEPKT_SHIFT;
+
+ /* Setup buffer sizes */
+ switch (adapter->rx_buffer_len) {
+ case IGB_RXBUFFER_256:
+ rctl |= E1000_RCTL_SZ_256;
+ break;
+ case IGB_RXBUFFER_512:
+ rctl |= E1000_RCTL_SZ_512;
+ break;
+ default:
+ srrctl = ALIGN(adapter->rx_buffer_len, 1024)
+ >> E1000_SRRCTL_BSIZEPKT_SHIFT;
+ break;
}
/* 82575 and greater support packet-split where the protocol
@@ -1841,8 +1875,10 @@ static void igb_setup_rctl(struct igb_adapter *adapter)
srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
}
- for (i = 0; i < adapter->num_rx_queues; i++)
- wr32(E1000_SRRCTL(i), srrctl);
+ for (i = 0; i < adapter->num_rx_queues; i++) {
+ j = adapter->rx_ring[i].reg_idx;
+ wr32(E1000_SRRCTL(j), srrctl);
+ }
wr32(E1000_RCTL, rctl);
}
@@ -1859,7 +1895,7 @@ static void igb_configure_rx(struct igb_adapter *adapter)
struct e1000_hw *hw = &adapter->hw;
u32 rctl, rxcsum;
u32 rxdctl;
- int i;
+ int i, j;
/* disable receives while setting up the descriptors */
rctl = rd32(E1000_RCTL);
@@ -1874,25 +1910,26 @@ static void igb_configure_rx(struct igb_adapter *adapter)
* the Base and Length of the Rx Descriptor Ring */
for (i = 0; i < adapter->num_rx_queues; i++) {
struct igb_ring *ring = &(adapter->rx_ring[i]);
+ j = ring->reg_idx;
rdba = ring->dma;
- wr32(E1000_RDBAL(i),
+ wr32(E1000_RDBAL(j),
rdba & 0x00000000ffffffffULL);
- wr32(E1000_RDBAH(i), rdba >> 32);
- wr32(E1000_RDLEN(i),
+ wr32(E1000_RDBAH(j), rdba >> 32);
+ wr32(E1000_RDLEN(j),
ring->count * sizeof(union e1000_adv_rx_desc));
- ring->head = E1000_RDH(i);
- ring->tail = E1000_RDT(i);
+ ring->head = E1000_RDH(j);
+ ring->tail = E1000_RDT(j);
writel(0, hw->hw_addr + ring->tail);
writel(0, hw->hw_addr + ring->head);
- rxdctl = rd32(E1000_RXDCTL(i));
+ rxdctl = rd32(E1000_RXDCTL(j));
rxdctl |= E1000_RXDCTL_QUEUE_ENABLE;
rxdctl &= 0xFFF00000;
rxdctl |= IGB_RX_PTHRESH;
rxdctl |= IGB_RX_HTHRESH << 8;
rxdctl |= IGB_RX_WTHRESH << 16;
- wr32(E1000_RXDCTL(i), rxdctl);
+ wr32(E1000_RXDCTL(j), rxdctl);
#ifdef CONFIG_IGB_LRO
/* Intitial LRO Settings */
ring->lro_mgr.max_aggr = MAX_LRO_AGGR;
@@ -1922,7 +1959,7 @@ static void igb_configure_rx(struct igb_adapter *adapter)
shift = 6;
for (j = 0; j < (32 * 4); j++) {
reta.bytes[j & 3] =
- (j % adapter->num_rx_queues) << shift;
+ adapter->rx_ring[(j % adapter->num_rx_queues)].reg_idx << shift;
if ((j & 3) == 3)
writel(reta.dword,
hw->hw_addr + E1000_RETA(0) + (j & ~3));
@@ -1984,7 +2021,7 @@ static void igb_configure_rx(struct igb_adapter *adapter)
*
* Free all transmit software resources
**/
-static void igb_free_tx_resources(struct igb_ring *tx_ring)
+void igb_free_tx_resources(struct igb_ring *tx_ring)
{
struct pci_dev *pdev = tx_ring->adapter->pdev;
@@ -2082,7 +2119,7 @@ static void igb_clean_all_tx_rings(struct igb_adapter *adapter)
*
* Free all receive software resources
**/
-static void igb_free_rx_resources(struct igb_ring *rx_ring)
+void igb_free_rx_resources(struct igb_ring *rx_ring)
{
struct pci_dev *pdev = rx_ring->adapter->pdev;
@@ -2274,8 +2311,7 @@ static void igb_set_multi(struct net_device *netdev)
static void igb_update_phy_info(unsigned long data)
{
struct igb_adapter *adapter = (struct igb_adapter *) data;
- if (adapter->hw.phy.ops.get_phy_info)
- adapter->hw.phy.ops.get_phy_info(&adapter->hw);
+ igb_get_phy_info(&adapter->hw);
}
/**
@@ -2330,9 +2366,10 @@ static void igb_watchdog_task(struct work_struct *work)
&adapter->link_duplex);
ctrl = rd32(E1000_CTRL);
- dev_info(&adapter->pdev->dev,
- "NIC Link is Up %d Mbps %s, "
+ /* Links status message must follow this format */
+ printk(KERN_INFO "igb: %s NIC Link is Up %d Mbps %s, "
"Flow Control: %s\n",
+ netdev->name,
adapter->link_speed,
adapter->link_duplex == FULL_DUPLEX ?
"Full Duplex" : "Half Duplex",
@@ -2367,7 +2404,9 @@ static void igb_watchdog_task(struct work_struct *work)
if (netif_carrier_ok(netdev)) {
adapter->link_speed = 0;
adapter->link_duplex = 0;
- dev_info(&adapter->pdev->dev, "NIC Link is Down\n");
+ /* Links status message must follow this format */
+ printk(KERN_INFO "igb: %s NIC Link is Down\n",
+ netdev->name);
netif_carrier_off(netdev);
netif_tx_stop_all_queues(netdev);
if (!test_bit(__IGB_DOWN, &adapter->state))
@@ -2703,6 +2742,7 @@ static inline int igb_tso_adv(struct igb_adapter *adapter,
context_desc->seqnum_seed = 0;
buffer_info->time_stamp = jiffies;
+ buffer_info->next_to_watch = i;
buffer_info->dma = 0;
i++;
if (i == tx_ring->count)
@@ -2766,6 +2806,7 @@ static inline bool igb_tx_csum_adv(struct igb_adapter *adapter,
cpu_to_le32(tx_ring->queue_index << 4);
buffer_info->time_stamp = jiffies;
+ buffer_info->next_to_watch = i;
buffer_info->dma = 0;
i++;
@@ -2784,8 +2825,8 @@ static inline bool igb_tx_csum_adv(struct igb_adapter *adapter,
#define IGB_MAX_DATA_PER_TXD (1<<IGB_MAX_TXD_PWR)
static inline int igb_tx_map_adv(struct igb_adapter *adapter,
- struct igb_ring *tx_ring,
- struct sk_buff *skb)
+ struct igb_ring *tx_ring, struct sk_buff *skb,
+ unsigned int first)
{
struct igb_buffer *buffer_info;
unsigned int len = skb_headlen(skb);
@@ -2799,6 +2840,7 @@ static inline int igb_tx_map_adv(struct igb_adapter *adapter,
buffer_info->length = len;
/* set time_stamp *before* dma to help avoid a possible race */
buffer_info->time_stamp = jiffies;
+ buffer_info->next_to_watch = i;
buffer_info->dma = pci_map_single(adapter->pdev, skb->data, len,
PCI_DMA_TODEVICE);
count++;
@@ -2816,6 +2858,7 @@ static inline int igb_tx_map_adv(struct igb_adapter *adapter,
BUG_ON(len >= IGB_MAX_DATA_PER_TXD);
buffer_info->length = len;
buffer_info->time_stamp = jiffies;
+ buffer_info->next_to_watch = i;
buffer_info->dma = pci_map_page(adapter->pdev,
frag->page,
frag->page_offset,
@@ -2828,8 +2871,9 @@ static inline int igb_tx_map_adv(struct igb_adapter *adapter,
i = 0;
}
- i = (i == 0) ? tx_ring->count - 1 : i - 1;
+ i = ((i == 0) ? tx_ring->count - 1 : i - 1);
tx_ring->buffer_info[i].skb = skb;
+ tx_ring->buffer_info[first].next_to_watch = i;
return count;
}
@@ -2936,6 +2980,7 @@ static int igb_xmit_frame_ring_adv(struct sk_buff *skb,
struct igb_ring *tx_ring)
{
struct igb_adapter *adapter = netdev_priv(netdev);
+ unsigned int first;
unsigned int tx_flags = 0;
unsigned int len;
u8 hdr_len = 0;
@@ -2972,6 +3017,8 @@ static int igb_xmit_frame_ring_adv(struct sk_buff *skb,
if (skb->protocol == htons(ETH_P_IP))
tx_flags |= IGB_TX_FLAGS_IPV4;
+ first = tx_ring->next_to_use;
+
tso = skb_is_gso(skb) ? igb_tso_adv(adapter, tx_ring, skb, tx_flags,
&hdr_len) : 0;
@@ -2987,7 +3034,7 @@ static int igb_xmit_frame_ring_adv(struct sk_buff *skb,
tx_flags |= IGB_TX_FLAGS_CSUM;
igb_tx_queue_adv(adapter, tx_ring, tx_flags,
- igb_tx_map_adv(adapter, tx_ring, skb),
+ igb_tx_map_adv(adapter, tx_ring, skb, first),
skb->len, hdr_len);
netdev->trans_start = jiffies;
@@ -3249,7 +3296,7 @@ void igb_update_stats(struct igb_adapter *adapter)
/* Phy Stats */
if (hw->phy.media_type == e1000_media_type_copper) {
if ((adapter->link_speed == SPEED_1000) &&
- (!hw->phy.ops.read_phy_reg(hw, PHY_1000T_STATUS,
+ (!igb_read_phy_reg(hw, PHY_1000T_STATUS,
&phy_tmp))) {
phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK;
adapter->phy_stats.idle_errors += phy_tmp;
@@ -3332,7 +3379,6 @@ static void igb_write_itr(struct igb_ring *ring)
static irqreturn_t igb_msix_rx(int irq, void *data)
{
struct igb_ring *rx_ring = data;
- struct igb_adapter *adapter = rx_ring->adapter;
/* Write the ITR value calculated at the end of the
* previous interrupt.
@@ -3340,11 +3386,11 @@ static irqreturn_t igb_msix_rx(int irq, void *data)
igb_write_itr(rx_ring);
- if (netif_rx_schedule_prep(adapter->netdev, &rx_ring->napi))
- __netif_rx_schedule(adapter->netdev, &rx_ring->napi);
+ if (netif_rx_schedule_prep(&rx_ring->napi))
+ __netif_rx_schedule(&rx_ring->napi);
#ifdef CONFIG_IGB_DCA
- if (adapter->flags & IGB_FLAG_DCA_ENABLED)
+ if (rx_ring->adapter->flags & IGB_FLAG_DCA_ENABLED)
igb_update_rx_dca(rx_ring);
#endif
return IRQ_HANDLED;
@@ -3357,7 +3403,7 @@ static void igb_update_rx_dca(struct igb_ring *rx_ring)
struct igb_adapter *adapter = rx_ring->adapter;
struct e1000_hw *hw = &adapter->hw;
int cpu = get_cpu();
- int q = rx_ring - adapter->rx_ring;
+ int q = rx_ring->reg_idx;
if (rx_ring->cpu != cpu) {
dca_rxctrl = rd32(E1000_DCA_RXCTRL(q));
@@ -3384,7 +3430,7 @@ static void igb_update_tx_dca(struct igb_ring *tx_ring)
struct igb_adapter *adapter = tx_ring->adapter;
struct e1000_hw *hw = &adapter->hw;
int cpu = get_cpu();
- int q = tx_ring - adapter->tx_ring;
+ int q = tx_ring->reg_idx;
if (tx_ring->cpu != cpu) {
dca_txctrl = rd32(E1000_DCA_TXCTRL(q));
@@ -3493,7 +3539,7 @@ static irqreturn_t igb_intr_msi(int irq, void *data)
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
- netif_rx_schedule(netdev, &adapter->rx_ring[0].napi);
+ netif_rx_schedule(&adapter->rx_ring[0].napi);
return IRQ_HANDLED;
}
@@ -3531,7 +3577,7 @@ static irqreturn_t igb_intr(int irq, void *data)
mod_timer(&adapter->watchdog_timer, jiffies + 1);
}
- netif_rx_schedule(netdev, &adapter->rx_ring[0].napi);
+ netif_rx_schedule(&adapter->rx_ring[0].napi);
return IRQ_HANDLED;
}
@@ -3566,7 +3612,7 @@ static int igb_poll(struct napi_struct *napi, int budget)
!netif_running(netdev)) {
if (adapter->itr_setting & 3)
igb_set_itr(adapter);
- netif_rx_complete(netdev, napi);
+ netif_rx_complete(napi);
if (!test_bit(__IGB_DOWN, &adapter->state))
igb_irq_enable(adapter);
return 0;
@@ -3592,7 +3638,7 @@ static int igb_clean_rx_ring_msix(struct napi_struct *napi, int budget)
/* If not enough Rx work done, exit the polling mode */
if ((work_done == 0) || !netif_running(netdev)) {
- netif_rx_complete(netdev, napi);
+ netif_rx_complete(napi);
if (adapter->itr_setting & 3) {
if (adapter->num_rx_queues == 1)
@@ -3610,12 +3656,6 @@ static int igb_clean_rx_ring_msix(struct napi_struct *napi, int budget)
return 1;
}
-static inline u32 get_head(struct igb_ring *tx_ring)
-{
- void *end = (struct e1000_tx_desc *)tx_ring->desc + tx_ring->count;
- return le32_to_cpu(*(volatile __le32 *)end);
-}
-
/**
* igb_clean_tx_irq - Reclaim resources after transmit completes
* @adapter: board private structure
@@ -3624,24 +3664,25 @@ static inline u32 get_head(struct igb_ring *tx_ring)
static bool igb_clean_tx_irq(struct igb_ring *tx_ring)
{
struct igb_adapter *adapter = tx_ring->adapter;
- struct e1000_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;
- struct e1000_tx_desc *tx_desc;
+ struct e1000_hw *hw = &adapter->hw;
struct igb_buffer *buffer_info;
struct sk_buff *skb;
- unsigned int i;
- u32 head, oldhead;
- unsigned int count = 0;
+ union e1000_adv_tx_desc *tx_desc, *eop_desc;
unsigned int total_bytes = 0, total_packets = 0;
- bool retval = true;
+ unsigned int i, eop, count = 0;
+ bool cleaned = false;
- rmb();
- head = get_head(tx_ring);
i = tx_ring->next_to_clean;
- while (1) {
- while (i != head) {
- tx_desc = E1000_TX_DESC(*tx_ring, i);
+ eop = tx_ring->buffer_info[i].next_to_watch;
+ eop_desc = E1000_TX_DESC_ADV(*tx_ring, eop);
+
+ while ((eop_desc->wb.status & cpu_to_le32(E1000_TXD_STAT_DD)) &&
+ (count < tx_ring->count)) {
+ for (cleaned = false; !cleaned; count++) {
+ tx_desc = E1000_TX_DESC_ADV(*tx_ring, i);
buffer_info = &tx_ring->buffer_info[i];
+ cleaned = (i == eop);
skb = buffer_info->skb;
if (skb) {
@@ -3656,25 +3697,17 @@ static bool igb_clean_tx_irq(struct igb_ring *tx_ring)
}
igb_unmap_and_free_tx_resource(adapter, buffer_info);
+ tx_desc->wb.status = 0;
i++;
if (i == tx_ring->count)
i = 0;
-
- count++;
- if (count == IGB_MAX_TX_CLEAN) {
- retval = false;
- goto done_cleaning;
- }
}
- oldhead = head;
- rmb();
- head = get_head(tx_ring);
- if (head == oldhead)
- goto done_cleaning;
- } /* while (1) */
-
-done_cleaning:
+
+ eop = tx_ring->buffer_info[i].next_to_watch;
+ eop_desc = E1000_TX_DESC_ADV(*tx_ring, eop);
+ }
+
tx_ring->next_to_clean = i;
if (unlikely(count &&
@@ -3701,7 +3734,6 @@ done_cleaning:
&& !(rd32(E1000_STATUS) &
E1000_STATUS_TXOFF)) {
- tx_desc = E1000_TX_DESC(*tx_ring, i);
/* detected Tx unit hang */
dev_err(&adapter->pdev->dev,
"Detected Tx Unit Hang\n"
@@ -3710,9 +3742,9 @@ done_cleaning:
" TDT <%x>\n"
" next_to_use <%x>\n"
" next_to_clean <%x>\n"
- " head (WB) <%x>\n"
"buffer_info[next_to_clean]\n"
" time_stamp <%lx>\n"
+ " next_to_watch <%x>\n"
" jiffies <%lx>\n"
" desc.status <%x>\n",
tx_ring->queue_index,
@@ -3720,10 +3752,10 @@ done_cleaning:
readl(adapter->hw.hw_addr + tx_ring->tail),
tx_ring->next_to_use,
tx_ring->next_to_clean,
- head,
tx_ring->buffer_info[i].time_stamp,
+ eop,
jiffies,
- tx_desc->upper.fields.status);
+ eop_desc->wb.status);
netif_stop_subqueue(netdev, tx_ring->queue_index);
}
}
@@ -3733,7 +3765,7 @@ done_cleaning:
tx_ring->tx_stats.packets += total_packets;
adapter->net_stats.tx_bytes += total_bytes;
adapter->net_stats.tx_packets += total_packets;
- return retval;
+ return (count < tx_ring->count);
}
#ifdef CONFIG_IGB_LRO
@@ -3919,8 +3951,10 @@ send_up:
next_buffer = &rx_ring->buffer_info[i];
if (!(staterr & E1000_RXD_STAT_EOP)) {
- buffer_info->skb = xchg(&next_buffer->skb, skb);
- buffer_info->dma = xchg(&next_buffer->dma, 0);
+ buffer_info->skb = next_buffer->skb;
+ buffer_info->dma = next_buffer->dma;
+ next_buffer->skb = skb;
+ next_buffer->dma = 0;
goto next_desc;
}
@@ -3938,8 +3972,6 @@ send_up:
igb_receive_skb(rx_ring, staterr, rx_desc, skb);
- netdev->last_rx = jiffies;
-
next_desc:
rx_desc->wb.upper.status_error = 0;
@@ -4102,9 +4134,8 @@ static int igb_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
case SIOCGMIIREG:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- if (adapter->hw.phy.ops.read_phy_reg(&adapter->hw,
- data->reg_num
- & 0x1F, &data->val_out))
+ if (igb_read_phy_reg(&adapter->hw, data->reg_num & 0x1F,
+ &data->val_out))
return -EIO;
break;
case SIOCSMIIREG:
@@ -4474,27 +4505,38 @@ static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev)
struct net_device *netdev = pci_get_drvdata(pdev);
struct igb_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw;
+ pci_ers_result_t result;
int err;
if (adapter->need_ioport)
err = pci_enable_device(pdev);
else
err = pci_enable_device_mem(pdev);
+
if (err) {
dev_err(&pdev->dev,
"Cannot re-enable PCI device after reset.\n");
- return PCI_ERS_RESULT_DISCONNECT;
- }
- pci_set_master(pdev);
- pci_restore_state(pdev);
+ result = PCI_ERS_RESULT_DISCONNECT;
+ } else {
+ pci_set_master(pdev);
+ pci_restore_state(pdev);
- pci_enable_wake(pdev, PCI_D3hot, 0);
- pci_enable_wake(pdev, PCI_D3cold, 0);
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0);
- igb_reset(adapter);
- wr32(E1000_WUS, ~0);
+ igb_reset(adapter);
+ wr32(E1000_WUS, ~0);
+ result = PCI_ERS_RESULT_RECOVERED;
+ }
+
+ err = pci_cleanup_aer_uncorrect_error_status(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "pci_cleanup_aer_uncorrect_error_status "
+ "failed 0x%0x\n", err);
+ /* non-fatal, continue */
+ }
- return PCI_ERS_RESULT_RECOVERED;
+ return result;
}
/**
@@ -4522,7 +4564,6 @@ static void igb_io_resume(struct pci_dev *pdev)
/* let the f/w know that the h/w is now under the control of the
* driver. */
igb_get_hw_control(adapter);
-
}
/* igb_main.c */
diff --git a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
index 1f25263dc7eb..170b12d1d70e 100644
--- a/drivers/net/ioc3-eth.c
+++ b/drivers/net/ioc3-eth.c
@@ -390,11 +390,8 @@ static int nic_init(struct ioc3 *ioc3)
}
printk("Found %s NIC", type);
- if (type != unknown) {
- printk (" registration number %02x:%02x:%02x:%02x:%02x:%02x,"
- " CRC %02x", serial[0], serial[1], serial[2],
- serial[3], serial[4], serial[5], crc);
- }
+ if (type != unknown)
+ printk (" registration number %pM, CRC %02x", serial, crc);
printk(".\n");
return 0;
@@ -443,12 +440,9 @@ static void ioc3_get_eaddr_nic(struct ioc3_private *ip)
*/
static void ioc3_get_eaddr(struct ioc3_private *ip)
{
- DECLARE_MAC_BUF(mac);
-
ioc3_get_eaddr_nic(ip);
- printk("Ethernet address is %s.\n",
- print_mac(mac, priv_netdev(ip)->dev_addr));
+ printk("Ethernet address is %pM.\n", priv_netdev(ip)->dev_addr);
}
static void __ioc3_set_mac_address(struct net_device *dev)
@@ -627,7 +621,6 @@ static inline void ioc3_rx(struct ioc3_private *ip)
rxb = (struct ioc3_erxbuf *) new_skb->data;
skb_reserve(new_skb, RX_OFFSET);
- priv_netdev(ip)->last_rx = jiffies;
ip->stats.rx_packets++; /* Statistics */
ip->stats.rx_bytes += len;
} else {
diff --git a/drivers/net/ipg.c b/drivers/net/ipg.c
index 059369885be1..7b6d435a8468 100644
--- a/drivers/net/ipg.c
+++ b/drivers/net/ipg.c
@@ -1222,7 +1222,6 @@ static void ipg_nic_rx_with_start_and_end(struct net_device *dev,
skb->protocol = eth_type_trans(skb, dev);
skb->ip_summed = CHECKSUM_NONE;
netif_rx(skb);
- dev->last_rx = jiffies;
sp->rx_buff[entry] = NULL;
}
@@ -1256,7 +1255,6 @@ static void ipg_nic_rx_with_start(struct net_device *dev,
jumbo->skb = skb;
sp->rx_buff[entry] = NULL;
- dev->last_rx = jiffies;
}
static void ipg_nic_rx_with_end(struct net_device *dev,
@@ -1292,7 +1290,6 @@ static void ipg_nic_rx_with_end(struct net_device *dev,
}
}
- dev->last_rx = jiffies;
jumbo->found_start = 0;
jumbo->current_size = 0;
jumbo->skb = NULL;
@@ -1325,7 +1322,6 @@ static void ipg_nic_rx_no_start_no_end(struct net_device *dev,
skb->data, sp->rxfrag_size);
}
}
- dev->last_rx = jiffies;
ipg_nic_rx_free_skb(dev);
}
} else {
@@ -1494,11 +1490,6 @@ static int ipg_nic_rx(struct net_device *dev)
* when processing completes.
*/
netif_rx(skb);
-
- /* Record frame receive time (jiffies = Linux
- * kernel current time stamp).
- */
- dev->last_rx = jiffies;
}
/* Assure RX buffer is not reused by IPG. */
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c
index 2ff181861d2d..3c58e67ef1e4 100644
--- a/drivers/net/irda/ali-ircc.c
+++ b/drivers/net/irda/ali-ircc.c
@@ -292,7 +292,7 @@ static int ali_ircc_open(int i, chipio_t *info)
return -ENOMEM;
}
- self = dev->priv;
+ self = netdev_priv(dev);
self->netdev = dev;
spin_lock_init(&self->lock);
@@ -665,7 +665,7 @@ static irqreturn_t ali_ircc_interrupt(int irq, void *dev_id)
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __func__);
- self = dev->priv;
+ self = netdev_priv(dev);
spin_lock(&self->lock);
@@ -1333,7 +1333,7 @@ static int ali_ircc_net_open(struct net_device *dev)
IRDA_ASSERT(dev != NULL, return -1;);
- self = (struct ali_ircc_cb *) dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return 0;);
@@ -1396,7 +1396,7 @@ static int ali_ircc_net_close(struct net_device *dev)
IRDA_ASSERT(dev != NULL, return -1;);
- self = (struct ali_ircc_cb *) dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return 0;);
/* Stop device */
@@ -1436,7 +1436,7 @@ static int ali_ircc_fir_hard_xmit(struct sk_buff *skb, struct net_device *dev)
IRDA_DEBUG(1, "%s(), ---------------- Start -----------------\n", __func__ );
- self = (struct ali_ircc_cb *) dev->priv;
+ self = netdev_priv(dev);
iobase = self->io.fir_base;
netif_stop_queue(dev);
@@ -1931,7 +1931,6 @@ static int ali_ircc_dma_receive_complete(struct ali_ircc_cb *self)
skb_reset_mac_header(skb);
skb->protocol = htons(ETH_P_IRDA);
netif_rx(skb);
- self->netdev->last_rx = jiffies;
}
}
@@ -1960,7 +1959,7 @@ static int ali_ircc_sir_hard_xmit(struct sk_buff *skb, struct net_device *dev)
IRDA_ASSERT(dev != NULL, return 0;);
- self = (struct ali_ircc_cb *) dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return 0;);
iobase = self->io.sir_base;
@@ -2028,7 +2027,7 @@ static int ali_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
IRDA_ASSERT(dev != NULL, return -1;);
- self = dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return -1;);
@@ -2114,7 +2113,7 @@ static int ali_ircc_is_receiving(struct ali_ircc_cb *self)
static struct net_device_stats *ali_ircc_net_get_stats(struct net_device *dev)
{
- struct ali_ircc_cb *self = (struct ali_ircc_cb *) dev->priv;
+ struct ali_ircc_cb *self = netdev_priv(dev);
IRDA_DEBUG(2, "%s(), ---------------- Start ----------------\n", __func__ );
diff --git a/drivers/net/irda/au1k_ir.c b/drivers/net/irda/au1k_ir.c
index a1e4508717c8..6c4b53ffbcac 100644
--- a/drivers/net/irda/au1k_ir.c
+++ b/drivers/net/irda/au1k_ir.c
@@ -620,7 +620,6 @@ static int au1k_irda_rx(struct net_device *dev)
/* next descriptor */
prxd = aup->rx_ring[aup->rx_head];
flags = prxd->flags;
- dev->last_rx = jiffies;
}
return 0;
diff --git a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
index 69d16b30323b..687c2d53d4d2 100644
--- a/drivers/net/irda/donauboe.c
+++ b/drivers/net/irda/donauboe.c
@@ -979,7 +979,7 @@ toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev)
unsigned long flags;
struct irda_skb_cb *cb = (struct irda_skb_cb *) skb->cb;
- self = (struct toshoboe_cb *) dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT (self != NULL, return 0; );
@@ -1384,7 +1384,7 @@ toshoboe_net_close (struct net_device *dev)
IRDA_DEBUG (4, "%s()\n", __func__);
IRDA_ASSERT (dev != NULL, return -1; );
- self = (struct toshoboe_cb *) dev->priv;
+ self = netdev_priv(dev);
/* Stop device */
netif_stop_queue(dev);
@@ -1422,7 +1422,7 @@ toshoboe_net_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
IRDA_ASSERT (dev != NULL, return -1; );
- self = dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT (self != NULL, return -1; );
@@ -1546,7 +1546,7 @@ toshoboe_open (struct pci_dev *pci_dev, const struct pci_device_id *pdid)
return -ENOMEM;
}
- self = dev->priv;
+ self = netdev_priv(dev);
self->netdev = dev;
self->pdev = pci_dev;
self->base = pci_resource_start(pci_dev,0);
diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
index b5d6b9ac162a..205e4e825a97 100644
--- a/drivers/net/irda/irda-usb.c
+++ b/drivers/net/irda/irda-usb.c
@@ -384,7 +384,7 @@ static void speed_bulk_callback(struct urb *urb)
*/
static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
{
- struct irda_usb_cb *self = netdev->priv;
+ struct irda_usb_cb *self = netdev_priv(netdev);
struct urb *urb = self->tx_urb;
unsigned long flags;
s32 speed;
@@ -628,7 +628,7 @@ static void write_bulk_callback(struct urb *urb)
static void irda_usb_net_timeout(struct net_device *netdev)
{
unsigned long flags;
- struct irda_usb_cb *self = netdev->priv;
+ struct irda_usb_cb *self = netdev_priv(netdev);
struct urb *urb;
int done = 0; /* If we have made any progress */
@@ -929,7 +929,6 @@ static void irda_usb_receive(struct urb *urb)
/* Keep stats up to date */
self->stats.rx_bytes += len;
self->stats.rx_packets++;
- self->netdev->last_rx = jiffies;
done:
/* Note : at this point, the URB we've just received (urb)
@@ -1175,7 +1174,7 @@ static int irda_usb_net_open(struct net_device *netdev)
IRDA_DEBUG(1, "%s()\n", __func__);
IRDA_ASSERT(netdev != NULL, return -1;);
- self = (struct irda_usb_cb *) netdev->priv;
+ self = netdev_priv(netdev);
IRDA_ASSERT(self != NULL, return -1;);
spin_lock_irqsave(&self->lock, flags);
@@ -1257,7 +1256,7 @@ static int irda_usb_net_close(struct net_device *netdev)
IRDA_DEBUG(1, "%s()\n", __func__);
IRDA_ASSERT(netdev != NULL, return -1;);
- self = (struct irda_usb_cb *) netdev->priv;
+ self = netdev_priv(netdev);
IRDA_ASSERT(self != NULL, return -1;);
/* Clear this flag *before* unlinking the urbs and *before*
@@ -1306,7 +1305,7 @@ static int irda_usb_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
int ret = 0;
IRDA_ASSERT(dev != NULL, return -1;);
- self = dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return -1;);
IRDA_DEBUG(2, "%s(), %s, (cmd=0x%X)\n", __func__, dev->name, cmd);
@@ -1348,7 +1347,7 @@ static int irda_usb_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
*/
static struct net_device_stats *irda_usb_net_get_stats(struct net_device *dev)
{
- struct irda_usb_cb *self = dev->priv;
+ struct irda_usb_cb *self = netdev_priv(dev);
return &self->stats;
}
@@ -1641,7 +1640,7 @@ static int irda_usb_probe(struct usb_interface *intf,
goto err_out;
SET_NETDEV_DEV(net, &intf->dev);
- self = net->priv;
+ self = netdev_priv(net);
self->netdev = net;
spin_lock_init(&self->lock);
init_timer(&self->rx_defer_timer);
diff --git a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
index 6bcee01c684c..d53aa9582137 100644
--- a/drivers/net/irda/irtty-sir.c
+++ b/drivers/net/irda/irtty-sir.c
@@ -191,7 +191,7 @@ static int irtty_do_write(struct sir_dev *dev, const unsigned char *ptr, size_t
tty = priv->tty;
if (!tty->ops->write)
return 0;
- tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
+ set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
writelen = tty_write_room(tty);
if (writelen > len)
writelen = len;
@@ -263,8 +263,7 @@ static void irtty_write_wakeup(struct tty_struct *tty)
IRDA_ASSERT(priv != NULL, return;);
IRDA_ASSERT(priv->magic == IRTTY_MAGIC, return;);
- tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
-
+ clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
if (priv->dev)
sirdev_write_complete(priv->dev);
}
@@ -522,7 +521,7 @@ static void irtty_close(struct tty_struct *tty)
/* Stop tty */
irtty_stop_receiver(tty, TRUE);
- tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+ clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
if (tty->ops->stop)
tty->ops->stop(tty);
diff --git a/drivers/net/irda/kingsun-sir.c b/drivers/net/irda/kingsun-sir.c
index e1429fc6d050..c747c874d44d 100644
--- a/drivers/net/irda/kingsun-sir.c
+++ b/drivers/net/irda/kingsun-sir.c
@@ -235,7 +235,6 @@ static void kingsun_rcv_irq(struct urb *urb)
&kingsun->stats,
&kingsun->rx_buff, bytes[i]);
}
- kingsun->netdev->last_rx = jiffies;
do_gettimeofday(&kingsun->rx_time);
kingsun->receiving =
(kingsun->rx_buff.state != OUTSIDE_FRAME)
diff --git a/drivers/net/irda/ks959-sir.c b/drivers/net/irda/ks959-sir.c
index 2e67ae015d91..600d96f9cdb7 100644
--- a/drivers/net/irda/ks959-sir.c
+++ b/drivers/net/irda/ks959-sir.c
@@ -474,7 +474,6 @@ static void ks959_rcv_irq(struct urb *urb)
bytes[i]);
}
}
- kingsun->netdev->last_rx = jiffies;
do_gettimeofday(&kingsun->rx_time);
kingsun->receiving =
(kingsun->rx_unwrap_buff.state != OUTSIDE_FRAME) ? 1 : 0;
diff --git a/drivers/net/irda/ksdazzle-sir.c b/drivers/net/irda/ksdazzle-sir.c
index 3843b5faba8b..0e7f89337b25 100644
--- a/drivers/net/irda/ksdazzle-sir.c
+++ b/drivers/net/irda/ksdazzle-sir.c
@@ -371,7 +371,6 @@ static void ksdazzle_rcv_irq(struct urb *urb)
async_unwrap_char(kingsun->netdev, &kingsun->stats,
&kingsun->rx_unwrap_buff, bytes[i]);
}
- kingsun->netdev->last_rx = jiffies;
kingsun->receiving =
(kingsun->rx_unwrap_buff.state != OUTSIDE_FRAME) ? 1 : 0;
}
diff --git a/drivers/net/irda/ma600-sir.c b/drivers/net/irda/ma600-sir.c
index 1ceed9cfb7c4..e91216452379 100644
--- a/drivers/net/irda/ma600-sir.c
+++ b/drivers/net/irda/ma600-sir.c
@@ -236,7 +236,7 @@ static int ma600_change_speed(struct sir_dev *dev, unsigned speed)
* avoid the state machine complexity before we get things working
*/
-int ma600_reset(struct sir_dev *dev)
+static int ma600_reset(struct sir_dev *dev)
{
IRDA_DEBUG(2, "%s()\n", __func__);
diff --git a/drivers/net/irda/mcs7780.c b/drivers/net/irda/mcs7780.c
index ad92d3ff1c40..904c9610c0dd 100644
--- a/drivers/net/irda/mcs7780.c
+++ b/drivers/net/irda/mcs7780.c
@@ -806,7 +806,6 @@ static void mcs_receive_irq(struct urb *urb)
mcs_unwrap_fir(mcs, urb->transfer_buffer,
urb->actual_length);
}
- mcs->netdev->last_rx = jiffies;
do_gettimeofday(&mcs->rx_time);
}
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index 8583d951a6ad..2c6bf2d11bb1 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -373,7 +373,7 @@ static int __init nsc_ircc_open(chipio_t *info)
return -ENOMEM;
}
- self = dev->priv;
+ self = netdev_priv(dev);
self->netdev = dev;
spin_lock_init(&self->lock);
@@ -1354,7 +1354,7 @@ static int nsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
__s32 speed;
__u8 bank;
- self = (struct nsc_ircc_cb *) dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return 0;);
@@ -1427,7 +1427,7 @@ static int nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
__u8 bank;
int mtt, diff;
- self = (struct nsc_ircc_cb *) dev->priv;
+ self = netdev_priv(dev);
iobase = self->io.fir_base;
netif_stop_queue(dev);
@@ -1896,7 +1896,6 @@ static int nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase)
skb_reset_mac_header(skb);
skb->protocol = htons(ETH_P_IRDA);
netif_rx(skb);
- self->netdev->last_rx = jiffies;
}
}
/* Restore bank register */
@@ -2085,7 +2084,7 @@ static irqreturn_t nsc_ircc_interrupt(int irq, void *dev_id)
__u8 bsr, eir;
int iobase;
- self = dev->priv;
+ self = netdev_priv(dev);
spin_lock(&self->lock);
@@ -2166,7 +2165,7 @@ static int nsc_ircc_net_open(struct net_device *dev)
IRDA_DEBUG(4, "%s()\n", __func__);
IRDA_ASSERT(dev != NULL, return -1;);
- self = (struct nsc_ircc_cb *) dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return 0;);
@@ -2229,7 +2228,7 @@ static int nsc_ircc_net_close(struct net_device *dev)
IRDA_ASSERT(dev != NULL, return -1;);
- self = (struct nsc_ircc_cb *) dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return 0;);
/* Stop device */
@@ -2275,7 +2274,7 @@ static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
IRDA_ASSERT(dev != NULL, return -1;);
- self = dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return -1;);
@@ -2310,7 +2309,7 @@ static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev)
{
- struct nsc_ircc_cb *self = (struct nsc_ircc_cb *) dev->priv;
+ struct nsc_ircc_cb *self = netdev_priv(dev);
return &self->stats;
}
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index c5b02b66f756..a0ee05318155 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -225,7 +225,6 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
}
lsr = STLSR;
}
- dev->last_rx = jiffies;
si->last_oscr = OSCR;
break;
@@ -237,7 +236,6 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id)
si->stats.rx_bytes++;
async_unwrap_char(dev, &si->stats, &si->rx_buff, STRBR);
} while (STLSR & LSR_DR);
- dev->last_rx = jiffies;
si->last_oscr = OSCR;
break;
@@ -397,8 +395,6 @@ static void pxa_irda_fir_irq_eif(struct pxa_irda *si, struct net_device *dev, in
si->stats.rx_packets++;
si->stats.rx_bytes += len;
-
- dev->last_rx = jiffies;
}
}
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c
index a95188948de7..ccde5829ba21 100644
--- a/drivers/net/irda/sa1100_ir.c
+++ b/drivers/net/irda/sa1100_ir.c
@@ -298,7 +298,7 @@ static int sa1100_irda_suspend(struct platform_device *pdev, pm_message_t state)
if (!dev)
return 0;
- si = dev->priv;
+ si = netdev_priv(dev);
if (si->open) {
/*
* Stop the transmit queue
@@ -323,7 +323,7 @@ static int sa1100_irda_resume(struct platform_device *pdev)
if (!dev)
return 0;
- si = dev->priv;
+ si = netdev_priv(dev);
if (si->open) {
/*
* If we missed a speed change, initialise at the new speed
@@ -359,7 +359,7 @@ static int sa1100_irda_resume(struct platform_device *pdev)
*/
static void sa1100_irda_hpsir_irq(struct net_device *dev)
{
- struct sa1100_irda *si = dev->priv;
+ struct sa1100_irda *si = netdev_priv(dev);
int status;
status = Ser2UTSR0;
@@ -410,7 +410,6 @@ static void sa1100_irda_hpsir_irq(struct net_device *dev)
Ser2UTDR);
} while (Ser2UTSR1 & UTSR1_RNE);
- dev->last_rx = jiffies;
}
if (status & UTSR0_TFS && si->tx_buff.len) {
@@ -515,7 +514,6 @@ static void sa1100_irda_fir_error(struct sa1100_irda *si, struct net_device *dev
sa1100_irda_rx_alloc(si);
netif_rx(skb);
- dev->last_rx = jiffies;
} else {
/*
* Remap the buffer.
@@ -534,7 +532,7 @@ static void sa1100_irda_fir_error(struct sa1100_irda *si, struct net_device *dev
*/
static void sa1100_irda_fir_irq(struct net_device *dev)
{
- struct sa1100_irda *si = dev->priv;
+ struct sa1100_irda *si = netdev_priv(dev);
/*
* Stop RX DMA
@@ -582,7 +580,7 @@ static void sa1100_irda_fir_irq(struct net_device *dev)
static irqreturn_t sa1100_irda_irq(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
- if (IS_FIR(((struct sa1100_irda *)dev->priv)))
+ if (IS_FIR(((struct sa1100_irda *)netdev_priv(dev))))
sa1100_irda_fir_irq(dev);
else
sa1100_irda_hpsir_irq(dev);
@@ -595,7 +593,7 @@ static irqreturn_t sa1100_irda_irq(int irq, void *dev_id)
static void sa1100_irda_txdma_irq(void *id)
{
struct net_device *dev = id;
- struct sa1100_irda *si = dev->priv;
+ struct sa1100_irda *si = netdev_priv(dev);
struct sk_buff *skb = si->txskb;
si->txskb = NULL;
@@ -649,7 +647,7 @@ static void sa1100_irda_txdma_irq(void *id)
static int sa1100_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct sa1100_irda *si = dev->priv;
+ struct sa1100_irda *si = netdev_priv(dev);
int speed = irda_get_next_speed(skb);
/*
@@ -724,7 +722,7 @@ static int
sa1100_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
{
struct if_irda_req *rq = (struct if_irda_req *)ifreq;
- struct sa1100_irda *si = dev->priv;
+ struct sa1100_irda *si = netdev_priv(dev);
int ret = -EOPNOTSUPP;
switch (cmd) {
@@ -766,13 +764,13 @@ sa1100_irda_ioctl(struct net_device *dev, struct ifreq *ifreq, int cmd)
static struct net_device_stats *sa1100_irda_stats(struct net_device *dev)
{
- struct sa1100_irda *si = dev->priv;
+ struct sa1100_irda *si = netdev_priv(dev);
return &si->stats;
}
static int sa1100_irda_start(struct net_device *dev)
{
- struct sa1100_irda *si = dev->priv;
+ struct sa1100_irda *si = netdev_priv(dev);
int err;
si->speed = 9600;
@@ -835,7 +833,7 @@ err_irq:
static int sa1100_irda_stop(struct net_device *dev)
{
- struct sa1100_irda *si = dev->priv;
+ struct sa1100_irda *si = netdev_priv(dev);
disable_irq(dev->irq);
sa1100_irda_shutdown(si);
@@ -908,7 +906,7 @@ static int sa1100_irda_probe(struct platform_device *pdev)
if (!dev)
goto err_mem_4;
- si = dev->priv;
+ si = netdev_priv(dev);
si->dev = &pdev->dev;
si->pdata = pdev->dev.platform_data;
@@ -987,7 +985,7 @@ static int sa1100_irda_remove(struct platform_device *pdev)
struct net_device *dev = platform_get_drvdata(pdev);
if (dev) {
- struct sa1100_irda *si = dev->priv;
+ struct sa1100_irda *si = netdev_priv(dev);
unregister_netdev(dev);
kfree(si->tx_buff.head);
kfree(si->rx_buff.head);
diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
index 3f32909c24c8..ceef040aa76d 100644
--- a/drivers/net/irda/sir_dev.c
+++ b/drivers/net/irda/sir_dev.c
@@ -584,14 +584,14 @@ EXPORT_SYMBOL(sirdev_receive);
static struct net_device_stats *sirdev_get_stats(struct net_device *ndev)
{
- struct sir_dev *dev = ndev->priv;
+ struct sir_dev *dev = netdev_priv(ndev);
return (dev) ? &dev->stats : NULL;
}
static int sirdev_hard_xmit(struct sk_buff *skb, struct net_device *ndev)
{
- struct sir_dev *dev = ndev->priv;
+ struct sir_dev *dev = netdev_priv(ndev);
unsigned long flags;
int actual = 0;
int err;
@@ -683,7 +683,7 @@ static int sirdev_hard_xmit(struct sk_buff *skb, struct net_device *ndev)
static int sirdev_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
{
struct if_irda_req *irq = (struct if_irda_req *) rq;
- struct sir_dev *dev = ndev->priv;
+ struct sir_dev *dev = netdev_priv(ndev);
int ret = 0;
IRDA_ASSERT(dev != NULL, return -1;);
@@ -795,7 +795,7 @@ static void sirdev_free_buffers(struct sir_dev *dev)
static int sirdev_open(struct net_device *ndev)
{
- struct sir_dev *dev = ndev->priv;
+ struct sir_dev *dev = netdev_priv(ndev);
const struct sir_driver *drv = dev->drv;
if (!drv)
@@ -840,7 +840,7 @@ errout_dec:
static int sirdev_close(struct net_device *ndev)
{
- struct sir_dev *dev = ndev->priv;
+ struct sir_dev *dev = netdev_priv(ndev);
const struct sir_driver *drv;
// IRDA_DEBUG(0, "%s\n", __func__);
@@ -896,7 +896,7 @@ struct sir_dev * sirdev_get_instance(const struct sir_driver *drv, const char *n
IRDA_ERROR("%s - Can't allocate memory for IrDA control block!\n", __func__);
goto out;
}
- dev = ndev->priv;
+ dev = netdev_priv(ndev);
irda_init_max_qos_capabilies(&dev->qos);
dev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index b5360fe99d3a..5d09e157e15b 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -872,7 +872,7 @@ static void smsc_ircc_timeout(struct net_device *dev)
* waits until the next transmit interrupt, and continues until the
* frame is transmitted.
*/
-int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
+static int smsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
{
struct smsc_ircc_cb *self;
unsigned long flags;
@@ -1128,7 +1128,7 @@ static void smsc_ircc_change_speed(struct smsc_ircc_cb *self, u32 speed)
* Set speed of IrDA port to specified baudrate
*
*/
-void smsc_ircc_set_sir_speed(struct smsc_ircc_cb *self, __u32 speed)
+static void smsc_ircc_set_sir_speed(struct smsc_ircc_cb *self, __u32 speed)
{
int iobase;
int fcr; /* FIFO control reg */
@@ -1894,7 +1894,7 @@ static void __exit smsc_ircc_cleanup(void)
* This function *must* be called with spinlock held, because it may
* be called from the irq handler (via smsc_ircc_change_speed()). - Jean II
*/
-void smsc_ircc_sir_start(struct smsc_ircc_cb *self)
+static void smsc_ircc_sir_start(struct smsc_ircc_cb *self)
{
struct net_device *dev;
int fir_base, sir_base;
diff --git a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
index 3575804fd7c6..ca4cd9266e55 100644
--- a/drivers/net/irda/stir4200.c
+++ b/drivers/net/irda/stir4200.c
@@ -824,7 +824,6 @@ static void stir_rcv_irq(struct urb *urb)
unwrap_chars(stir, urb->transfer_buffer,
urb->actual_length);
- stir->netdev->last_rx = jiffies;
do_gettimeofday(&stir->rx_time);
}
diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
index 84e609ea5fbb..74c78cf7a333 100644
--- a/drivers/net/irda/via-ircc.c
+++ b/drivers/net/irda/via-ircc.c
@@ -334,7 +334,7 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
if (dev == NULL)
return -ENOMEM;
- self = dev->priv;
+ self = netdev_priv(dev);
self->netdev = dev;
spin_lock_init(&self->lock);
@@ -824,7 +824,7 @@ static int via_ircc_hard_xmit_sir(struct sk_buff *skb,
u16 iobase;
__u32 speed;
- self = (struct via_ircc_cb *) dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return 0;);
iobase = self->io.fir_base;
@@ -896,7 +896,7 @@ static int via_ircc_hard_xmit_fir(struct sk_buff *skb,
__u32 speed;
unsigned long flags;
- self = (struct via_ircc_cb *) dev->priv;
+ self = netdev_priv(dev);
iobase = self->io.fir_base;
if (self->st_fifo.len)
@@ -1349,7 +1349,7 @@ static int RxTimerHandler(struct via_ircc_cb *self, int iobase)
static irqreturn_t via_ircc_interrupt(int dummy, void *dev_id)
{
struct net_device *dev = dev_id;
- struct via_ircc_cb *self = dev->priv;
+ struct via_ircc_cb *self = netdev_priv(dev);
int iobase;
u8 iHostIntType, iRxIntType, iTxIntType;
@@ -1522,7 +1522,7 @@ static int via_ircc_net_open(struct net_device *dev)
IRDA_DEBUG(3, "%s()\n", __func__);
IRDA_ASSERT(dev != NULL, return -1;);
- self = (struct via_ircc_cb *) dev->priv;
+ self = netdev_priv(dev);
self->stats.rx_packets = 0;
IRDA_ASSERT(self != NULL, return 0;);
iobase = self->io.fir_base;
@@ -1589,7 +1589,7 @@ static int via_ircc_net_close(struct net_device *dev)
IRDA_DEBUG(3, "%s()\n", __func__);
IRDA_ASSERT(dev != NULL, return -1;);
- self = (struct via_ircc_cb *) dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return 0;);
/* Stop device */
@@ -1628,7 +1628,7 @@ static int via_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq,
int ret = 0;
IRDA_ASSERT(dev != NULL, return -1;);
- self = dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return -1;);
IRDA_DEBUG(1, "%s(), %s, (cmd=0x%X)\n", __func__, dev->name,
cmd);
@@ -1663,7 +1663,7 @@ static int via_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq,
static struct net_device_stats *via_ircc_net_get_stats(struct net_device
*dev)
{
- struct via_ircc_cb *self = (struct via_ircc_cb *) dev->priv;
+ struct via_ircc_cb *self = netdev_priv(dev);
return &self->stats;
}
diff --git a/drivers/net/irda/vlsi_ir.c b/drivers/net/irda/vlsi_ir.c
index 9c926d205de9..0d30f8d659a1 100644
--- a/drivers/net/irda/vlsi_ir.c
+++ b/drivers/net/irda/vlsi_ir.c
@@ -178,7 +178,7 @@ static void vlsi_proc_pdev(struct seq_file *seq, struct pci_dev *pdev)
static void vlsi_proc_ndev(struct seq_file *seq, struct net_device *ndev)
{
- vlsi_irda_dev_t *idev = ndev->priv;
+ vlsi_irda_dev_t *idev = netdev_priv(ndev);
u8 byte;
u16 word;
unsigned delta1, delta2;
@@ -346,7 +346,7 @@ static void vlsi_proc_ring(struct seq_file *seq, struct vlsi_ring *r)
static int vlsi_seq_show(struct seq_file *seq, void *v)
{
struct net_device *ndev = seq->private;
- vlsi_irda_dev_t *idev = ndev->priv;
+ vlsi_irda_dev_t *idev = netdev_priv(ndev);
unsigned long flags;
seq_printf(seq, "\n%s %s\n\n", DRIVER_NAME, DRIVER_VERSION);
@@ -543,7 +543,7 @@ static int vlsi_process_rx(struct vlsi_ring *r, struct ring_descr *rd)
struct sk_buff *skb;
int ret = 0;
struct net_device *ndev = (struct net_device *)pci_get_drvdata(r->pdev);
- vlsi_irda_dev_t *idev = ndev->priv;
+ vlsi_irda_dev_t *idev = netdev_priv(ndev);
pci_dma_sync_single_for_cpu(r->pdev, rd_get_addr(rd), r->len, r->dir);
/* dma buffer now owned by the CPU */
@@ -600,7 +600,6 @@ static int vlsi_process_rx(struct vlsi_ring *r, struct ring_descr *rd)
netif_rx(skb);
else
netif_rx_ni(skb);
- ndev->last_rx = jiffies;
done:
rd_set_status(rd, 0);
@@ -638,7 +637,7 @@ static void vlsi_fill_rx(struct vlsi_ring *r)
static void vlsi_rx_interrupt(struct net_device *ndev)
{
- vlsi_irda_dev_t *idev = ndev->priv;
+ vlsi_irda_dev_t *idev = netdev_priv(ndev);
struct vlsi_ring *r = idev->rx_ring;
struct ring_descr *rd;
int ret;
@@ -856,7 +855,7 @@ static int vlsi_set_baud(vlsi_irda_dev_t *idev, unsigned iobase)
static int vlsi_hard_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
- vlsi_irda_dev_t *idev = ndev->priv;
+ vlsi_irda_dev_t *idev = netdev_priv(ndev);
struct vlsi_ring *r = idev->tx_ring;
struct ring_descr *rd;
unsigned long flags;
@@ -1063,7 +1062,7 @@ drop:
static void vlsi_tx_interrupt(struct net_device *ndev)
{
- vlsi_irda_dev_t *idev = ndev->priv;
+ vlsi_irda_dev_t *idev = netdev_priv(ndev);
struct vlsi_ring *r = idev->tx_ring;
struct ring_descr *rd;
unsigned iobase;
@@ -1262,7 +1261,7 @@ static inline void vlsi_clear_regs(unsigned iobase)
static int vlsi_init_chip(struct pci_dev *pdev)
{
struct net_device *ndev = pci_get_drvdata(pdev);
- vlsi_irda_dev_t *idev = ndev->priv;
+ vlsi_irda_dev_t *idev = netdev_priv(ndev);
unsigned iobase;
u16 ptr;
@@ -1376,14 +1375,14 @@ static int vlsi_stop_hw(vlsi_irda_dev_t *idev)
static struct net_device_stats * vlsi_get_stats(struct net_device *ndev)
{
- vlsi_irda_dev_t *idev = ndev->priv;
+ vlsi_irda_dev_t *idev = netdev_priv(ndev);
return &idev->stats;
}
static void vlsi_tx_timeout(struct net_device *ndev)
{
- vlsi_irda_dev_t *idev = ndev->priv;
+ vlsi_irda_dev_t *idev = netdev_priv(ndev);
vlsi_reg_debug(ndev->base_addr, __func__);
@@ -1408,7 +1407,7 @@ static void vlsi_tx_timeout(struct net_device *ndev)
static int vlsi_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
{
- vlsi_irda_dev_t *idev = ndev->priv;
+ vlsi_irda_dev_t *idev = netdev_priv(ndev);
struct if_irda_req *irq = (struct if_irda_req *) rq;
unsigned long flags;
u16 fifocnt;
@@ -1458,7 +1457,7 @@ static int vlsi_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
static irqreturn_t vlsi_interrupt(int irq, void *dev_instance)
{
struct net_device *ndev = dev_instance;
- vlsi_irda_dev_t *idev = ndev->priv;
+ vlsi_irda_dev_t *idev = netdev_priv(ndev);
unsigned iobase;
u8 irintr;
int boguscount = 5;
@@ -1499,7 +1498,7 @@ static irqreturn_t vlsi_interrupt(int irq, void *dev_instance)
static int vlsi_open(struct net_device *ndev)
{
- vlsi_irda_dev_t *idev = ndev->priv;
+ vlsi_irda_dev_t *idev = netdev_priv(ndev);
int err = -EAGAIN;
char hwname[32];
@@ -1558,7 +1557,7 @@ errout:
static int vlsi_close(struct net_device *ndev)
{
- vlsi_irda_dev_t *idev = ndev->priv;
+ vlsi_irda_dev_t *idev = netdev_priv(ndev);
netif_stop_queue(ndev);
@@ -1581,7 +1580,7 @@ static int vlsi_close(struct net_device *ndev)
static int vlsi_irda_init(struct net_device *ndev)
{
- vlsi_irda_dev_t *idev = ndev->priv;
+ vlsi_irda_dev_t *idev = netdev_priv(ndev);
struct pci_dev *pdev = idev->pdev;
ndev->irq = pdev->irq;
@@ -1656,7 +1655,7 @@ vlsi_irda_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_disable;
}
- idev = ndev->priv;
+ idev = netdev_priv(ndev);
spin_lock_init(&idev->lock);
mutex_init(&idev->mtx);
@@ -1713,7 +1712,7 @@ static void __devexit vlsi_irda_remove(struct pci_dev *pdev)
unregister_netdev(ndev);
- idev = ndev->priv;
+ idev = netdev_priv(ndev);
mutex_lock(&idev->mtx);
if (idev->proc_entry) {
remove_proc_entry(ndev->name, vlsi_proc_root);
@@ -1748,7 +1747,7 @@ static int vlsi_irda_suspend(struct pci_dev *pdev, pm_message_t state)
__func__, pci_name(pdev));
return 0;
}
- idev = ndev->priv;
+ idev = netdev_priv(ndev);
mutex_lock(&idev->mtx);
if (pdev->current_state != 0) { /* already suspended */
if (state.event > pdev->current_state) { /* simply go deeper */
@@ -1787,7 +1786,7 @@ static int vlsi_irda_resume(struct pci_dev *pdev)
__func__, pci_name(pdev));
return 0;
}
- idev = ndev->priv;
+ idev = netdev_priv(ndev);
mutex_lock(&idev->mtx);
if (pdev->current_state == 0) {
mutex_unlock(&idev->mtx);
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index 002a6d769f21..30ec9131c5ce 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -147,8 +147,8 @@ static void __exit w83977af_cleanup(void)
* Open driver instance
*
*/
-int w83977af_open(int i, unsigned int iobase, unsigned int irq,
- unsigned int dma)
+static int w83977af_open(int i, unsigned int iobase, unsigned int irq,
+ unsigned int dma)
{
struct net_device *dev;
struct w83977af_ir *self;
@@ -178,7 +178,7 @@ int w83977af_open(int i, unsigned int iobase, unsigned int irq,
goto err_out;
}
- self = dev->priv;
+ self = netdev_priv(dev);
spin_lock_init(&self->lock);
@@ -310,7 +310,7 @@ static int w83977af_close(struct w83977af_ir *self)
return 0;
}
-int w83977af_probe( int iobase, int irq, int dma)
+static int w83977af_probe(int iobase, int irq, int dma)
{
int version;
int i;
@@ -409,7 +409,7 @@ int w83977af_probe( int iobase, int irq, int dma)
return -1;
}
-void w83977af_change_speed(struct w83977af_ir *self, __u32 speed)
+static void w83977af_change_speed(struct w83977af_ir *self, __u32 speed)
{
int ir_mode = HCR_SIR;
int iobase;
@@ -489,7 +489,7 @@ void w83977af_change_speed(struct w83977af_ir *self, __u32 speed)
* Sets up a DMA transfer to send the current frame.
*
*/
-int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev)
+static int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct w83977af_ir *self;
__s32 speed;
@@ -497,7 +497,7 @@ int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev)
__u8 set;
int mtt;
- self = (struct w83977af_ir *) dev->priv;
+ self = netdev_priv(dev);
iobase = self->io.fir_base;
@@ -731,7 +731,7 @@ static void w83977af_dma_xmit_complete(struct w83977af_ir *self)
* if it starts to receive a frame.
*
*/
-int w83977af_dma_receive(struct w83977af_ir *self)
+static int w83977af_dma_receive(struct w83977af_ir *self)
{
int iobase;
__u8 set;
@@ -803,7 +803,7 @@ int w83977af_dma_receive(struct w83977af_ir *self)
* Finished with receiving a frame
*
*/
-int w83977af_dma_receive_complete(struct w83977af_ir *self)
+static int w83977af_dma_receive_complete(struct w83977af_ir *self)
{
struct sk_buff *skb;
struct st_fifo *st_fifo;
@@ -923,7 +923,6 @@ int w83977af_dma_receive_complete(struct w83977af_ir *self)
skb_reset_mac_header(skb);
skb->protocol = htons(ETH_P_IRDA);
netif_rx(skb);
- self->netdev->last_rx = jiffies;
}
}
/* Restore set register */
@@ -1119,7 +1118,7 @@ static irqreturn_t w83977af_interrupt(int irq, void *dev_id)
__u8 set, icr, isr;
int iobase;
- self = dev->priv;
+ self = netdev_priv(dev);
iobase = self->io.fir_base;
@@ -1192,7 +1191,7 @@ static int w83977af_net_open(struct net_device *dev)
IRDA_DEBUG(0, "%s()\n", __func__ );
IRDA_ASSERT(dev != NULL, return -1;);
- self = (struct w83977af_ir *) dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return 0;);
@@ -1256,7 +1255,7 @@ static int w83977af_net_close(struct net_device *dev)
IRDA_ASSERT(dev != NULL, return -1;);
- self = (struct w83977af_ir *) dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return 0;);
@@ -1303,7 +1302,7 @@ static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
IRDA_ASSERT(dev != NULL, return -1;);
- self = dev->priv;
+ self = netdev_priv(dev);
IRDA_ASSERT(self != NULL, return -1;);
@@ -1339,7 +1338,7 @@ out:
static struct net_device_stats *w83977af_net_get_stats(struct net_device *dev)
{
- struct w83977af_ir *self = (struct w83977af_ir *) dev->priv;
+ struct w83977af_ir *self = netdev_priv(dev);
return &self->stats;
}
diff --git a/drivers/net/isa-skeleton.c b/drivers/net/isa-skeleton.c
index d6ff26af37b3..3126678bdd3c 100644
--- a/drivers/net/isa-skeleton.c
+++ b/drivers/net/isa-skeleton.c
@@ -192,7 +192,6 @@ static int __init netcard_probe1(struct net_device *dev, int ioaddr)
static unsigned version_printed;
int i;
int err = -ENODEV;
- DECLARE_MAC_BUF(mac);
/* Grab the region so that no one else tries to probe our ioports. */
if (!request_region(ioaddr, NETCARD_IO_EXTENT, cardname))
@@ -220,7 +219,7 @@ static int __init netcard_probe1(struct net_device *dev, int ioaddr)
for (i = 0; i < 6; i++)
dev->dev_addr[i] = inb(ioaddr + i);
- printk("%s", print_mac(mac, dev->dev_addr));
+ printk("%pM", dev->dev_addr);
err = -EAGAIN;
#ifdef jumpered_interrupts
@@ -584,7 +583,6 @@ net_rx(struct net_device *dev)
insw(ioaddr, skb->data, (pkt_len + 1) >> 1);
netif_rx(skb);
- dev->last_rx = jiffies;
lp->stats.rx_packets++;
lp->stats.rx_bytes += pkt_len;
}
@@ -711,15 +709,3 @@ cleanup_module(void)
}
#endif /* MODULE */
-
-/*
- * Local variables:
- * compile-command:
- * gcc -D__KERNEL__ -Wall -Wstrict-prototypes -Wwrite-strings
- * -Wredundant-decls -O2 -m486 -c skeleton.c
- * version-control: t
- * kept-new-versions: 5
- * tab-width: 4
- * c-indent-level: 4
- * End:
- */
diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c
index c46864d626b2..c7457f97259d 100644
--- a/drivers/net/iseries_veth.c
+++ b/drivers/net/iseries_veth.c
@@ -952,7 +952,7 @@ static int veth_change_mtu(struct net_device *dev, int new_mtu)
static void veth_set_multicast_list(struct net_device *dev)
{
- struct veth_port *port = (struct veth_port *) dev->priv;
+ struct veth_port *port = netdev_priv(dev);
unsigned long flags;
write_lock_irqsave(&port->mcast_gate, flags);
@@ -1044,7 +1044,7 @@ static struct net_device *veth_probe_one(int vlan,
return NULL;
}
- port = (struct veth_port *) dev->priv;
+ port = netdev_priv(dev);
spin_lock_init(&port->queue_lock);
rwlock_init(&port->mcast_gate);
@@ -1102,7 +1102,7 @@ static int veth_transmit_to_one(struct sk_buff *skb, HvLpIndex rlp,
struct net_device *dev)
{
struct veth_lpar_connection *cnx = veth_cnx[rlp];
- struct veth_port *port = (struct veth_port *) dev->priv;
+ struct veth_port *port = netdev_priv(dev);
HvLpEvent_Rc rc;
struct veth_msg *msg = NULL;
unsigned long flags;
@@ -1191,7 +1191,7 @@ static void veth_transmit_to_many(struct sk_buff *skb,
static int veth_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned char *frame = skb->data;
- struct veth_port *port = (struct veth_port *) dev->priv;
+ struct veth_port *port = netdev_priv(dev);
HvLpIndexMap lpmask;
if (! (frame[0] & 0x01)) {
@@ -1255,7 +1255,7 @@ static void veth_wake_queues(struct veth_lpar_connection *cnx)
if (! dev)
continue;
- port = (struct veth_port *)dev->priv;
+ port = netdev_priv(dev);
if (! (port->lpar_map & (1<<cnx->remote_lp)))
continue;
@@ -1284,7 +1284,7 @@ static void veth_stop_queues(struct veth_lpar_connection *cnx)
if (! dev)
continue;
- port = (struct veth_port *)dev->priv;
+ port = netdev_priv(dev);
/* If this cnx is not on the vlan for this port, continue */
if (! (port->lpar_map & (1 << cnx->remote_lp)))
@@ -1506,7 +1506,7 @@ static void veth_receive(struct veth_lpar_connection *cnx,
continue;
}
- port = (struct veth_port *)dev->priv;
+ port = netdev_priv(dev);
dest = *((u64 *) skb->data) & 0xFFFFFFFFFFFF0000;
if ((vlan > HVMAXARCHITECTEDVIRTUALLANS) || !port) {
diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
index be3c7dc96f63..eee28d395682 100644
--- a/drivers/net/ixgb/ixgb_main.c
+++ b/drivers/net/ixgb/ixgb_main.c
@@ -321,6 +321,24 @@ ixgb_reset(struct ixgb_adapter *adapter)
}
}
+static const struct net_device_ops ixgb_netdev_ops = {
+ .ndo_open = ixgb_open,
+ .ndo_stop = ixgb_close,
+ .ndo_start_xmit = ixgb_xmit_frame,
+ .ndo_get_stats = ixgb_get_stats,
+ .ndo_set_multicast_list = ixgb_set_multi,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = ixgb_set_mac,
+ .ndo_change_mtu = ixgb_change_mtu,
+ .ndo_tx_timeout = ixgb_tx_timeout,
+ .ndo_vlan_rx_register = ixgb_vlan_rx_register,
+ .ndo_vlan_rx_add_vid = ixgb_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = ixgb_vlan_rx_kill_vid,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = ixgb_netpoll,
+#endif
+};
+
/**
* ixgb_probe - Device Initialization Routine
* @pdev: PCI device information struct
@@ -381,8 +399,7 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
adapter->hw.back = adapter;
adapter->msg_enable = netif_msg_init(debug, DEFAULT_DEBUG_LEVEL_SHIFT);
- adapter->hw.hw_addr = ioremap(pci_resource_start(pdev, BAR_0),
- pci_resource_len(pdev, BAR_0));
+ adapter->hw.hw_addr = pci_ioremap_bar(pdev, BAR_0);
if (!adapter->hw.hw_addr) {
err = -EIO;
goto err_ioremap;
@@ -397,23 +414,10 @@ ixgb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
}
}
- netdev->open = &ixgb_open;
- netdev->stop = &ixgb_close;
- netdev->hard_start_xmit = &ixgb_xmit_frame;
- netdev->get_stats = &ixgb_get_stats;
- netdev->set_multicast_list = &ixgb_set_multi;
- netdev->set_mac_address = &ixgb_set_mac;
- netdev->change_mtu = &ixgb_change_mtu;
+ netdev->netdev_ops = &ixgb_netdev_ops;
ixgb_set_ethtool_ops(netdev);
- netdev->tx_timeout = &ixgb_tx_timeout;
netdev->watchdog_timeo = 5 * HZ;
netif_napi_add(netdev, &adapter->napi, ixgb_clean, 64);
- netdev->vlan_rx_register = ixgb_vlan_rx_register;
- netdev->vlan_rx_add_vid = ixgb_vlan_rx_add_vid;
- netdev->vlan_rx_kill_vid = ixgb_vlan_rx_kill_vid;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- netdev->poll_controller = ixgb_netpoll;
-#endif
strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1);
@@ -1106,8 +1110,15 @@ ixgb_watchdog(unsigned long data)
if (adapter->hw.link_up) {
if (!netif_carrier_ok(netdev)) {
- DPRINTK(LINK, INFO,
- "NIC Link is Up 10000 Mbps Full Duplex\n");
+ printk(KERN_INFO "ixgb: %s NIC Link is Up 10 Gbps "
+ "Full Duplex, Flow Control: %s\n",
+ netdev->name,
+ (adapter->hw.fc.type == ixgb_fc_full) ?
+ "RX/TX" :
+ ((adapter->hw.fc.type == ixgb_fc_rx_pause) ?
+ "RX" :
+ ((adapter->hw.fc.type == ixgb_fc_tx_pause) ?
+ "TX" : "None")));
adapter->link_speed = 10000;
adapter->link_duplex = FULL_DUPLEX;
netif_carrier_on(netdev);
@@ -1117,7 +1128,8 @@ ixgb_watchdog(unsigned long data)
if (netif_carrier_ok(netdev)) {
adapter->link_speed = 0;
adapter->link_duplex = 0;
- DPRINTK(LINK, INFO, "NIC Link is Down\n");
+ printk(KERN_INFO "ixgb: %s NIC Link is Down\n",
+ netdev->name);
netif_carrier_off(netdev);
netif_stop_queue(netdev);
@@ -1709,14 +1721,14 @@ ixgb_intr(int irq, void *data)
if (!test_bit(__IXGB_DOWN, &adapter->flags))
mod_timer(&adapter->watchdog_timer, jiffies);
- if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
+ if (netif_rx_schedule_prep(&adapter->napi)) {
/* Disable interrupts and register for poll. The flush
of the posted write is intentionally left out.
*/
IXGB_WRITE_REG(&adapter->hw, IMC, ~0);
- __netif_rx_schedule(netdev, &adapter->napi);
+ __netif_rx_schedule(&adapter->napi);
}
return IRQ_HANDLED;
}
@@ -1730,7 +1742,6 @@ static int
ixgb_clean(struct napi_struct *napi, int budget)
{
struct ixgb_adapter *adapter = container_of(napi, struct ixgb_adapter, napi);
- struct net_device *netdev = adapter->netdev;
int work_done = 0;
ixgb_clean_tx_irq(adapter);
@@ -1738,7 +1749,7 @@ ixgb_clean(struct napi_struct *napi, int budget)
/* If budget not fully consumed, exit the polling mode */
if (work_done < budget) {
- netif_rx_complete(netdev, napi);
+ netif_rx_complete(napi);
if (!test_bit(__IXGB_DOWN, &adapter->flags))
ixgb_irq_enable(adapter);
}
@@ -1981,7 +1992,6 @@ ixgb_clean_rx_irq(struct ixgb_adapter *adapter, int *work_done, int work_to_do)
} else {
netif_receive_skb(skb);
}
- netdev->last_rx = jiffies;
rxdesc_done:
/* clean up descriptor, might be written over by hw */
diff --git a/drivers/net/ixgbe/Makefile b/drivers/net/ixgbe/Makefile
index ccd83d9f579e..6e7ef765bcd8 100644
--- a/drivers/net/ixgbe/Makefile
+++ b/drivers/net/ixgbe/Makefile
@@ -34,3 +34,5 @@ obj-$(CONFIG_IXGBE) += ixgbe.o
ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \
ixgbe_82598.o ixgbe_phy.o
+
+ixgbe-$(CONFIG_IXGBE_DCB) += ixgbe_dcb.o ixgbe_dcb_82598.o ixgbe_dcb_nl.o
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h
index e116d340dcc6..e112008f39c1 100644
--- a/drivers/net/ixgbe/ixgbe.h
+++ b/drivers/net/ixgbe/ixgbe.h
@@ -32,10 +32,11 @@
#include <linux/pci.h>
#include <linux/netdevice.h>
#include <linux/inet_lro.h>
+#include <linux/aer.h>
#include "ixgbe_type.h"
#include "ixgbe_common.h"
-
+#include "ixgbe_dcb.h"
#ifdef CONFIG_IXGBE_DCA
#include <linux/dca.h>
#endif
@@ -84,6 +85,7 @@
#define IXGBE_TX_FLAGS_TSO (u32)(1 << 2)
#define IXGBE_TX_FLAGS_IPV4 (u32)(1 << 3)
#define IXGBE_TX_FLAGS_VLAN_MASK 0xffff0000
+#define IXGBE_TX_FLAGS_VLAN_PRIO_MASK 0x0000e000
#define IXGBE_TX_FLAGS_VLAN_SHIFT 16
#define IXGBE_MAX_LRO_DESCRIPTORS 8
@@ -134,7 +136,7 @@ struct ixgbe_ring {
u16 reg_idx; /* holds the special value that gets the hardware register
* offset associated with this ring, which is different
- * for DCE and RSS modes */
+ * for DCB and RSS modes */
#ifdef CONFIG_IXGBE_DCA
/* cpu for tx queue */
@@ -152,8 +154,10 @@ struct ixgbe_ring {
u16 rx_buf_len;
};
+#define RING_F_DCB 0
#define RING_F_VMDQ 1
#define RING_F_RSS 2
+#define IXGBE_MAX_DCB_INDICES 8
#define IXGBE_MAX_RSS_INDICES 16
#define IXGBE_MAX_VMDQ_INDICES 16
struct ixgbe_ring_feature {
@@ -164,6 +168,10 @@ struct ixgbe_ring_feature {
#define MAX_RX_QUEUES 64
#define MAX_TX_QUEUES 32
+#define MAX_RX_PACKET_BUFFERS ((adapter->flags & IXGBE_FLAG_DCB_ENABLED) \
+ ? 8 : 1)
+#define MAX_TX_PACKET_BUFFERS MAX_RX_PACKET_BUFFERS
+
/* MAX_MSIX_Q_VECTORS of these are allocated,
* but we only use one per queue-specific vector.
*/
@@ -215,6 +223,9 @@ struct ixgbe_adapter {
struct work_struct reset_task;
struct ixgbe_q_vector q_vector[MAX_MSIX_Q_VECTORS];
char name[MAX_MSIX_COUNT][IFNAMSIZ + 5];
+ struct ixgbe_dcb_config dcb_cfg;
+ struct ixgbe_dcb_config temp_dcb_cfg;
+ u8 dcb_set_bitmap;
/* Interrupt Throttle Rate */
u32 itr_setting;
@@ -267,8 +278,10 @@ struct ixgbe_adapter {
#define IXGBE_FLAG_RSS_CAPABLE (u32)(1 << 17)
#define IXGBE_FLAG_VMDQ_CAPABLE (u32)(1 << 18)
#define IXGBE_FLAG_VMDQ_ENABLED (u32)(1 << 19)
+#define IXGBE_FLAG_FAN_FAIL_CAPABLE (u32)(1 << 20)
#define IXGBE_FLAG_NEED_LINK_UPDATE (u32)(1 << 22)
#define IXGBE_FLAG_IN_WATCHDOG_TASK (u32)(1 << 23)
+#define IXGBE_FLAG_DCB_ENABLED (u32)(1 << 24)
/* default to trying for four seconds */
#define IXGBE_TRY_LINK_TIMEOUT (4 * HZ)
@@ -299,12 +312,15 @@ struct ixgbe_adapter {
unsigned long link_check_timeout;
struct work_struct watchdog_task;
+ struct work_struct sfp_task;
+ struct timer_list sfp_timer;
};
enum ixbge_state_t {
__IXGBE_TESTING,
__IXGBE_RESETTING,
- __IXGBE_DOWN
+ __IXGBE_DOWN,
+ __IXGBE_SFP_MODULE_NOT_FOUND
};
enum ixgbe_boards {
@@ -312,6 +328,12 @@ enum ixgbe_boards {
};
extern struct ixgbe_info ixgbe_82598_info;
+#ifdef CONFIG_IXGBE_DCB
+extern 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[];
extern const char ixgbe_driver_version[];
@@ -326,5 +348,9 @@ extern int ixgbe_setup_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *)
extern void ixgbe_free_rx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
extern void ixgbe_free_tx_resources(struct ixgbe_adapter *, struct ixgbe_ring *);
extern void ixgbe_update_stats(struct ixgbe_adapter *adapter);
+extern void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter);
+extern int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter);
+void ixgbe_napi_add_all(struct ixgbe_adapter *adapter);
+void ixgbe_napi_del_all(struct ixgbe_adapter *adapter);
#endif /* _IXGBE_H_ */
diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c
index 7cddcfba809e..ad5699d9ab0d 100644
--- a/drivers/net/ixgbe/ixgbe_82598.c
+++ b/drivers/net/ixgbe/ixgbe_82598.c
@@ -46,6 +46,8 @@ static s32 ixgbe_setup_copper_link_speed_82598(struct ixgbe_hw *hw,
ixgbe_link_speed speed,
bool autoneg,
bool autoneg_wait_to_complete);
+static s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
+ u8 *eeprom_data);
/**
*/
@@ -53,12 +55,40 @@ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw)
{
struct ixgbe_mac_info *mac = &hw->mac;
struct ixgbe_phy_info *phy = &hw->phy;
+ s32 ret_val = 0;
+ u16 list_offset, data_offset;
/* Call PHY identify routine to get the phy type */
ixgbe_identify_phy_generic(hw);
/* PHY Init */
switch (phy->type) {
+ case ixgbe_phy_tn:
+ phy->ops.check_link = &ixgbe_check_phy_link_tnx;
+ phy->ops.get_firmware_version =
+ &ixgbe_get_phy_firmware_version_tnx;
+ break;
+ case ixgbe_phy_nl:
+ phy->ops.reset = &ixgbe_reset_phy_nl;
+
+ /* Call SFP+ identify routine to get the SFP+ module type */
+ ret_val = phy->ops.identify_sfp(hw);
+ if (ret_val != 0)
+ goto out;
+ else if (hw->phy.sfp_type == ixgbe_sfp_type_unknown) {
+ ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED;
+ goto out;
+ }
+
+ /* Check to see if SFP+ module is supported */
+ ret_val = ixgbe_get_sfp_init_sequence_offsets(hw,
+ &list_offset,
+ &data_offset);
+ if (ret_val != 0) {
+ ret_val = IXGBE_ERR_SFP_NOT_SUPPORTED;
+ goto out;
+ }
+ break;
default:
break;
}
@@ -77,7 +107,8 @@ static s32 ixgbe_get_invariants_82598(struct ixgbe_hw *hw)
mac->max_rx_queues = IXGBE_82598_MAX_RX_QUEUES;
mac->max_tx_queues = IXGBE_82598_MAX_TX_QUEUES;
- return 0;
+out:
+ return ret_val;
}
/**
@@ -146,9 +177,9 @@ static s32 ixgbe_get_link_capabilities_82598(struct ixgbe_hw *hw,
*
* Determines the link capabilities by reading the AUTOC register.
**/
-s32 ixgbe_get_copper_link_capabilities_82598(struct ixgbe_hw *hw,
- ixgbe_link_speed *speed,
- bool *autoneg)
+static s32 ixgbe_get_copper_link_capabilities_82598(struct ixgbe_hw *hw,
+ ixgbe_link_speed *speed,
+ bool *autoneg)
{
s32 status = IXGBE_ERR_LINK_SETUP;
u16 speed_ability;
@@ -186,9 +217,15 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
case IXGBE_DEV_ID_82598EB_CX4:
case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
+ case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
+ case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
case IXGBE_DEV_ID_82598EB_XF_LR:
+ case IXGBE_DEV_ID_82598EB_SFP_LOM:
media_type = ixgbe_media_type_fiber;
break;
+ case IXGBE_DEV_ID_82598AT:
+ media_type = ixgbe_media_type_copper;
+ break;
default:
media_type = ixgbe_media_type_unknown;
break;
@@ -205,7 +242,7 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw)
* Configures the flow control settings based on SW configuration. This
* function is used for 802.3x flow control configuration only.
**/
-s32 ixgbe_setup_fc_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
+static s32 ixgbe_setup_fc_82598(struct ixgbe_hw *hw, s32 packetbuf_num)
{
u32 frctl_reg;
u32 rmcs_reg;
@@ -391,6 +428,46 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
{
u32 links_reg;
u32 i;
+ u16 link_reg, adapt_comp_reg;
+
+ /*
+ * SERDES PHY requires us to read link status from register 0xC79F.
+ * Bit 0 set indicates link is up/ready; clear indicates link down.
+ * 0xC00C is read to check that the XAUI lanes are active. Bit 0
+ * clear indicates active; set indicates inactive.
+ */
+ if (hw->phy.type == ixgbe_phy_nl) {
+ hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg);
+ hw->phy.ops.read_reg(hw, 0xC79F, IXGBE_TWINAX_DEV, &link_reg);
+ hw->phy.ops.read_reg(hw, 0xC00C, IXGBE_TWINAX_DEV,
+ &adapt_comp_reg);
+ if (link_up_wait_to_complete) {
+ for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
+ if ((link_reg & 1) &&
+ ((adapt_comp_reg & 1) == 0)) {
+ *link_up = true;
+ break;
+ } else {
+ *link_up = false;
+ }
+ msleep(100);
+ hw->phy.ops.read_reg(hw, 0xC79F,
+ IXGBE_TWINAX_DEV,
+ &link_reg);
+ hw->phy.ops.read_reg(hw, 0xC00C,
+ IXGBE_TWINAX_DEV,
+ &adapt_comp_reg);
+ }
+ } else {
+ if ((link_reg & 1) && ((adapt_comp_reg & 1) == 0))
+ *link_up = true;
+ else
+ *link_up = false;
+ }
+
+ if (*link_up == false)
+ goto out;
+ }
links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
if (link_up_wait_to_complete) {
@@ -416,6 +493,7 @@ static s32 ixgbe_check_mac_link_82598(struct ixgbe_hw *hw,
else
*speed = IXGBE_LINK_SPEED_1GB_FULL;
+out:
return 0;
}
@@ -648,7 +726,7 @@ static s32 ixgbe_reset_hw_82598(struct ixgbe_hw *hw)
* @rar: receive address register index to associate with a VMDq index
* @vmdq: VMDq set index
**/
-s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
+static s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
{
u32 rar_high;
@@ -692,8 +770,8 @@ static s32 ixgbe_clear_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
*
* Turn on/off specified VLAN in the VLAN filter table.
**/
-s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind,
- bool vlan_on)
+static s32 ixgbe_set_vfta_82598(struct ixgbe_hw *hw, u32 vlan, u32 vind,
+ bool vlan_on)
{
u32 regindex;
u32 bitindex;
@@ -816,7 +894,7 @@ static s32 ixgbe_blink_led_stop_82598(struct ixgbe_hw *hw, u32 index)
*
* Performs read operation to Atlas analog register specified.
**/
-s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val)
+static s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val)
{
u32 atlas_ctl;
@@ -838,7 +916,7 @@ s32 ixgbe_read_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 *val)
*
* Performs write operation to Atlas analog register specified.
**/
-s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val)
+static s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val)
{
u32 atlas_ctl;
@@ -851,12 +929,75 @@ s32 ixgbe_write_analog_reg8_82598(struct ixgbe_hw *hw, u32 reg, u8 val)
}
/**
+ * ixgbe_read_i2c_eeprom_82598 - Read 8 bit EEPROM word of an SFP+ module
+ * over I2C interface through an intermediate phy.
+ * @hw: pointer to hardware structure
+ * @byte_offset: EEPROM byte offset to read
+ * @eeprom_data: value read
+ *
+ * Performs byte read operation to SFP module's EEPROM over I2C interface.
+ **/
+static s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
+ u8 *eeprom_data)
+{
+ s32 status = 0;
+ u16 sfp_addr = 0;
+ u16 sfp_data = 0;
+ u16 sfp_stat = 0;
+ u32 i;
+
+ if (hw->phy.type == ixgbe_phy_nl) {
+ /*
+ * phy SDA/SCL registers are at addresses 0xC30A to
+ * 0xC30D. These registers are used to talk to the SFP+
+ * module's EEPROM through the SDA/SCL (I2C) interface.
+ */
+ sfp_addr = (IXGBE_I2C_EEPROM_DEV_ADDR << 8) + byte_offset;
+ sfp_addr = (sfp_addr | IXGBE_I2C_EEPROM_READ_MASK);
+ hw->phy.ops.write_reg(hw,
+ IXGBE_MDIO_PMA_PMD_SDA_SCL_ADDR,
+ IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+ sfp_addr);
+
+ /* Poll status */
+ for (i = 0; i < 100; i++) {
+ hw->phy.ops.read_reg(hw,
+ IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT,
+ IXGBE_MDIO_PMA_PMD_DEV_TYPE,
+ &sfp_stat);
+ sfp_stat = sfp_stat & IXGBE_I2C_EEPROM_STATUS_MASK;
+ if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS)
+ break;
+ msleep(10);
+ }
+
+ if (sfp_stat != IXGBE_I2C_EEPROM_STATUS_PASS) {
+ hw_dbg(hw, "EEPROM read did not pass.\n");
+ status = IXGBE_ERR_SFP_NOT_PRESENT;
+ goto out;
+ }
+
+ /* Read data */
+ hw->phy.ops.read_reg(hw, IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA,
+ IXGBE_MDIO_PMA_PMD_DEV_TYPE, &sfp_data);
+
+ *eeprom_data = (u8)(sfp_data >> 8);
+ } else {
+ status = IXGBE_ERR_PHY;
+ goto out;
+ }
+
+out:
+ return status;
+}
+
+/**
* ixgbe_get_supported_physical_layer_82598 - Returns physical layer type
* @hw: pointer to hardware structure
*
* Determines physical layer capabilities of the current configuration.
**/
-s32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
+static s32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
{
s32 physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
@@ -865,13 +1006,39 @@ s32 ixgbe_get_supported_physical_layer_82598(struct ixgbe_hw *hw)
case IXGBE_DEV_ID_82598_CX4_DUAL_PORT:
physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_CX4;
break;
+ case IXGBE_DEV_ID_82598_DA_DUAL_PORT:
+ physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
+ break;
case IXGBE_DEV_ID_82598AF_DUAL_PORT:
case IXGBE_DEV_ID_82598AF_SINGLE_PORT:
+ case IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM:
physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
break;
case IXGBE_DEV_ID_82598EB_XF_LR:
physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
break;
+ case IXGBE_DEV_ID_82598AT:
+ physical_layer = (IXGBE_PHYSICAL_LAYER_10GBASE_T |
+ IXGBE_PHYSICAL_LAYER_1000BASE_T);
+ break;
+ case IXGBE_DEV_ID_82598EB_SFP_LOM:
+ hw->phy.ops.identify_sfp(hw);
+
+ switch (hw->phy.sfp_type) {
+ case ixgbe_sfp_type_da_cu:
+ physical_layer = IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU;
+ break;
+ case ixgbe_sfp_type_sr:
+ physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_SR;
+ break;
+ case ixgbe_sfp_type_lr:
+ physical_layer = IXGBE_PHYSICAL_LAYER_10GBASE_LR;
+ break;
+ default:
+ physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
+ break;
+ }
+ break;
default:
physical_layer = IXGBE_PHYSICAL_LAYER_UNKNOWN;
@@ -923,12 +1090,13 @@ static struct ixgbe_eeprom_operations eeprom_ops_82598 = {
static struct ixgbe_phy_operations phy_ops_82598 = {
.identify = &ixgbe_identify_phy_generic,
- /* .identify_sfp = &ixgbe_identify_sfp_module_generic, */
+ .identify_sfp = &ixgbe_identify_sfp_module_generic,
.reset = &ixgbe_reset_phy_generic,
.read_reg = &ixgbe_read_phy_reg_generic,
.write_reg = &ixgbe_write_phy_reg_generic,
.setup_link = &ixgbe_setup_phy_link_generic,
.setup_link_speed = &ixgbe_setup_phy_link_speed_generic,
+ .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_82598,
};
struct ixgbe_info ixgbe_82598_info = {
diff --git a/drivers/net/ixgbe/ixgbe_dcb.c b/drivers/net/ixgbe/ixgbe_dcb.c
new file mode 100644
index 000000000000..e2e28ac63dec
--- /dev/null
+++ b/drivers/net/ixgbe/ixgbe_dcb.c
@@ -0,0 +1,332 @@
+/*******************************************************************************
+
+ Intel 10 Gigabit PCI Express Linux driver
+ Copyright(c) 1999 - 2007 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ Linux NICS <linux.nics@intel.com>
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+
+#include "ixgbe.h"
+#include "ixgbe_type.h"
+#include "ixgbe_dcb.h"
+#include "ixgbe_dcb_82598.h"
+
+/**
+ * ixgbe_dcb_config - Struct containing DCB settings.
+ * @dcb_config: Pointer to DCB config structure
+ *
+ * This function checks DCB rules for DCB settings.
+ * The following rules are checked:
+ * 1. The sum of bandwidth percentages of all Bandwidth Groups must total 100%.
+ * 2. The sum of bandwidth percentages of all Traffic Classes within a Bandwidth
+ * Group must total 100.
+ * 3. A Traffic Class should not be set to both Link Strict Priority
+ * and Group Strict Priority.
+ * 4. Link strict Bandwidth Groups can only have link strict traffic classes
+ * with zero bandwidth.
+ */
+s32 ixgbe_dcb_check_config(struct ixgbe_dcb_config *dcb_config)
+{
+ struct tc_bw_alloc *p;
+ s32 ret_val = 0;
+ u8 i, j, bw = 0, bw_id;
+ u8 bw_sum[2][MAX_BW_GROUP];
+ bool link_strict[2][MAX_BW_GROUP];
+
+ memset(bw_sum, 0, sizeof(bw_sum));
+ memset(link_strict, 0, sizeof(link_strict));
+
+ /* First Tx, then Rx */
+ for (i = 0; i < 2; i++) {
+ /* Check each traffic class for rule violation */
+ for (j = 0; j < MAX_TRAFFIC_CLASS; j++) {
+ p = &dcb_config->tc_config[j].path[i];
+
+ bw = p->bwg_percent;
+ bw_id = p->bwg_id;
+
+ if (bw_id >= MAX_BW_GROUP) {
+ ret_val = DCB_ERR_CONFIG;
+ goto err_config;
+ }
+ if (p->prio_type == prio_link) {
+ link_strict[i][bw_id] = true;
+ /* Link strict should have zero bandwidth */
+ if (bw) {
+ ret_val = DCB_ERR_LS_BW_NONZERO;
+ goto err_config;
+ }
+ } else if (!bw) {
+ /*
+ * Traffic classes without link strict
+ * should have non-zero bandwidth.
+ */
+ ret_val = DCB_ERR_TC_BW_ZERO;
+ goto err_config;
+ }
+ bw_sum[i][bw_id] += bw;
+ }
+
+ bw = 0;
+
+ /* Check each bandwidth group for rule violation */
+ for (j = 0; j < MAX_BW_GROUP; j++) {
+ bw += dcb_config->bw_percentage[i][j];
+ /*
+ * Sum of bandwidth percentages of all traffic classes
+ * within a Bandwidth Group must total 100 except for
+ * link strict group (zero bandwidth).
+ */
+ if (link_strict[i][j]) {
+ if (bw_sum[i][j]) {
+ /*
+ * Link strict group should have zero
+ * bandwidth.
+ */
+ ret_val = DCB_ERR_LS_BWG_NONZERO;
+ goto err_config;
+ }
+ } else if (bw_sum[i][j] != BW_PERCENT &&
+ bw_sum[i][j] != 0) {
+ ret_val = DCB_ERR_TC_BW;
+ goto err_config;
+ }
+ }
+
+ if (bw != BW_PERCENT) {
+ ret_val = DCB_ERR_BW_GROUP;
+ goto err_config;
+ }
+ }
+
+err_config:
+ return ret_val;
+}
+
+/**
+ * ixgbe_dcb_calculate_tc_credits - Calculates traffic class credits
+ * @ixgbe_dcb_config: Struct containing DCB settings.
+ * @direction: Configuring either Tx or Rx.
+ *
+ * This function calculates the credits allocated to each traffic class.
+ * It should be called only after the rules are checked by
+ * ixgbe_dcb_check_config().
+ */
+s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *dcb_config,
+ u8 direction)
+{
+ struct tc_bw_alloc *p;
+ s32 ret_val = 0;
+ /* Initialization values default for Tx settings */
+ u32 credit_refill = 0;
+ u32 credit_max = 0;
+ u16 link_percentage = 0;
+ u8 bw_percent = 0;
+ u8 i;
+
+ if (dcb_config == NULL) {
+ ret_val = DCB_ERR_CONFIG;
+ goto out;
+ }
+
+ /* Find out the link percentage for each TC first */
+ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+ p = &dcb_config->tc_config[i].path[direction];
+ bw_percent = dcb_config->bw_percentage[direction][p->bwg_id];
+
+ link_percentage = p->bwg_percent;
+ /* Must be careful of integer division for very small nums */
+ link_percentage = (link_percentage * bw_percent) / 100;
+ if (p->bwg_percent > 0 && link_percentage == 0)
+ link_percentage = 1;
+
+ /* Save link_percentage for reference */
+ p->link_percent = (u8)link_percentage;
+
+ /* Calculate credit refill and save it */
+ credit_refill = link_percentage * MINIMUM_CREDIT_REFILL;
+ p->data_credits_refill = (u16)credit_refill;
+
+ /* Calculate maximum credit for the TC */
+ credit_max = (link_percentage * MAX_CREDIT) / 100;
+
+ /*
+ * Adjustment based on rule checking, if the percentage
+ * of a TC is too small, the maximum credit may not be
+ * enough to send out a jumbo frame in data plane arbitration.
+ */
+ if (credit_max && (credit_max < MINIMUM_CREDIT_FOR_JUMBO))
+ credit_max = MINIMUM_CREDIT_FOR_JUMBO;
+
+ if (direction == DCB_TX_CONFIG) {
+ /*
+ * Adjustment based on rule checking, if the
+ * percentage of a TC is too small, the maximum
+ * credit may not be enough to send out a TSO
+ * packet in descriptor plane arbitration.
+ */
+ if (credit_max &&
+ (credit_max < MINIMUM_CREDIT_FOR_TSO))
+ credit_max = MINIMUM_CREDIT_FOR_TSO;
+
+ dcb_config->tc_config[i].desc_credits_max =
+ (u16)credit_max;
+ }
+
+ p->data_credits_max = (u16)credit_max;
+ }
+
+out:
+ return ret_val;
+}
+
+/**
+ * ixgbe_dcb_get_tc_stats - Returns status of each traffic class
+ * @hw: pointer to hardware structure
+ * @stats: pointer to statistics structure
+ * @tc_count: Number of elements in bwg_array.
+ *
+ * This function returns the status data for each of the Traffic Classes in use.
+ */
+s32 ixgbe_dcb_get_tc_stats(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats,
+ u8 tc_count)
+{
+ s32 ret = 0;
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ ret = ixgbe_dcb_get_tc_stats_82598(hw, stats, tc_count);
+ return ret;
+}
+
+/**
+ * ixgbe_dcb_get_pfc_stats - Returns CBFC status of each traffic class
+ * hw - pointer to hardware structure
+ * stats - pointer to statistics structure
+ * tc_count - Number of elements in bwg_array.
+ *
+ * This function returns the CBFC status data for each of the Traffic Classes.
+ */
+s32 ixgbe_dcb_get_pfc_stats(struct ixgbe_hw *hw, struct ixgbe_hw_stats *stats,
+ u8 tc_count)
+{
+ s32 ret = 0;
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ ret = ixgbe_dcb_get_pfc_stats_82598(hw, stats, tc_count);
+ return ret;
+}
+
+/**
+ * ixgbe_dcb_config_rx_arbiter - Config Rx arbiter
+ * @hw: pointer to hardware structure
+ * @dcb_config: pointer to ixgbe_dcb_config structure
+ *
+ * Configure Rx Data Arbiter and credits for each traffic class.
+ */
+s32 ixgbe_dcb_config_rx_arbiter(struct ixgbe_hw *hw,
+ struct ixgbe_dcb_config *dcb_config)
+{
+ s32 ret = 0;
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ ret = ixgbe_dcb_config_rx_arbiter_82598(hw, dcb_config);
+ return ret;
+}
+
+/**
+ * ixgbe_dcb_config_tx_desc_arbiter - Config Tx Desc arbiter
+ * @hw: pointer to hardware structure
+ * @dcb_config: pointer to ixgbe_dcb_config structure
+ *
+ * Configure Tx Descriptor Arbiter and credits for each traffic class.
+ */
+s32 ixgbe_dcb_config_tx_desc_arbiter(struct ixgbe_hw *hw,
+ struct ixgbe_dcb_config *dcb_config)
+{
+ s32 ret = 0;
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ ret = ixgbe_dcb_config_tx_desc_arbiter_82598(hw, dcb_config);
+ return ret;
+}
+
+/**
+ * ixgbe_dcb_config_tx_data_arbiter - Config Tx data arbiter
+ * @hw: pointer to hardware structure
+ * @dcb_config: pointer to ixgbe_dcb_config structure
+ *
+ * Configure Tx Data Arbiter and credits for each traffic class.
+ */
+s32 ixgbe_dcb_config_tx_data_arbiter(struct ixgbe_hw *hw,
+ struct ixgbe_dcb_config *dcb_config)
+{
+ s32 ret = 0;
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ ret = ixgbe_dcb_config_tx_data_arbiter_82598(hw, dcb_config);
+ return ret;
+}
+
+/**
+ * ixgbe_dcb_config_pfc - Config priority flow control
+ * @hw: pointer to hardware structure
+ * @dcb_config: pointer to ixgbe_dcb_config structure
+ *
+ * Configure Priority Flow Control for each traffic class.
+ */
+s32 ixgbe_dcb_config_pfc(struct ixgbe_hw *hw,
+ struct ixgbe_dcb_config *dcb_config)
+{
+ s32 ret = 0;
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ ret = ixgbe_dcb_config_pfc_82598(hw, dcb_config);
+ return ret;
+}
+
+/**
+ * ixgbe_dcb_config_tc_stats - Config traffic class statistics
+ * @hw: pointer to hardware structure
+ *
+ * Configure queue statistics registers, all queues belonging to same traffic
+ * class uses a single set of queue statistics counters.
+ */
+s32 ixgbe_dcb_config_tc_stats(struct ixgbe_hw *hw)
+{
+ s32 ret = 0;
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ ret = ixgbe_dcb_config_tc_stats_82598(hw);
+ return ret;
+}
+
+/**
+ * ixgbe_dcb_hw_config - Config and enable DCB
+ * @hw: pointer to hardware structure
+ * @dcb_config: pointer to ixgbe_dcb_config structure
+ *
+ * Configure dcb settings and enable dcb mode.
+ */
+s32 ixgbe_dcb_hw_config(struct ixgbe_hw *hw,
+ struct ixgbe_dcb_config *dcb_config)
+{
+ s32 ret = 0;
+ if (hw->mac.type == ixgbe_mac_82598EB)
+ ret = ixgbe_dcb_hw_config_82598(hw, dcb_config);
+ return ret;
+}
+
diff --git a/drivers/net/ixgbe/ixgbe_dcb.h b/drivers/net/ixgbe/ixgbe_dcb.h
new file mode 100644
index 000000000000..75f6efe1e369
--- /dev/null
+++ b/drivers/net/ixgbe/ixgbe_dcb.h
@@ -0,0 +1,184 @@
+/*******************************************************************************
+
+ Intel 10 Gigabit PCI Express Linux driver
+ Copyright(c) 1999 - 2007 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ Linux NICS <linux.nics@intel.com>
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#ifndef _DCB_CONFIG_H_
+#define _DCB_CONFIG_H_
+
+#include "ixgbe_type.h"
+
+/* DCB data structures */
+
+#define IXGBE_MAX_PACKET_BUFFERS 8
+#define MAX_USER_PRIORITY 8
+#define MAX_TRAFFIC_CLASS 8
+#define MAX_BW_GROUP 8
+#define BW_PERCENT 100
+
+#define DCB_TX_CONFIG 0
+#define DCB_RX_CONFIG 1
+
+/* DCB error Codes */
+#define DCB_SUCCESS 0
+#define DCB_ERR_CONFIG -1
+#define DCB_ERR_PARAM -2
+
+/* Transmit and receive Errors */
+/* Error in bandwidth group allocation */
+#define DCB_ERR_BW_GROUP -3
+/* Error in traffic class bandwidth allocation */
+#define DCB_ERR_TC_BW -4
+/* Traffic class has both link strict and group strict enabled */
+#define DCB_ERR_LS_GS -5
+/* Link strict traffic class has non zero bandwidth */
+#define DCB_ERR_LS_BW_NONZERO -6
+/* Link strict bandwidth group has non zero bandwidth */
+#define DCB_ERR_LS_BWG_NONZERO -7
+/* Traffic class has zero bandwidth */
+#define DCB_ERR_TC_BW_ZERO -8
+
+#define DCB_NOT_IMPLEMENTED 0x7FFFFFFF
+
+struct dcb_pfc_tc_debug {
+ u8 tc;
+ u8 pause_status;
+ u64 pause_quanta;
+};
+
+enum strict_prio_type {
+ prio_none = 0,
+ prio_group,
+ prio_link
+};
+
+/* Traffic class bandwidth allocation per direction */
+struct tc_bw_alloc {
+ u8 bwg_id; /* Bandwidth Group (BWG) ID */
+ u8 bwg_percent; /* % of BWG's bandwidth */
+ u8 link_percent; /* % of link bandwidth */
+ u8 up_to_tc_bitmap; /* User Priority to Traffic Class mapping */
+ u16 data_credits_refill; /* Credit refill amount in 64B granularity */
+ u16 data_credits_max; /* Max credits for a configured packet buffer
+ * in 64B granularity.*/
+ enum strict_prio_type prio_type; /* Link or Group Strict Priority */
+};
+
+enum dcb_pfc_type {
+ pfc_disabled = 0,
+ pfc_enabled_full,
+ pfc_enabled_tx,
+ pfc_enabled_rx
+};
+
+/* Traffic class configuration */
+struct tc_configuration {
+ struct tc_bw_alloc path[2]; /* One each for Tx/Rx */
+ enum dcb_pfc_type dcb_pfc; /* Class based flow control setting */
+
+ u16 desc_credits_max; /* For Tx Descriptor arbitration */
+ u8 tc; /* Traffic class (TC) */
+};
+
+enum dcb_rx_pba_cfg {
+ pba_equal, /* PBA[0-7] each use 64KB FIFO */
+ pba_80_48 /* PBA[0-3] each use 80KB, PBA[4-7] each use 48KB */
+};
+
+/*
+ * This structure contains many values encoded as fixed-point
+ * numbers, meaning that some of bits are dedicated to the
+ * magnitude and others to the fraction part. In the comments
+ * this is shown as f=n, where n is the number of fraction bits.
+ * These fraction bits are always the low-order bits. The size
+ * of the magnitude is not specified.
+ */
+struct bcn_config {
+ u32 rp_admin_mode[MAX_TRAFFIC_CLASS]; /* BCN enabled, per TC */
+ u32 bcna_option[2]; /* BCNA Port + MAC Addr */
+ u32 rp_w; /* Derivative Weight, f=3 */
+ u32 rp_gi; /* Increase Gain, f=12 */
+ u32 rp_gd; /* Decrease Gain, f=12 */
+ u32 rp_ru; /* Rate Unit */
+ u32 rp_alpha; /* Max Decrease Factor, f=12 */
+ u32 rp_beta; /* Max Increase Factor, f=12 */
+ u32 rp_ri; /* Initial Rate */
+ u32 rp_td; /* Drift Interval Timer */
+ u32 rp_rd; /* Drift Increase */
+ u32 rp_tmax; /* Severe Congestion Backoff Timer Range */
+ u32 rp_rmin; /* Severe Congestion Restart Rate */
+ u32 rp_wrtt; /* RTT Moving Average Weight */
+};
+
+struct ixgbe_dcb_config {
+ struct bcn_config bcn;
+
+ struct tc_configuration tc_config[MAX_TRAFFIC_CLASS];
+ u8 bw_percentage[2][MAX_BW_GROUP]; /* One each for Tx/Rx */
+
+ bool round_robin_enable;
+
+ enum dcb_rx_pba_cfg rx_pba_cfg;
+
+ u32 dcb_cfg_version; /* Not used...OS-specific? */
+ u32 link_speed; /* For bandwidth allocation validation purpose */
+};
+
+/* DCB driver APIs */
+
+/* DCB rule checking function.*/
+s32 ixgbe_dcb_check_config(struct ixgbe_dcb_config *config);
+
+/* DCB credits calculation */
+s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_dcb_config *, u8);
+
+/* DCB PFC functions */
+s32 ixgbe_dcb_config_pfc(struct ixgbe_hw *, struct ixgbe_dcb_config *g);
+s32 ixgbe_dcb_get_pfc_stats(struct ixgbe_hw *, struct ixgbe_hw_stats *, u8);
+
+/* DCB traffic class stats */
+s32 ixgbe_dcb_config_tc_stats(struct ixgbe_hw *);
+s32 ixgbe_dcb_get_tc_stats(struct ixgbe_hw *, struct ixgbe_hw_stats *, u8);
+
+/* DCB config arbiters */
+s32 ixgbe_dcb_config_tx_desc_arbiter(struct ixgbe_hw *,
+ struct ixgbe_dcb_config *);
+s32 ixgbe_dcb_config_tx_data_arbiter(struct ixgbe_hw *,
+ struct ixgbe_dcb_config *);
+s32 ixgbe_dcb_config_rx_arbiter(struct ixgbe_hw *, struct ixgbe_dcb_config *);
+
+/* DCB hw initialization */
+s32 ixgbe_dcb_hw_config(struct ixgbe_hw *, struct ixgbe_dcb_config *);
+
+/* DCB definitions for credit calculation */
+#define MAX_CREDIT_REFILL 511 /* 0x1FF * 64B = 32704B */
+#define MINIMUM_CREDIT_REFILL 5 /* 5*64B = 320B */
+#define MINIMUM_CREDIT_FOR_JUMBO 145 /* 145= UpperBound((9*1024+54)/64B) for 9KB jumbo frame */
+#define DCB_MAX_TSO_SIZE (32*1024) /* MAX TSO packet size supported in DCB mode */
+#define MINIMUM_CREDIT_FOR_TSO (DCB_MAX_TSO_SIZE/64 + 1) /* 513 for 32KB TSO packet */
+#define MAX_CREDIT 4095 /* Maximum credit supported: 256KB * 1204 / 64B */
+
+#endif /* _DCB_CONFIG_H */
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ixgbe/ixgbe_dcb_82598.c
new file mode 100644
index 000000000000..2c046b0b5d28
--- /dev/null
+++ b/drivers/net/ixgbe/ixgbe_dcb_82598.c
@@ -0,0 +1,398 @@
+/*******************************************************************************
+
+ Intel 10 Gigabit PCI Express Linux driver
+ Copyright(c) 1999 - 2007 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ Linux NICS <linux.nics@intel.com>
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#include "ixgbe.h"
+#include "ixgbe_type.h"
+#include "ixgbe_dcb.h"
+#include "ixgbe_dcb_82598.h"
+
+/**
+ * ixgbe_dcb_get_tc_stats_82598 - Return status data for each traffic class
+ * @hw: pointer to hardware structure
+ * @stats: pointer to statistics structure
+ * @tc_count: Number of elements in bwg_array.
+ *
+ * This function returns the status data for each of the Traffic Classes in use.
+ */
+s32 ixgbe_dcb_get_tc_stats_82598(struct ixgbe_hw *hw,
+ struct ixgbe_hw_stats *stats,
+ u8 tc_count)
+{
+ int tc;
+
+ if (tc_count > MAX_TRAFFIC_CLASS)
+ return DCB_ERR_PARAM;
+
+ /* Statistics pertaining to each traffic class */
+ for (tc = 0; tc < tc_count; tc++) {
+ /* Transmitted Packets */
+ stats->qptc[tc] += IXGBE_READ_REG(hw, IXGBE_QPTC(tc));
+ /* Transmitted Bytes */
+ stats->qbtc[tc] += IXGBE_READ_REG(hw, IXGBE_QBTC(tc));
+ /* Received Packets */
+ stats->qprc[tc] += IXGBE_READ_REG(hw, IXGBE_QPRC(tc));
+ /* Received Bytes */
+ stats->qbrc[tc] += IXGBE_READ_REG(hw, IXGBE_QBRC(tc));
+ }
+
+ return 0;
+}
+
+/**
+ * ixgbe_dcb_get_pfc_stats_82598 - Returns CBFC status data
+ * @hw: pointer to hardware structure
+ * @stats: pointer to statistics structure
+ * @tc_count: Number of elements in bwg_array.
+ *
+ * This function returns the CBFC status data for each of the Traffic Classes.
+ */
+s32 ixgbe_dcb_get_pfc_stats_82598(struct ixgbe_hw *hw,
+ struct ixgbe_hw_stats *stats,
+ u8 tc_count)
+{
+ int tc;
+
+ if (tc_count > MAX_TRAFFIC_CLASS)
+ return DCB_ERR_PARAM;
+
+ for (tc = 0; tc < tc_count; tc++) {
+ /* Priority XOFF Transmitted */
+ stats->pxofftxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(tc));
+ /* Priority XOFF Received */
+ stats->pxoffrxc[tc] += IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(tc));
+ }
+
+ return 0;
+}
+
+/**
+ * ixgbe_dcb_config_packet_buffers_82598 - Configure packet buffers
+ * @hw: pointer to hardware structure
+ * @dcb_config: pointer to ixgbe_dcb_config structure
+ *
+ * Configure packet buffers for DCB mode.
+ */
+static s32 ixgbe_dcb_config_packet_buffers_82598(struct ixgbe_hw *hw,
+ struct ixgbe_dcb_config *dcb_config)
+{
+ s32 ret_val = 0;
+ u32 value = IXGBE_RXPBSIZE_64KB;
+ u8 i = 0;
+
+ /* Setup Rx packet buffer sizes */
+ switch (dcb_config->rx_pba_cfg) {
+ case pba_80_48:
+ /* Setup the first four at 80KB */
+ value = IXGBE_RXPBSIZE_80KB;
+ for (; i < 4; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), value);
+ /* Setup the last four at 48KB...don't re-init i */
+ value = IXGBE_RXPBSIZE_48KB;
+ /* Fall Through */
+ case pba_equal:
+ default:
+ for (; i < IXGBE_MAX_PACKET_BUFFERS; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(i), value);
+
+ /* Setup Tx packet buffer sizes */
+ for (i = 0; i < IXGBE_MAX_PACKET_BUFFERS; i++) {
+ IXGBE_WRITE_REG(hw, IXGBE_TXPBSIZE(i),
+ IXGBE_TXPBSIZE_40KB);
+ }
+ break;
+ }
+
+ return ret_val;
+}
+
+/**
+ * ixgbe_dcb_config_rx_arbiter_82598 - Config Rx data arbiter
+ * @hw: pointer to hardware structure
+ * @dcb_config: pointer to ixgbe_dcb_config structure
+ *
+ * Configure Rx Data Arbiter and credits for each traffic class.
+ */
+s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw,
+ struct ixgbe_dcb_config *dcb_config)
+{
+ struct tc_bw_alloc *p;
+ u32 reg = 0;
+ u32 credit_refill = 0;
+ u32 credit_max = 0;
+ u8 i = 0;
+
+ reg = IXGBE_READ_REG(hw, IXGBE_RUPPBMR) | IXGBE_RUPPBMR_MQA;
+ IXGBE_WRITE_REG(hw, IXGBE_RUPPBMR, reg);
+
+ reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
+ /* Enable Arbiter */
+ reg &= ~IXGBE_RMCS_ARBDIS;
+ /* Enable Receive Recycle within the BWG */
+ reg |= IXGBE_RMCS_RRM;
+ /* Enable Deficit Fixed Priority arbitration*/
+ reg |= IXGBE_RMCS_DFP;
+
+ IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg);
+
+ /* Configure traffic class credits and priority */
+ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+ p = &dcb_config->tc_config[i].path[DCB_RX_CONFIG];
+ credit_refill = p->data_credits_refill;
+ credit_max = p->data_credits_max;
+
+ reg = credit_refill | (credit_max << IXGBE_RT2CR_MCL_SHIFT);
+
+ if (p->prio_type == prio_link)
+ reg |= IXGBE_RT2CR_LSP;
+
+ IXGBE_WRITE_REG(hw, IXGBE_RT2CR(i), reg);
+ }
+
+ reg = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
+ reg |= IXGBE_RDRXCTL_RDMTS_1_2;
+ reg |= IXGBE_RDRXCTL_MPBEN;
+ reg |= IXGBE_RDRXCTL_MCEN;
+ IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, reg);
+
+ reg = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
+ /* Make sure there is enough descriptors before arbitration */
+ reg &= ~IXGBE_RXCTRL_DMBYPS;
+ IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, reg);
+
+ return 0;
+}
+
+/**
+ * ixgbe_dcb_config_tx_desc_arbiter_82598 - Config Tx Desc. arbiter
+ * @hw: pointer to hardware structure
+ * @dcb_config: pointer to ixgbe_dcb_config structure
+ *
+ * Configure Tx Descriptor Arbiter and credits for each traffic class.
+ */
+s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw,
+ struct ixgbe_dcb_config *dcb_config)
+{
+ struct tc_bw_alloc *p;
+ u32 reg, max_credits;
+ u8 i;
+
+ reg = IXGBE_READ_REG(hw, IXGBE_DPMCS);
+
+ /* Enable arbiter */
+ reg &= ~IXGBE_DPMCS_ARBDIS;
+ if (!(dcb_config->round_robin_enable)) {
+ /* Enable DFP and Recycle mode */
+ reg |= (IXGBE_DPMCS_TDPAC | IXGBE_DPMCS_TRM);
+ }
+ reg |= IXGBE_DPMCS_TSOEF;
+ /* Configure Max TSO packet size 34KB including payload and headers */
+ reg |= (0x4 << IXGBE_DPMCS_MTSOS_SHIFT);
+
+ IXGBE_WRITE_REG(hw, IXGBE_DPMCS, reg);
+
+ /* Configure traffic class credits and priority */
+ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+ p = &dcb_config->tc_config[i].path[DCB_TX_CONFIG];
+ max_credits = dcb_config->tc_config[i].desc_credits_max;
+ reg = max_credits << IXGBE_TDTQ2TCCR_MCL_SHIFT;
+ reg |= p->data_credits_refill;
+ reg |= (u32)(p->bwg_id) << IXGBE_TDTQ2TCCR_BWG_SHIFT;
+
+ if (p->prio_type == prio_group)
+ reg |= IXGBE_TDTQ2TCCR_GSP;
+
+ if (p->prio_type == prio_link)
+ reg |= IXGBE_TDTQ2TCCR_LSP;
+
+ IXGBE_WRITE_REG(hw, IXGBE_TDTQ2TCCR(i), reg);
+ }
+
+ return 0;
+}
+
+/**
+ * ixgbe_dcb_config_tx_data_arbiter_82598 - Config Tx data arbiter
+ * @hw: pointer to hardware structure
+ * @dcb_config: pointer to ixgbe_dcb_config structure
+ *
+ * Configure Tx Data Arbiter and credits for each traffic class.
+ */
+s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
+ struct ixgbe_dcb_config *dcb_config)
+{
+ struct tc_bw_alloc *p;
+ u32 reg;
+ u8 i;
+
+ reg = IXGBE_READ_REG(hw, IXGBE_PDPMCS);
+ /* Enable Data Plane Arbiter */
+ reg &= ~IXGBE_PDPMCS_ARBDIS;
+ /* Enable DFP and Transmit Recycle Mode */
+ reg |= (IXGBE_PDPMCS_TPPAC | IXGBE_PDPMCS_TRM);
+
+ IXGBE_WRITE_REG(hw, IXGBE_PDPMCS, reg);
+
+ /* Configure traffic class credits and priority */
+ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+ p = &dcb_config->tc_config[i].path[DCB_TX_CONFIG];
+ reg = p->data_credits_refill;
+ reg |= (u32)(p->data_credits_max) << IXGBE_TDPT2TCCR_MCL_SHIFT;
+ reg |= (u32)(p->bwg_id) << IXGBE_TDPT2TCCR_BWG_SHIFT;
+
+ if (p->prio_type == prio_group)
+ reg |= IXGBE_TDPT2TCCR_GSP;
+
+ if (p->prio_type == prio_link)
+ reg |= IXGBE_TDPT2TCCR_LSP;
+
+ IXGBE_WRITE_REG(hw, IXGBE_TDPT2TCCR(i), reg);
+ }
+
+ /* Enable Tx packet buffer division */
+ reg = IXGBE_READ_REG(hw, IXGBE_DTXCTL);
+ reg |= IXGBE_DTXCTL_ENDBUBD;
+ IXGBE_WRITE_REG(hw, IXGBE_DTXCTL, reg);
+
+ return 0;
+}
+
+/**
+ * ixgbe_dcb_config_pfc_82598 - Config priority flow control
+ * @hw: pointer to hardware structure
+ * @dcb_config: pointer to ixgbe_dcb_config structure
+ *
+ * Configure Priority Flow Control for each traffic class.
+ */
+s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw,
+ struct ixgbe_dcb_config *dcb_config)
+{
+ u32 reg, rx_pba_size;
+ u8 i;
+
+ /* 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 */
+ hw->fc.type = ixgbe_fc_none;
+ 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 flow control thresholds and enable priority flow control
+ * for each traffic class.
+ */
+ for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+ if (dcb_config->rx_pba_cfg == pba_equal) {
+ rx_pba_size = IXGBE_RXPBSIZE_64KB;
+ } else {
+ rx_pba_size = (i < 4) ? IXGBE_RXPBSIZE_80KB
+ : IXGBE_RXPBSIZE_48KB;
+ }
+
+ reg = ((rx_pba_size >> 5) & 0xFFF0);
+ if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx ||
+ dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full)
+ reg |= IXGBE_FCRTL_XONE;
+
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), reg);
+
+ reg = ((rx_pba_size >> 2) & 0xFFF0);
+ if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx ||
+ dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full)
+ reg |= IXGBE_FCRTH_FCEN;
+
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), reg);
+ }
+
+ /* Configure pause time */
+ for (i = 0; i < (MAX_TRAFFIC_CLASS >> 1); i++)
+ IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), 0x68006800);
+
+ /* Configure flow control refresh threshold value */
+ IXGBE_WRITE_REG(hw, IXGBE_FCRTV, 0x3400);
+
+ return 0;
+}
+
+/**
+ * ixgbe_dcb_config_tc_stats_82598 - Configure traffic class statistics
+ * @hw: pointer to hardware structure
+ *
+ * Configure queue statistics registers, all queues belonging to same traffic
+ * class uses a single set of queue statistics counters.
+ */
+s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw)
+{
+ u32 reg = 0;
+ u8 i = 0;
+ u8 j = 0;
+
+ /* Receive Queues stats setting - 8 queues per statistics reg */
+ for (i = 0, j = 0; i < 15 && j < 8; i = i + 2, j++) {
+ reg = IXGBE_READ_REG(hw, IXGBE_RQSMR(i));
+ reg |= ((0x1010101) * j);
+ IXGBE_WRITE_REG(hw, IXGBE_RQSMR(i), reg);
+ reg = IXGBE_READ_REG(hw, IXGBE_RQSMR(i + 1));
+ reg |= ((0x1010101) * j);
+ IXGBE_WRITE_REG(hw, IXGBE_RQSMR(i + 1), reg);
+ }
+ /* Transmit Queues stats setting - 4 queues per statistics reg */
+ for (i = 0; i < 8; i++) {
+ reg = IXGBE_READ_REG(hw, IXGBE_TQSMR(i));
+ reg |= ((0x1010101) * i);
+ IXGBE_WRITE_REG(hw, IXGBE_TQSMR(i), reg);
+ }
+
+ return 0;
+}
+
+/**
+ * ixgbe_dcb_hw_config_82598 - Config and enable DCB
+ * @hw: pointer to hardware structure
+ * @dcb_config: pointer to ixgbe_dcb_config structure
+ *
+ * Configure dcb settings and enable dcb mode.
+ */
+s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw,
+ struct ixgbe_dcb_config *dcb_config)
+{
+ ixgbe_dcb_config_packet_buffers_82598(hw, dcb_config);
+ ixgbe_dcb_config_rx_arbiter_82598(hw, dcb_config);
+ ixgbe_dcb_config_tx_desc_arbiter_82598(hw, dcb_config);
+ ixgbe_dcb_config_tx_data_arbiter_82598(hw, dcb_config);
+ ixgbe_dcb_config_pfc_82598(hw, dcb_config);
+ ixgbe_dcb_config_tc_stats_82598(hw);
+
+ return 0;
+}
diff --git a/drivers/net/ixgbe/ixgbe_dcb_82598.h b/drivers/net/ixgbe/ixgbe_dcb_82598.h
new file mode 100644
index 000000000000..1e6a313719d7
--- /dev/null
+++ b/drivers/net/ixgbe/ixgbe_dcb_82598.h
@@ -0,0 +1,94 @@
+/*******************************************************************************
+
+ Intel 10 Gigabit PCI Express Linux driver
+ Copyright(c) 1999 - 2007 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ Linux NICS <linux.nics@intel.com>
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#ifndef _DCB_82598_CONFIG_H_
+#define _DCB_82598_CONFIG_H_
+
+/* DCB register definitions */
+
+#define IXGBE_DPMCS_MTSOS_SHIFT 16
+#define IXGBE_DPMCS_TDPAC 0x00000001 /* 0 Round Robin, 1 DFP - Deficit Fixed Priority */
+#define IXGBE_DPMCS_TRM 0x00000010 /* Transmit Recycle Mode */
+#define IXGBE_DPMCS_ARBDIS 0x00000040 /* DCB arbiter disable */
+#define IXGBE_DPMCS_TSOEF 0x00080000 /* TSO Expand Factor: 0=x4, 1=x2 */
+
+#define IXGBE_RUPPBMR_MQA 0x80000000 /* Enable UP to queue mapping */
+
+#define IXGBE_RT2CR_MCL_SHIFT 12 /* Offset to Max Credit Limit setting */
+#define IXGBE_RT2CR_LSP 0x80000000 /* LSP enable bit */
+
+#define IXGBE_RDRXCTL_MPBEN 0x00000010 /* DMA config for multiple packet buffers enable */
+#define IXGBE_RDRXCTL_MCEN 0x00000040 /* DMA config for multiple cores (RSS) enable */
+
+#define IXGBE_TDTQ2TCCR_MCL_SHIFT 12
+#define IXGBE_TDTQ2TCCR_BWG_SHIFT 9
+#define IXGBE_TDTQ2TCCR_GSP 0x40000000
+#define IXGBE_TDTQ2TCCR_LSP 0x80000000
+
+#define IXGBE_TDPT2TCCR_MCL_SHIFT 12
+#define IXGBE_TDPT2TCCR_BWG_SHIFT 9
+#define IXGBE_TDPT2TCCR_GSP 0x40000000
+#define IXGBE_TDPT2TCCR_LSP 0x80000000
+
+#define IXGBE_PDPMCS_TPPAC 0x00000020 /* 0 Round Robin, 1 for DFP - Deficit Fixed Priority */
+#define IXGBE_PDPMCS_ARBDIS 0x00000040 /* Arbiter disable */
+#define IXGBE_PDPMCS_TRM 0x00000100 /* Transmit Recycle Mode enable */
+
+#define IXGBE_DTXCTL_ENDBUBD 0x00000004 /* Enable DBU buffer division */
+
+#define IXGBE_TXPBSIZE_40KB 0x0000A000 /* 40KB Packet Buffer */
+#define IXGBE_RXPBSIZE_48KB 0x0000C000 /* 48KB Packet Buffer */
+#define IXGBE_RXPBSIZE_64KB 0x00010000 /* 64KB Packet Buffer */
+#define IXGBE_RXPBSIZE_80KB 0x00014000 /* 80KB Packet Buffer */
+
+#define IXGBE_RDRXCTL_RDMTS_1_2 0x00000000
+
+/* DCB hardware-specific driver APIs */
+
+/* DCB PFC functions */
+s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *, struct ixgbe_dcb_config *);
+s32 ixgbe_dcb_get_pfc_stats_82598(struct ixgbe_hw *, struct ixgbe_hw_stats *,
+ u8);
+
+/* DCB traffic class stats */
+s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *);
+s32 ixgbe_dcb_get_tc_stats_82598(struct ixgbe_hw *, struct ixgbe_hw_stats *,
+ u8);
+
+/* DCB config arbiters */
+s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *,
+ struct ixgbe_dcb_config *);
+s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *,
+ struct ixgbe_dcb_config *);
+s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *,
+ struct ixgbe_dcb_config *);
+
+/* DCB hw initialization */
+s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *, struct ixgbe_dcb_config *);
+
+#endif /* _DCB_82598_CONFIG_H */
diff --git a/drivers/net/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ixgbe/ixgbe_dcb_nl.c
new file mode 100644
index 000000000000..4129976953f5
--- /dev/null
+++ b/drivers/net/ixgbe/ixgbe_dcb_nl.c
@@ -0,0 +1,641 @@
+/*******************************************************************************
+
+ Intel 10 Gigabit PCI Express Linux driver
+ Copyright(c) 1999 - 2008 Intel Corporation.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms and conditions of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ more details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+
+ The full GNU General Public License is included in this distribution in
+ the file called "COPYING".
+
+ Contact Information:
+ Linux NICS <linux.nics@intel.com>
+ e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#include "ixgbe.h"
+#include <linux/dcbnl.h>
+
+/* Callbacks for DCB netlink in the kernel */
+#define BIT_DCB_MODE 0x01
+#define BIT_PFC 0x02
+#define BIT_PG_RX 0x04
+#define BIT_PG_TX 0x08
+#define BIT_BCN 0x10
+
+int ixgbe_copy_dcb_cfg(struct ixgbe_dcb_config *src_dcb_cfg,
+ struct ixgbe_dcb_config *dst_dcb_cfg, int tc_max)
+{
+ struct tc_configuration *src_tc_cfg = NULL;
+ struct tc_configuration *dst_tc_cfg = NULL;
+ int i;
+
+ if (!src_dcb_cfg || !dst_dcb_cfg)
+ return -EINVAL;
+
+ for (i = DCB_PG_ATTR_TC_0; i < tc_max + DCB_PG_ATTR_TC_0; i++) {
+ src_tc_cfg = &src_dcb_cfg->tc_config[i - DCB_PG_ATTR_TC_0];
+ dst_tc_cfg = &dst_dcb_cfg->tc_config[i - DCB_PG_ATTR_TC_0];
+
+ dst_tc_cfg->path[DCB_TX_CONFIG].prio_type =
+ src_tc_cfg->path[DCB_TX_CONFIG].prio_type;
+
+ dst_tc_cfg->path[DCB_TX_CONFIG].bwg_id =
+ src_tc_cfg->path[DCB_TX_CONFIG].bwg_id;
+
+ dst_tc_cfg->path[DCB_TX_CONFIG].bwg_percent =
+ src_tc_cfg->path[DCB_TX_CONFIG].bwg_percent;
+
+ dst_tc_cfg->path[DCB_TX_CONFIG].up_to_tc_bitmap =
+ src_tc_cfg->path[DCB_TX_CONFIG].up_to_tc_bitmap;
+
+ dst_tc_cfg->path[DCB_RX_CONFIG].prio_type =
+ src_tc_cfg->path[DCB_RX_CONFIG].prio_type;
+
+ dst_tc_cfg->path[DCB_RX_CONFIG].bwg_id =
+ src_tc_cfg->path[DCB_RX_CONFIG].bwg_id;
+
+ dst_tc_cfg->path[DCB_RX_CONFIG].bwg_percent =
+ src_tc_cfg->path[DCB_RX_CONFIG].bwg_percent;
+
+ dst_tc_cfg->path[DCB_RX_CONFIG].up_to_tc_bitmap =
+ src_tc_cfg->path[DCB_RX_CONFIG].up_to_tc_bitmap;
+ }
+
+ for (i = DCB_PG_ATTR_BW_ID_0; i < DCB_PG_ATTR_BW_ID_MAX; i++) {
+ dst_dcb_cfg->bw_percentage[DCB_TX_CONFIG]
+ [i-DCB_PG_ATTR_BW_ID_0] = src_dcb_cfg->bw_percentage
+ [DCB_TX_CONFIG][i-DCB_PG_ATTR_BW_ID_0];
+ dst_dcb_cfg->bw_percentage[DCB_RX_CONFIG]
+ [i-DCB_PG_ATTR_BW_ID_0] = src_dcb_cfg->bw_percentage
+ [DCB_RX_CONFIG][i-DCB_PG_ATTR_BW_ID_0];
+ }
+
+ for (i = DCB_PFC_UP_ATTR_0; i < DCB_PFC_UP_ATTR_MAX; i++) {
+ dst_dcb_cfg->tc_config[i - DCB_PFC_UP_ATTR_0].dcb_pfc =
+ src_dcb_cfg->tc_config[i - DCB_PFC_UP_ATTR_0].dcb_pfc;
+ }
+
+ for (i = DCB_BCN_ATTR_RP_0; i < DCB_BCN_ATTR_RP_ALL; i++) {
+ dst_dcb_cfg->bcn.rp_admin_mode[i - DCB_BCN_ATTR_RP_0] =
+ src_dcb_cfg->bcn.rp_admin_mode[i - DCB_BCN_ATTR_RP_0];
+ }
+ dst_dcb_cfg->bcn.bcna_option[0] = src_dcb_cfg->bcn.bcna_option[0];
+ dst_dcb_cfg->bcn.bcna_option[1] = src_dcb_cfg->bcn.bcna_option[1];
+ dst_dcb_cfg->bcn.rp_alpha = src_dcb_cfg->bcn.rp_alpha;
+ dst_dcb_cfg->bcn.rp_beta = src_dcb_cfg->bcn.rp_beta;
+ dst_dcb_cfg->bcn.rp_gd = src_dcb_cfg->bcn.rp_gd;
+ dst_dcb_cfg->bcn.rp_gi = src_dcb_cfg->bcn.rp_gi;
+ dst_dcb_cfg->bcn.rp_tmax = src_dcb_cfg->bcn.rp_tmax;
+ dst_dcb_cfg->bcn.rp_td = src_dcb_cfg->bcn.rp_td;
+ dst_dcb_cfg->bcn.rp_rmin = src_dcb_cfg->bcn.rp_rmin;
+ dst_dcb_cfg->bcn.rp_w = src_dcb_cfg->bcn.rp_w;
+ dst_dcb_cfg->bcn.rp_rd = src_dcb_cfg->bcn.rp_rd;
+ dst_dcb_cfg->bcn.rp_ru = src_dcb_cfg->bcn.rp_ru;
+ dst_dcb_cfg->bcn.rp_wrtt = src_dcb_cfg->bcn.rp_wrtt;
+ dst_dcb_cfg->bcn.rp_ri = src_dcb_cfg->bcn.rp_ri;
+
+ return 0;
+}
+
+static u8 ixgbe_dcbnl_get_state(struct net_device *netdev)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ DPRINTK(DRV, INFO, "Get DCB Admin Mode.\n");
+
+ return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED);
+}
+
+static u16 ixgbe_dcb_select_queue(struct net_device *dev, struct sk_buff *skb)
+{
+ /* All traffic should default to class 0 */
+ return 0;
+}
+
+static u8 ixgbe_dcbnl_set_state(struct net_device *netdev, u8 state)
+{
+ u8 err = 0;
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ DPRINTK(DRV, INFO, "Set DCB Admin Mode.\n");
+
+ if (state > 0) {
+ /* Turn on DCB */
+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
+ goto out;
+
+ if (!(adapter->flags & IXGBE_FLAG_MSIX_ENABLED)) {
+ DPRINTK(DRV, ERR, "Enable failed, needs MSI-X\n");
+ err = 1;
+ goto out;
+ }
+
+ if (netif_running(netdev))
+ netdev->netdev_ops->ndo_stop(netdev);
+ ixgbe_reset_interrupt_capability(adapter);
+ ixgbe_napi_del_all(adapter);
+ INIT_LIST_HEAD(&netdev->napi_list);
+ kfree(adapter->tx_ring);
+ kfree(adapter->rx_ring);
+ adapter->tx_ring = NULL;
+ adapter->rx_ring = NULL;
+ netdev->select_queue = &ixgbe_dcb_select_queue;
+
+ adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
+ adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
+ ixgbe_init_interrupt_scheme(adapter);
+ if (netif_running(netdev))
+ netdev->netdev_ops->ndo_open(netdev);
+ } else {
+ /* Turn off DCB */
+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+ if (netif_running(netdev))
+ netdev->netdev_ops->ndo_stop(netdev);
+ ixgbe_reset_interrupt_capability(adapter);
+ ixgbe_napi_del_all(adapter);
+ INIT_LIST_HEAD(&netdev->napi_list);
+ kfree(adapter->tx_ring);
+ kfree(adapter->rx_ring);
+ adapter->tx_ring = NULL;
+ adapter->rx_ring = NULL;
+ netdev->select_queue = NULL;
+
+ adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
+ adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
+ ixgbe_init_interrupt_scheme(adapter);
+ if (netif_running(netdev))
+ netdev->netdev_ops->ndo_open(netdev);
+ }
+ }
+out:
+ return err;
+}
+
+static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev,
+ u8 *perm_addr)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ int i;
+
+ for (i = 0; i < netdev->addr_len; i++)
+ perm_addr[i] = adapter->hw.mac.perm_addr[i];
+}
+
+static void ixgbe_dcbnl_set_pg_tc_cfg_tx(struct net_device *netdev, int tc,
+ u8 prio, u8 bwg_id, u8 bw_pct,
+ u8 up_map)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ if (prio != DCB_ATTR_VALUE_UNDEFINED)
+ adapter->temp_dcb_cfg.tc_config[tc].path[0].prio_type = prio;
+ if (bwg_id != DCB_ATTR_VALUE_UNDEFINED)
+ adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_id = bwg_id;
+ if (bw_pct != DCB_ATTR_VALUE_UNDEFINED)
+ adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent =
+ bw_pct;
+ if (up_map != DCB_ATTR_VALUE_UNDEFINED)
+ adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap =
+ up_map;
+
+ if ((adapter->temp_dcb_cfg.tc_config[tc].path[0].prio_type !=
+ adapter->dcb_cfg.tc_config[tc].path[0].prio_type) ||
+ (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_id !=
+ adapter->dcb_cfg.tc_config[tc].path[0].bwg_id) ||
+ (adapter->temp_dcb_cfg.tc_config[tc].path[0].bwg_percent !=
+ adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent) ||
+ (adapter->temp_dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap !=
+ adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap))
+ adapter->dcb_set_bitmap |= BIT_PG_TX;
+}
+
+static void ixgbe_dcbnl_set_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
+ u8 bw_pct)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] = bw_pct;
+
+ if (adapter->temp_dcb_cfg.bw_percentage[0][bwg_id] !=
+ adapter->dcb_cfg.bw_percentage[0][bwg_id])
+ adapter->dcb_set_bitmap |= BIT_PG_RX;
+}
+
+static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc,
+ u8 prio, u8 bwg_id, u8 bw_pct,
+ u8 up_map)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ if (prio != DCB_ATTR_VALUE_UNDEFINED)
+ adapter->temp_dcb_cfg.tc_config[tc].path[1].prio_type = prio;
+ if (bwg_id != DCB_ATTR_VALUE_UNDEFINED)
+ adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_id = bwg_id;
+ if (bw_pct != DCB_ATTR_VALUE_UNDEFINED)
+ adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent =
+ bw_pct;
+ if (up_map != DCB_ATTR_VALUE_UNDEFINED)
+ adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap =
+ up_map;
+
+ if ((adapter->temp_dcb_cfg.tc_config[tc].path[1].prio_type !=
+ adapter->dcb_cfg.tc_config[tc].path[1].prio_type) ||
+ (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_id !=
+ adapter->dcb_cfg.tc_config[tc].path[1].bwg_id) ||
+ (adapter->temp_dcb_cfg.tc_config[tc].path[1].bwg_percent !=
+ adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent) ||
+ (adapter->temp_dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap !=
+ adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap))
+ adapter->dcb_set_bitmap |= BIT_PG_RX;
+}
+
+static void ixgbe_dcbnl_set_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
+ u8 bw_pct)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] = bw_pct;
+
+ if (adapter->temp_dcb_cfg.bw_percentage[1][bwg_id] !=
+ adapter->dcb_cfg.bw_percentage[1][bwg_id])
+ adapter->dcb_set_bitmap |= BIT_PG_RX;
+}
+
+static void ixgbe_dcbnl_get_pg_tc_cfg_tx(struct net_device *netdev, int tc,
+ u8 *prio, u8 *bwg_id, u8 *bw_pct,
+ u8 *up_map)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ *prio = adapter->dcb_cfg.tc_config[tc].path[0].prio_type;
+ *bwg_id = adapter->dcb_cfg.tc_config[tc].path[0].bwg_id;
+ *bw_pct = adapter->dcb_cfg.tc_config[tc].path[0].bwg_percent;
+ *up_map = adapter->dcb_cfg.tc_config[tc].path[0].up_to_tc_bitmap;
+}
+
+static void ixgbe_dcbnl_get_pg_bwg_cfg_tx(struct net_device *netdev, int bwg_id,
+ u8 *bw_pct)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ *bw_pct = adapter->dcb_cfg.bw_percentage[0][bwg_id];
+}
+
+static void ixgbe_dcbnl_get_pg_tc_cfg_rx(struct net_device *netdev, int tc,
+ u8 *prio, u8 *bwg_id, u8 *bw_pct,
+ u8 *up_map)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ *prio = adapter->dcb_cfg.tc_config[tc].path[1].prio_type;
+ *bwg_id = adapter->dcb_cfg.tc_config[tc].path[1].bwg_id;
+ *bw_pct = adapter->dcb_cfg.tc_config[tc].path[1].bwg_percent;
+ *up_map = adapter->dcb_cfg.tc_config[tc].path[1].up_to_tc_bitmap;
+}
+
+static void ixgbe_dcbnl_get_pg_bwg_cfg_rx(struct net_device *netdev, int bwg_id,
+ u8 *bw_pct)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ *bw_pct = adapter->dcb_cfg.bw_percentage[1][bwg_id];
+}
+
+static void ixgbe_dcbnl_set_pfc_cfg(struct net_device *netdev, int priority,
+ u8 setting)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc = setting;
+ if (adapter->temp_dcb_cfg.tc_config[priority].dcb_pfc !=
+ adapter->dcb_cfg.tc_config[priority].dcb_pfc)
+ adapter->dcb_set_bitmap |= BIT_PFC;
+}
+
+static void ixgbe_dcbnl_get_pfc_cfg(struct net_device *netdev, int priority,
+ u8 *setting)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ *setting = adapter->dcb_cfg.tc_config[priority].dcb_pfc;
+}
+
+static u8 ixgbe_dcbnl_set_all(struct net_device *netdev)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ int ret;
+
+ adapter->dcb_set_bitmap &= ~BIT_BCN; /* no set for BCN */
+ if (!adapter->dcb_set_bitmap)
+ return 1;
+
+ while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
+ msleep(1);
+
+ if (netif_running(netdev))
+ ixgbe_down(adapter);
+
+ ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
+ adapter->ring_feature[RING_F_DCB].indices);
+ if (ret) {
+ clear_bit(__IXGBE_RESETTING, &adapter->state);
+ return ret;
+ }
+
+ if (netif_running(netdev))
+ ixgbe_up(adapter);
+
+ adapter->dcb_set_bitmap = 0x00;
+ clear_bit(__IXGBE_RESETTING, &adapter->state);
+ return ret;
+}
+
+static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ u8 rval = 0;
+
+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+ switch (capid) {
+ case DCB_CAP_ATTR_PG:
+ *cap = true;
+ break;
+ case DCB_CAP_ATTR_PFC:
+ *cap = true;
+ break;
+ case DCB_CAP_ATTR_UP2TC:
+ *cap = false;
+ break;
+ case DCB_CAP_ATTR_PG_TCS:
+ *cap = 0x80;
+ break;
+ case DCB_CAP_ATTR_PFC_TCS:
+ *cap = 0x80;
+ break;
+ case DCB_CAP_ATTR_GSP:
+ *cap = true;
+ break;
+ case DCB_CAP_ATTR_BCN:
+ *cap = false;
+ break;
+ default:
+ rval = -EINVAL;
+ break;
+ }
+ } else {
+ rval = -EINVAL;
+ }
+
+ return rval;
+}
+
+static u8 ixgbe_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ u8 rval = 0;
+
+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+ switch (tcid) {
+ case DCB_NUMTCS_ATTR_PG:
+ *num = MAX_TRAFFIC_CLASS;
+ break;
+ case DCB_NUMTCS_ATTR_PFC:
+ *num = MAX_TRAFFIC_CLASS;
+ break;
+ default:
+ rval = -EINVAL;
+ break;
+ }
+ } else {
+ rval = -EINVAL;
+ }
+
+ return rval;
+}
+
+static u8 ixgbe_dcbnl_setnumtcs(struct net_device *netdev, int tcid, u8 num)
+{
+ return -EINVAL;
+}
+
+static u8 ixgbe_dcbnl_getpfcstate(struct net_device *netdev)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ return !!(adapter->flags & IXGBE_FLAG_DCB_ENABLED);
+}
+
+static void ixgbe_dcbnl_setpfcstate(struct net_device *netdev, u8 state)
+{
+ return;
+}
+
+static void ixgbe_dcbnl_getbcnrp(struct net_device *netdev, int priority,
+ u8 *setting)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ *setting = adapter->dcb_cfg.bcn.rp_admin_mode[priority];
+}
+
+
+static void ixgbe_dcbnl_getbcncfg(struct net_device *netdev, int enum_index,
+ u32 *setting)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ switch (enum_index) {
+ case DCB_BCN_ATTR_BCNA_0:
+ *setting = adapter->dcb_cfg.bcn.bcna_option[0];
+ break;
+ case DCB_BCN_ATTR_BCNA_1:
+ *setting = adapter->dcb_cfg.bcn.bcna_option[1];
+ break;
+ case DCB_BCN_ATTR_ALPHA:
+ *setting = adapter->dcb_cfg.bcn.rp_alpha;
+ break;
+ case DCB_BCN_ATTR_BETA:
+ *setting = adapter->dcb_cfg.bcn.rp_beta;
+ break;
+ case DCB_BCN_ATTR_GD:
+ *setting = adapter->dcb_cfg.bcn.rp_gd;
+ break;
+ case DCB_BCN_ATTR_GI:
+ *setting = adapter->dcb_cfg.bcn.rp_gi;
+ break;
+ case DCB_BCN_ATTR_TMAX:
+ *setting = adapter->dcb_cfg.bcn.rp_tmax;
+ break;
+ case DCB_BCN_ATTR_TD:
+ *setting = adapter->dcb_cfg.bcn.rp_td;
+ break;
+ case DCB_BCN_ATTR_RMIN:
+ *setting = adapter->dcb_cfg.bcn.rp_rmin;
+ break;
+ case DCB_BCN_ATTR_W:
+ *setting = adapter->dcb_cfg.bcn.rp_w;
+ break;
+ case DCB_BCN_ATTR_RD:
+ *setting = adapter->dcb_cfg.bcn.rp_rd;
+ break;
+ case DCB_BCN_ATTR_RU:
+ *setting = adapter->dcb_cfg.bcn.rp_ru;
+ break;
+ case DCB_BCN_ATTR_WRTT:
+ *setting = adapter->dcb_cfg.bcn.rp_wrtt;
+ break;
+ case DCB_BCN_ATTR_RI:
+ *setting = adapter->dcb_cfg.bcn.rp_ri;
+ break;
+ default:
+ *setting = -1;
+ }
+}
+
+static void ixgbe_dcbnl_setbcnrp(struct net_device *netdev, int priority,
+ u8 setting)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ adapter->temp_dcb_cfg.bcn.rp_admin_mode[priority] = setting;
+
+ if (adapter->temp_dcb_cfg.bcn.rp_admin_mode[priority] !=
+ adapter->dcb_cfg.bcn.rp_admin_mode[priority])
+ adapter->dcb_set_bitmap |= BIT_BCN;
+}
+
+static void ixgbe_dcbnl_setbcncfg(struct net_device *netdev, int enum_index,
+ u32 setting)
+{
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+
+ switch (enum_index) {
+ case DCB_BCN_ATTR_BCNA_0:
+ adapter->temp_dcb_cfg.bcn.bcna_option[0] = setting;
+ if (adapter->temp_dcb_cfg.bcn.bcna_option[0] !=
+ adapter->dcb_cfg.bcn.bcna_option[0])
+ adapter->dcb_set_bitmap |= BIT_BCN;
+ break;
+ case DCB_BCN_ATTR_BCNA_1:
+ adapter->temp_dcb_cfg.bcn.bcna_option[1] = setting;
+ if (adapter->temp_dcb_cfg.bcn.bcna_option[1] !=
+ adapter->dcb_cfg.bcn.bcna_option[1])
+ adapter->dcb_set_bitmap |= BIT_BCN;
+ break;
+ case DCB_BCN_ATTR_ALPHA:
+ adapter->temp_dcb_cfg.bcn.rp_alpha = setting;
+ if (adapter->temp_dcb_cfg.bcn.rp_alpha !=
+ adapter->dcb_cfg.bcn.rp_alpha)
+ adapter->dcb_set_bitmap |= BIT_BCN;
+ break;
+ case DCB_BCN_ATTR_BETA:
+ adapter->temp_dcb_cfg.bcn.rp_beta = setting;
+ if (adapter->temp_dcb_cfg.bcn.rp_beta !=
+ adapter->dcb_cfg.bcn.rp_beta)
+ adapter->dcb_set_bitmap |= BIT_BCN;
+ break;
+ case DCB_BCN_ATTR_GD:
+ adapter->temp_dcb_cfg.bcn.rp_gd = setting;
+ if (adapter->temp_dcb_cfg.bcn.rp_gd !=
+ adapter->dcb_cfg.bcn.rp_gd)
+ adapter->dcb_set_bitmap |= BIT_BCN;
+ break;
+ case DCB_BCN_ATTR_GI:
+ adapter->temp_dcb_cfg.bcn.rp_gi = setting;
+ if (adapter->temp_dcb_cfg.bcn.rp_gi !=
+ adapter->dcb_cfg.bcn.rp_gi)
+ adapter->dcb_set_bitmap |= BIT_BCN;
+ break;
+ case DCB_BCN_ATTR_TMAX:
+ adapter->temp_dcb_cfg.bcn.rp_tmax = setting;
+ if (adapter->temp_dcb_cfg.bcn.rp_tmax !=
+ adapter->dcb_cfg.bcn.rp_tmax)
+ adapter->dcb_set_bitmap |= BIT_BCN;
+ break;
+ case DCB_BCN_ATTR_TD:
+ adapter->temp_dcb_cfg.bcn.rp_td = setting;
+ if (adapter->temp_dcb_cfg.bcn.rp_td !=
+ adapter->dcb_cfg.bcn.rp_td)
+ adapter->dcb_set_bitmap |= BIT_BCN;
+ break;
+ case DCB_BCN_ATTR_RMIN:
+ adapter->temp_dcb_cfg.bcn.rp_rmin = setting;
+ if (adapter->temp_dcb_cfg.bcn.rp_rmin !=
+ adapter->dcb_cfg.bcn.rp_rmin)
+ adapter->dcb_set_bitmap |= BIT_BCN;
+ break;
+ case DCB_BCN_ATTR_W:
+ adapter->temp_dcb_cfg.bcn.rp_w = setting;
+ if (adapter->temp_dcb_cfg.bcn.rp_w !=
+ adapter->dcb_cfg.bcn.rp_w)
+ adapter->dcb_set_bitmap |= BIT_BCN;
+ break;
+ case DCB_BCN_ATTR_RD:
+ adapter->temp_dcb_cfg.bcn.rp_rd = setting;
+ if (adapter->temp_dcb_cfg.bcn.rp_rd !=
+ adapter->dcb_cfg.bcn.rp_rd)
+ adapter->dcb_set_bitmap |= BIT_BCN;
+ break;
+ case DCB_BCN_ATTR_RU:
+ adapter->temp_dcb_cfg.bcn.rp_ru = setting;
+ if (adapter->temp_dcb_cfg.bcn.rp_ru !=
+ adapter->dcb_cfg.bcn.rp_ru)
+ adapter->dcb_set_bitmap |= BIT_BCN;
+ break;
+ case DCB_BCN_ATTR_WRTT:
+ adapter->temp_dcb_cfg.bcn.rp_wrtt = setting;
+ if (adapter->temp_dcb_cfg.bcn.rp_wrtt !=
+ adapter->dcb_cfg.bcn.rp_wrtt)
+ adapter->dcb_set_bitmap |= BIT_BCN;
+ break;
+ case DCB_BCN_ATTR_RI:
+ adapter->temp_dcb_cfg.bcn.rp_ri = setting;
+ if (adapter->temp_dcb_cfg.bcn.rp_ri !=
+ adapter->dcb_cfg.bcn.rp_ri)
+ adapter->dcb_set_bitmap |= BIT_BCN;
+ break;
+ default:
+ break;
+ }
+}
+
+struct dcbnl_rtnl_ops dcbnl_ops = {
+ .getstate = ixgbe_dcbnl_get_state,
+ .setstate = ixgbe_dcbnl_set_state,
+ .getpermhwaddr = ixgbe_dcbnl_get_perm_hw_addr,
+ .setpgtccfgtx = ixgbe_dcbnl_set_pg_tc_cfg_tx,
+ .setpgbwgcfgtx = ixgbe_dcbnl_set_pg_bwg_cfg_tx,
+ .setpgtccfgrx = ixgbe_dcbnl_set_pg_tc_cfg_rx,
+ .setpgbwgcfgrx = ixgbe_dcbnl_set_pg_bwg_cfg_rx,
+ .getpgtccfgtx = ixgbe_dcbnl_get_pg_tc_cfg_tx,
+ .getpgbwgcfgtx = ixgbe_dcbnl_get_pg_bwg_cfg_tx,
+ .getpgtccfgrx = ixgbe_dcbnl_get_pg_tc_cfg_rx,
+ .getpgbwgcfgrx = ixgbe_dcbnl_get_pg_bwg_cfg_rx,
+ .setpfccfg = ixgbe_dcbnl_set_pfc_cfg,
+ .getpfccfg = ixgbe_dcbnl_get_pfc_cfg,
+ .setall = ixgbe_dcbnl_set_all,
+ .getcap = ixgbe_dcbnl_getcap,
+ .getnumtcs = ixgbe_dcbnl_getnumtcs,
+ .setnumtcs = ixgbe_dcbnl_setnumtcs,
+ .getpfcstate = ixgbe_dcbnl_getpfcstate,
+ .setpfcstate = ixgbe_dcbnl_setpfcstate,
+ .getbcncfg = ixgbe_dcbnl_getbcncfg,
+ .getbcnrp = ixgbe_dcbnl_getbcnrp,
+ .setbcncfg = ixgbe_dcbnl_setbcncfg,
+ .setbcnrp = ixgbe_dcbnl_setbcnrp
+};
+
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index 81a9c4b86726..67f87a79154d 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -94,12 +94,21 @@ static struct ixgbe_stats ixgbe_gstrings_stats[] = {
};
#define IXGBE_QUEUE_STATS_LEN \
- ((((struct ixgbe_adapter *)netdev->priv)->num_tx_queues + \
- ((struct ixgbe_adapter *)netdev->priv)->num_rx_queues) * \
- (sizeof(struct ixgbe_queue_stats) / sizeof(u64)))
-#define IXGBE_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + IXGBE_QUEUE_STATS_LEN)
+ ((((struct ixgbe_adapter *)netdev_priv(netdev))->num_tx_queues + \
+ ((struct ixgbe_adapter *)netdev_priv(netdev))->num_rx_queues) * \
+ (sizeof(struct ixgbe_queue_stats) / sizeof(u64)))
#define IXGBE_GLOBAL_STATS_LEN ARRAY_SIZE(ixgbe_gstrings_stats)
-#define IXGBE_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + IXGBE_QUEUE_STATS_LEN)
+#define IXGBE_PB_STATS_LEN ( \
+ (((struct ixgbe_adapter *)netdev_priv(netdev))->flags & \
+ IXGBE_FLAG_DCB_ENABLED) ? \
+ (sizeof(((struct ixgbe_adapter *)0)->stats.pxonrxc) + \
+ sizeof(((struct ixgbe_adapter *)0)->stats.pxontxc) + \
+ sizeof(((struct ixgbe_adapter *)0)->stats.pxoffrxc) + \
+ sizeof(((struct ixgbe_adapter *)0)->stats.pxofftxc)) \
+ / sizeof(u64) : 0)
+#define IXGBE_STATS_LEN (IXGBE_GLOBAL_STATS_LEN + \
+ IXGBE_PB_STATS_LEN + \
+ IXGBE_QUEUE_STATS_LEN)
static int ixgbe_get_settings(struct net_device *netdev,
struct ethtool_cmd *ecmd)
@@ -149,6 +158,8 @@ static int ixgbe_set_settings(struct net_device *netdev,
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_hw *hw = &adapter->hw;
+ u32 advertised, old;
+ s32 err;
switch (hw->phy.media_type) {
case ixgbe_media_type_fiber:
@@ -157,6 +168,31 @@ static int ixgbe_set_settings(struct net_device *netdev,
return -EINVAL;
/* in this case we currently only support 10Gb/FULL */
break;
+ case ixgbe_media_type_copper:
+ /* 10000/copper and 1000/copper must autoneg
+ * this function does not support any duplex forcing, but can
+ * limit the advertising of the adapter to only 10000 or 1000 */
+ if (ecmd->autoneg == AUTONEG_DISABLE)
+ return -EINVAL;
+
+ old = hw->phy.autoneg_advertised;
+ advertised = 0;
+ if (ecmd->advertising & ADVERTISED_10000baseT_Full)
+ advertised |= IXGBE_LINK_SPEED_10GB_FULL;
+
+ if (ecmd->advertising & ADVERTISED_1000baseT_Full)
+ advertised |= IXGBE_LINK_SPEED_1GB_FULL;
+
+ if (old == advertised)
+ break;
+ /* this sets the link speed and restarts auto-neg */
+ err = hw->mac.ops.setup_link_speed(hw, advertised, true, true);
+ if (err) {
+ DPRINTK(PROBE, INFO,
+ "setup link failed with code %d\n", err);
+ hw->mac.ops.setup_link_speed(hw, old, true, true);
+ }
+ break;
default:
break;
}
@@ -676,30 +712,15 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
return 0;
}
- if (adapter->num_tx_queues > adapter->num_rx_queues)
- temp_ring = vmalloc(adapter->num_tx_queues *
- sizeof(struct ixgbe_ring));
- else
- temp_ring = vmalloc(adapter->num_rx_queues *
- sizeof(struct ixgbe_ring));
+ temp_ring = kcalloc(adapter->num_tx_queues,
+ sizeof(struct ixgbe_ring), GFP_KERNEL);
if (!temp_ring)
return -ENOMEM;
while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
msleep(1);
- if (netif_running(netdev))
- ixgbe_down(adapter);
-
- /*
- * We can't just free everything and then setup again,
- * because the ISRs in MSI-X mode get passed pointers
- * to the tx and rx ring structs.
- */
if (new_tx_count != adapter->tx_ring->count) {
- memcpy(temp_ring, adapter->tx_ring,
- adapter->num_tx_queues * sizeof(struct ixgbe_ring));
-
for (i = 0; i < adapter->num_tx_queues; i++) {
temp_ring[i].count = new_tx_count;
err = ixgbe_setup_tx_resources(adapter, &temp_ring[i]);
@@ -711,21 +732,28 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
}
goto err_setup;
}
+ temp_ring[i].v_idx = adapter->tx_ring[i].v_idx;
}
-
- for (i = 0; i < adapter->num_tx_queues; i++)
- ixgbe_free_tx_resources(adapter, &adapter->tx_ring[i]);
-
- memcpy(adapter->tx_ring, temp_ring,
- adapter->num_tx_queues * sizeof(struct ixgbe_ring));
-
+ if (netif_running(netdev))
+ netdev->netdev_ops->ndo_stop(netdev);
+ ixgbe_reset_interrupt_capability(adapter);
+ ixgbe_napi_del_all(adapter);
+ INIT_LIST_HEAD(&netdev->napi_list);
+ kfree(adapter->tx_ring);
+ adapter->tx_ring = temp_ring;
+ temp_ring = NULL;
adapter->tx_ring_count = new_tx_count;
}
- if (new_rx_count != adapter->rx_ring->count) {
- memcpy(temp_ring, adapter->rx_ring,
- adapter->num_rx_queues * sizeof(struct ixgbe_ring));
+ temp_ring = kcalloc(adapter->num_rx_queues,
+ sizeof(struct ixgbe_ring), GFP_KERNEL);
+ if (!temp_ring) {
+ if (netif_running(netdev))
+ netdev->netdev_ops->ndo_open(netdev);
+ return -ENOMEM;
+ }
+ if (new_rx_count != adapter->rx_ring->count) {
for (i = 0; i < adapter->num_rx_queues; i++) {
temp_ring[i].count = new_rx_count;
err = ixgbe_setup_rx_resources(adapter, &temp_ring[i]);
@@ -737,13 +765,16 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
}
goto err_setup;
}
+ temp_ring[i].v_idx = adapter->rx_ring[i].v_idx;
}
-
- for (i = 0; i < adapter->num_rx_queues; i++)
- ixgbe_free_rx_resources(adapter, &adapter->rx_ring[i]);
-
- memcpy(adapter->rx_ring, temp_ring,
- adapter->num_rx_queues * sizeof(struct ixgbe_ring));
+ if (netif_running(netdev))
+ netdev->netdev_ops->ndo_stop(netdev);
+ ixgbe_reset_interrupt_capability(adapter);
+ ixgbe_napi_del_all(adapter);
+ INIT_LIST_HEAD(&netdev->napi_list);
+ kfree(adapter->rx_ring);
+ adapter->rx_ring = temp_ring;
+ temp_ring = NULL;
adapter->rx_ring_count = new_rx_count;
}
@@ -751,8 +782,9 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
/* success! */
err = 0;
err_setup:
+ ixgbe_init_interrupt_scheme(adapter);
if (netif_running(netdev))
- ixgbe_up(adapter);
+ netdev->netdev_ops->ndo_open(netdev);
clear_bit(__IXGBE_RESETTING, &adapter->state);
return err;
@@ -804,6 +836,16 @@ static void ixgbe_get_ethtool_stats(struct net_device *netdev,
data[i + k] = queue_stat[k];
i += k;
}
+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+ for (j = 0; j < MAX_TX_PACKET_BUFFERS; j++) {
+ data[i++] = adapter->stats.pxontxc[j];
+ data[i++] = adapter->stats.pxofftxc[j];
+ }
+ for (j = 0; j < MAX_RX_PACKET_BUFFERS; j++) {
+ data[i++] = adapter->stats.pxonrxc[j];
+ data[i++] = adapter->stats.pxoffrxc[j];
+ }
+ }
}
static void ixgbe_get_strings(struct net_device *netdev, u32 stringset,
@@ -832,6 +874,20 @@ static void ixgbe_get_strings(struct net_device *netdev, u32 stringset,
sprintf(p, "rx_queue_%u_bytes", i);
p += ETH_GSTRING_LEN;
}
+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+ for (i = 0; i < MAX_TX_PACKET_BUFFERS; i++) {
+ sprintf(p, "tx_pb_%u_pxon", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "tx_pb_%u_pxoff", i);
+ p += ETH_GSTRING_LEN;
+ }
+ for (i = 0; i < MAX_RX_PACKET_BUFFERS; i++) {
+ sprintf(p, "rx_pb_%u_pxon", i);
+ p += ETH_GSTRING_LEN;
+ sprintf(p, "rx_pb_%u_pxoff", i);
+ p += ETH_GSTRING_LEN;
+ }
+ }
/* BUG_ON(p - data != IXGBE_STATS_LEN * ETH_GSTRING_LEN); */
break;
}
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c
index 5236f633ee36..acef3c65cd2c 100644
--- a/drivers/net/ixgbe/ixgbe_main.c
+++ b/drivers/net/ixgbe/ixgbe_main.c
@@ -68,12 +68,20 @@ static struct pci_device_id ixgbe_pci_tbl[] = {
board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AF_SINGLE_PORT),
board_82598 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598AT),
+ board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_CX4),
board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_CX4_DUAL_PORT),
board_82598 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_DA_DUAL_PORT),
+ board_82598 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM),
+ board_82598 },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_XF_LR),
board_82598 },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_SFP_LOM),
+ board_82598 },
/* required last entry */
{0, }
@@ -402,7 +410,7 @@ static void ixgbe_receive_skb(struct ixgbe_adapter *adapter,
if (adapter->netdev->features & NETIF_F_LRO &&
skb->ip_summed == CHECKSUM_UNNECESSARY) {
- if (adapter->vlgrp && is_vlan)
+ if (adapter->vlgrp && is_vlan && (tag != 0))
lro_vlan_hwaccel_receive_skb(&ring->lro_mgr, skb,
adapter->vlgrp, tag,
rx_desc);
@@ -411,12 +419,12 @@ static void ixgbe_receive_skb(struct ixgbe_adapter *adapter,
ring->lro_used = true;
} else {
if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
- if (adapter->vlgrp && is_vlan)
+ if (adapter->vlgrp && is_vlan && (tag != 0))
vlan_hwaccel_receive_skb(skb, adapter->vlgrp, tag);
else
netif_receive_skb(skb);
} else {
- if (adapter->vlgrp && is_vlan)
+ if (adapter->vlgrp && is_vlan && (tag != 0))
vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
else
netif_rx(skb);
@@ -471,7 +479,6 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
union ixgbe_adv_rx_desc *rx_desc;
struct ixgbe_rx_buffer *bi;
unsigned int i;
- unsigned int bufsz = rx_ring->rx_buf_len + NET_IP_ALIGN;
i = rx_ring->next_to_use;
bi = &rx_ring->rx_buffer_info[i];
@@ -500,8 +507,10 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
}
if (!bi->skb) {
- struct sk_buff *skb = netdev_alloc_skb(adapter->netdev,
- bufsz);
+ struct sk_buff *skb;
+ skb = netdev_alloc_skb(adapter->netdev,
+ (rx_ring->rx_buf_len +
+ NET_IP_ALIGN));
if (!skb) {
adapter->alloc_rx_buff_failed++;
@@ -516,7 +525,8 @@ static void ixgbe_alloc_rx_buffers(struct ixgbe_adapter *adapter,
skb_reserve(skb, NET_IP_ALIGN);
bi->skb = skb;
- bi->dma = pci_map_single(pdev, skb->data, bufsz,
+ bi->dma = pci_map_single(pdev, skb->data,
+ rx_ring->rx_buf_len,
PCI_DMA_FROMDEVICE);
}
/* Refresh the desc even if buffer_addrs didn't change because
@@ -607,7 +617,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter,
if (len && !skb_shinfo(skb)->nr_frags) {
pci_unmap_single(pdev, rx_buffer_info->dma,
- rx_ring->rx_buf_len + NET_IP_ALIGN,
+ rx_ring->rx_buf_len,
PCI_DMA_FROMDEVICE);
skb_put(skb, len);
}
@@ -666,7 +676,6 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_adapter *adapter,
skb->protocol = eth_type_trans(skb, adapter->netdev);
ixgbe_receive_skb(adapter, skb, staterr, rx_ring, rx_desc);
- adapter->netdev->last_rx = jiffies;
next_desc:
rx_desc->wb.upper.status_error = 0;
@@ -904,6 +913,17 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector)
return;
}
+static void ixgbe_check_fan_failure(struct ixgbe_adapter *adapter, u32 eicr)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+
+ if ((adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) &&
+ (eicr & IXGBE_EICR_GPI_SDP1)) {
+ DPRINTK(PROBE, CRIT, "Fan has stopped, replace the adapter\n");
+ /* write to clear the interrupt */
+ IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1);
+ }
+}
static void ixgbe_check_lsc(struct ixgbe_adapter *adapter)
{
@@ -928,6 +948,8 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data)
if (eicr & IXGBE_EICR_LSC)
ixgbe_check_lsc(adapter);
+ ixgbe_check_fan_failure(adapter, eicr);
+
if (!test_bit(__IXGBE_DOWN, &adapter->state))
IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_OTHER);
@@ -990,7 +1012,7 @@ static irqreturn_t ixgbe_msix_clean_rx(int irq, void *data)
rx_ring = &(adapter->rx_ring[r_idx]);
/* disable interrupts on this vector only */
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, rx_ring->v_idx);
- netif_rx_schedule(adapter->netdev, &q_vector->napi);
+ netif_rx_schedule(&q_vector->napi);
return IRQ_HANDLED;
}
@@ -1031,7 +1053,7 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)
/* If all Rx work done, exit the polling mode */
if (work_done < budget) {
- netif_rx_complete(adapter->netdev, napi);
+ netif_rx_complete(napi);
if (adapter->itr_setting & 3)
ixgbe_set_itr_msix(q_vector);
if (!test_bit(__IXGBE_DOWN, &adapter->state))
@@ -1080,7 +1102,7 @@ static int ixgbe_clean_rxonly_many(struct napi_struct *napi, int budget)
rx_ring = &(adapter->rx_ring[r_idx]);
/* If all Rx work done, exit the polling mode */
if (work_done < budget) {
- netif_rx_complete(adapter->netdev, napi);
+ netif_rx_complete(napi);
if (adapter->itr_setting & 3)
ixgbe_set_itr_msix(q_vector);
if (!test_bit(__IXGBE_DOWN, &adapter->state))
@@ -1187,6 +1209,7 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
struct net_device *netdev = adapter->netdev;
irqreturn_t (*handler)(int, void *);
int i, vector, q_vectors, err;
+ int ri=0, ti=0;
/* Decrement for Other and TCP Timer vectors */
q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
@@ -1201,10 +1224,19 @@ static int ixgbe_request_msix_irqs(struct ixgbe_adapter *adapter)
&ixgbe_msix_clean_many)
for (vector = 0; vector < q_vectors; vector++) {
handler = SET_HANDLER(&adapter->q_vector[vector]);
- sprintf(adapter->name[vector], "%s:v%d-%s",
- netdev->name, vector,
- (handler == &ixgbe_msix_clean_rx) ? "Rx" :
- ((handler == &ixgbe_msix_clean_tx) ? "Tx" : "TxRx"));
+
+ if(handler == &ixgbe_msix_clean_rx) {
+ sprintf(adapter->name[vector], "%s-%s-%d",
+ netdev->name, "rx", ri++);
+ }
+ else if(handler == &ixgbe_msix_clean_tx) {
+ sprintf(adapter->name[vector], "%s-%s-%d",
+ netdev->name, "tx", ti++);
+ }
+ else
+ sprintf(adapter->name[vector], "%s-%s-%d",
+ netdev->name, "TxRx", vector);
+
err = request_irq(adapter->msix_entries[vector].vector,
handler, 0, adapter->name[vector],
&(adapter->q_vector[vector]));
@@ -1312,6 +1344,8 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter)
{
u32 mask;
mask = IXGBE_EIMS_ENABLE_MASK;
+ if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE)
+ mask |= IXGBE_EIMS_GPI_SDP1;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMS, mask);
IXGBE_WRITE_FLUSH(&adapter->hw);
}
@@ -1342,13 +1376,15 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
if (eicr & IXGBE_EICR_LSC)
ixgbe_check_lsc(adapter);
- if (netif_rx_schedule_prep(netdev, &adapter->q_vector[0].napi)) {
+ ixgbe_check_fan_failure(adapter, eicr);
+
+ if (netif_rx_schedule_prep(&adapter->q_vector[0].napi)) {
adapter->tx_ring[0].total_packets = 0;
adapter->tx_ring[0].total_bytes = 0;
adapter->rx_ring[0].total_packets = 0;
adapter->rx_ring[0].total_bytes = 0;
/* would disable interrupts here but EIAM disabled it */
- __netif_rx_schedule(netdev, &adapter->q_vector[0].napi);
+ __netif_rx_schedule(&adapter->q_vector[0].napi);
}
return IRQ_HANDLED;
@@ -1651,10 +1687,12 @@ static void ixgbe_configure_rx(struct ixgbe_adapter *adapter)
* effects of setting this bit are only that SRRCTL must be
* fully programmed [0..15]
*/
- rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
- rdrxctl |= IXGBE_RDRXCTL_MVMEN;
- IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl);
-
+ if (adapter->flags &
+ (IXGBE_FLAG_RSS_ENABLED | IXGBE_FLAG_VMDQ_ENABLED)) {
+ rdrxctl = IXGBE_READ_REG(hw, IXGBE_RDRXCTL);
+ rdrxctl |= IXGBE_RDRXCTL_MVMEN;
+ IXGBE_WRITE_REG(hw, IXGBE_RDRXCTL, rdrxctl);
+ }
if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
/* Fill out redirection table */
@@ -1713,6 +1751,16 @@ static void ixgbe_vlan_rx_register(struct net_device *netdev,
ixgbe_irq_disable(adapter);
adapter->vlgrp = grp;
+ /*
+ * For a DCB driver, always enable VLAN tag stripping so we can
+ * still receive traffic from a DCB-enabled host even if we're
+ * not in DCB mode.
+ */
+ ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_VLNCTRL);
+ ctrl |= IXGBE_VLNCTRL_VME;
+ ctrl &= ~IXGBE_VLNCTRL_CFIEN;
+ IXGBE_WRITE_REG(&adapter->hw, IXGBE_VLNCTRL, ctrl);
+
if (grp) {
/* enable VLAN tag insert/strip */
ctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_VLNCTRL);
@@ -1877,6 +1925,44 @@ static void ixgbe_napi_disable_all(struct ixgbe_adapter *adapter)
}
}
+#ifdef CONFIG_IXGBE_DCB
+/*
+ * ixgbe_configure_dcb - Configure DCB hardware
+ * @adapter: ixgbe adapter struct
+ *
+ * This is called by the driver on open to configure the DCB hardware.
+ * This is also called by the gennetlink interface when reconfiguring
+ * the DCB state.
+ */
+static void ixgbe_configure_dcb(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ u32 txdctl, vlnctrl;
+ int i, j;
+
+ ixgbe_dcb_check_config(&adapter->dcb_cfg);
+ ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, DCB_TX_CONFIG);
+ ixgbe_dcb_calculate_tc_credits(&adapter->dcb_cfg, DCB_RX_CONFIG);
+
+ /* reconfigure the hardware */
+ ixgbe_dcb_hw_config(&adapter->hw, &adapter->dcb_cfg);
+
+ for (i = 0; i < adapter->num_tx_queues; i++) {
+ j = adapter->tx_ring[i].reg_idx;
+ txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(j));
+ /* PThresh workaround for Tx hang with DFP enabled. */
+ txdctl |= 32;
+ IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(j), txdctl);
+ }
+ /* Enable VLAN tag insert/strip */
+ vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL);
+ vlnctrl |= IXGBE_VLNCTRL_VME | IXGBE_VLNCTRL_VFE;
+ vlnctrl &= ~IXGBE_VLNCTRL_CFIEN;
+ IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl);
+ hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true);
+}
+
+#endif
static void ixgbe_configure(struct ixgbe_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
@@ -1885,6 +1971,16 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
ixgbe_set_rx_mode(netdev);
ixgbe_restore_vlan(adapter);
+#ifdef CONFIG_IXGBE_DCB
+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+ netif_set_gso_max_size(netdev, 32768);
+ ixgbe_configure_dcb(adapter);
+ } else {
+ netif_set_gso_max_size(netdev, 65536);
+ }
+#else
+ netif_set_gso_max_size(netdev, 65536);
+#endif
ixgbe_configure_tx(adapter);
ixgbe_configure_rx(adapter);
@@ -1924,6 +2020,13 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE);
}
+ /* Enable fan failure interrupt if media type is copper */
+ if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) {
+ gpie = IXGBE_READ_REG(hw, IXGBE_GPIE);
+ gpie |= IXGBE_SDP1_GPIEN;
+ IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie);
+ }
+
mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
if (max_frame != (mhadd >> IXGBE_MHADD_MFS_SHIFT)) {
mhadd &= ~IXGBE_MHADD_MFS_MASK;
@@ -1961,6 +2064,8 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter)
else
ixgbe_configure_msi_and_legacy(adapter);
+ ixgbe_napi_add_all(adapter);
+
clear_bit(__IXGBE_DOWN, &adapter->state);
ixgbe_napi_enable_all(adapter);
@@ -2205,7 +2310,7 @@ static int ixgbe_poll(struct napi_struct *napi, int budget)
/* If budget not fully consumed, exit the polling mode */
if (work_done < budget) {
- netif_rx_complete(adapter->netdev, napi);
+ netif_rx_complete(napi);
if (adapter->itr_setting & 3)
ixgbe_set_itr(adapter);
if (!test_bit(__IXGBE_DOWN, &adapter->state))
@@ -2231,6 +2336,11 @@ static void ixgbe_reset_task(struct work_struct *work)
struct ixgbe_adapter *adapter;
adapter = container_of(work, struct ixgbe_adapter, reset_task);
+ /* If we're already down or resetting, just bail */
+ if (test_bit(__IXGBE_DOWN, &adapter->state) ||
+ test_bit(__IXGBE_RESETTING, &adapter->state))
+ return;
+
adapter->tx_timeout_count++;
ixgbe_reinit_locked(adapter);
@@ -2240,15 +2350,31 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
{
int nrq = 1, ntq = 1;
int feature_mask = 0, rss_i, rss_m;
+ int dcb_i, dcb_m;
/* Number of supported queues */
switch (adapter->hw.mac.type) {
case ixgbe_mac_82598EB:
+ dcb_i = adapter->ring_feature[RING_F_DCB].indices;
+ dcb_m = 0;
rss_i = adapter->ring_feature[RING_F_RSS].indices;
rss_m = 0;
feature_mask |= IXGBE_FLAG_RSS_ENABLED;
+ feature_mask |= IXGBE_FLAG_DCB_ENABLED;
switch (adapter->flags & feature_mask) {
+ case (IXGBE_FLAG_RSS_ENABLED | IXGBE_FLAG_DCB_ENABLED):
+ dcb_m = 0x7 << 3;
+ rss_i = min(8, rss_i);
+ rss_m = 0x7;
+ nrq = dcb_i * rss_i;
+ ntq = min(MAX_TX_QUEUES, dcb_i * rss_i);
+ break;
+ case (IXGBE_FLAG_DCB_ENABLED):
+ dcb_m = 0x7 << 3;
+ nrq = dcb_i;
+ ntq = dcb_i;
+ break;
case (IXGBE_FLAG_RSS_ENABLED):
rss_m = 0xF;
nrq = rss_i;
@@ -2256,6 +2382,8 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
break;
case 0:
default:
+ dcb_i = 0;
+ dcb_m = 0;
rss_i = 0;
rss_m = 0;
nrq = 1;
@@ -2263,6 +2391,12 @@ static void ixgbe_set_num_queues(struct ixgbe_adapter *adapter)
break;
}
+ /* Sanity check, we should never have zero queues */
+ nrq = (nrq ?:1);
+ ntq = (ntq ?:1);
+
+ adapter->ring_feature[RING_F_DCB].indices = dcb_i;
+ adapter->ring_feature[RING_F_DCB].mask = dcb_m;
adapter->ring_feature[RING_F_RSS].indices = rss_i;
adapter->ring_feature[RING_F_RSS].mask = rss_m;
break;
@@ -2314,6 +2448,7 @@ static void ixgbe_acquire_msix_vectors(struct ixgbe_adapter *adapter,
adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
kfree(adapter->msix_entries);
adapter->msix_entries = NULL;
+ adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
ixgbe_set_num_queues(adapter);
} else {
@@ -2333,15 +2468,42 @@ static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter)
{
int feature_mask = 0, rss_i;
int i, txr_idx, rxr_idx;
+ int dcb_i;
/* Number of supported queues */
switch (adapter->hw.mac.type) {
case ixgbe_mac_82598EB:
+ dcb_i = adapter->ring_feature[RING_F_DCB].indices;
rss_i = adapter->ring_feature[RING_F_RSS].indices;
txr_idx = 0;
rxr_idx = 0;
+ feature_mask |= IXGBE_FLAG_DCB_ENABLED;
feature_mask |= IXGBE_FLAG_RSS_ENABLED;
switch (adapter->flags & feature_mask) {
+ case (IXGBE_FLAG_RSS_ENABLED | IXGBE_FLAG_DCB_ENABLED):
+ for (i = 0; i < dcb_i; i++) {
+ int j;
+ /* Rx first */
+ for (j = 0; j < adapter->num_rx_queues; j++) {
+ adapter->rx_ring[rxr_idx].reg_idx =
+ i << 3 | j;
+ rxr_idx++;
+ }
+ /* Tx now */
+ for (j = 0; j < adapter->num_tx_queues; j++) {
+ adapter->tx_ring[txr_idx].reg_idx =
+ i << 2 | (j >> 1);
+ if (j & 1)
+ txr_idx++;
+ }
+ }
+ case (IXGBE_FLAG_DCB_ENABLED):
+ /* the number of queues is assumed to be symmetric */
+ for (i = 0; i < dcb_i; i++) {
+ adapter->rx_ring[i].reg_idx = i << 3;
+ adapter->tx_ring[i].reg_idx = i << 2;
+ }
+ break;
case (IXGBE_FLAG_RSS_ENABLED):
for (i = 0; i < adapter->num_rx_queues; i++)
adapter->rx_ring[i].reg_idx = i;
@@ -2363,8 +2525,7 @@ static void ixgbe_cache_ring_register(struct ixgbe_adapter *adapter)
* @adapter: board private structure to initialize
*
* We allocate one ring per queue at run-time since we don't know the
- * number of queues at compile-time. The polling_netdev array is
- * intended for Multiqueue, but should work fine with a single queue.
+ * number of queues at compile-time.
**/
static int ixgbe_alloc_queues(struct ixgbe_adapter *adapter)
{
@@ -2435,6 +2596,7 @@ static int ixgbe_set_interrupt_capability(struct ixgbe_adapter *adapter)
adapter->msix_entries = kcalloc(v_budget,
sizeof(struct msix_entry), GFP_KERNEL);
if (!adapter->msix_entries) {
+ adapter->flags &= ~IXGBE_FLAG_DCB_ENABLED;
adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
ixgbe_set_num_queues(adapter);
kfree(adapter->tx_ring);
@@ -2475,7 +2637,7 @@ out:
return err;
}
-static void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter)
+void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter)
{
if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
adapter->flags &= ~IXGBE_FLAG_MSIX_ENABLED;
@@ -2499,7 +2661,7 @@ static void ixgbe_reset_interrupt_capability(struct ixgbe_adapter *adapter)
* - Hardware queue count (num_*_queues)
* - defined by miscellaneous hardware support/features (RSS, etc.)
**/
-static int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
+int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
{
int err;
@@ -2535,6 +2697,57 @@ err_alloc_queues:
}
/**
+ * ixgbe_sfp_timer - worker thread to find a missing module
+ * @data: pointer to our adapter struct
+ **/
+static void ixgbe_sfp_timer(unsigned long data)
+{
+ struct ixgbe_adapter *adapter = (struct ixgbe_adapter *)data;
+
+ /* Do the sfp_timer outside of interrupt context due to the
+ * delays that sfp+ detection requires
+ */
+ schedule_work(&adapter->sfp_task);
+}
+
+/**
+ * ixgbe_sfp_task - worker thread to find a missing module
+ * @work: pointer to work_struct containing our data
+ **/
+static void ixgbe_sfp_task(struct work_struct *work)
+{
+ struct ixgbe_adapter *adapter = container_of(work,
+ struct ixgbe_adapter,
+ sfp_task);
+ struct ixgbe_hw *hw = &adapter->hw;
+
+ if ((hw->phy.type == ixgbe_phy_nl) &&
+ (hw->phy.sfp_type == ixgbe_sfp_type_not_present)) {
+ s32 ret = hw->phy.ops.identify_sfp(hw);
+ if (ret)
+ goto reschedule;
+ ret = hw->phy.ops.reset(hw);
+ if (ret == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+ DPRINTK(PROBE, ERR, "failed to initialize because an "
+ "unsupported SFP+ module type was detected.\n"
+ "Reload the driver after installing a "
+ "supported module.\n");
+ unregister_netdev(adapter->netdev);
+ } else {
+ DPRINTK(PROBE, INFO, "detected SFP+: %d\n",
+ hw->phy.sfp_type);
+ }
+ /* don't need this routine any more */
+ clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
+ }
+ return;
+reschedule:
+ if (test_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state))
+ mod_timer(&adapter->sfp_timer,
+ round_jiffies(jiffies + (2 * HZ)));
+}
+
+/**
* ixgbe_sw_init - Initialize general software structures (struct ixgbe_adapter)
* @adapter: board private structure to initialize
*
@@ -2547,6 +2760,10 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
struct ixgbe_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev;
unsigned int rss;
+#ifdef CONFIG_IXGBE_DCB
+ int j;
+ struct tc_configuration *tc;
+#endif
/* PCI config space info */
@@ -2560,6 +2777,30 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter)
rss = min(IXGBE_MAX_RSS_INDICES, (int)num_online_cpus());
adapter->ring_feature[RING_F_RSS].indices = rss;
adapter->flags |= IXGBE_FLAG_RSS_ENABLED;
+ adapter->ring_feature[RING_F_DCB].indices = IXGBE_MAX_DCB_INDICES;
+
+#ifdef CONFIG_IXGBE_DCB
+ /* Configure DCB traffic classes */
+ for (j = 0; j < MAX_TRAFFIC_CLASS; j++) {
+ tc = &adapter->dcb_cfg.tc_config[j];
+ tc->path[DCB_TX_CONFIG].bwg_id = 0;
+ tc->path[DCB_TX_CONFIG].bwg_percent = 12 + (j & 1);
+ tc->path[DCB_RX_CONFIG].bwg_id = 0;
+ tc->path[DCB_RX_CONFIG].bwg_percent = 12 + (j & 1);
+ tc->dcb_pfc = pfc_disabled;
+ }
+ adapter->dcb_cfg.bw_percentage[DCB_TX_CONFIG][0] = 100;
+ adapter->dcb_cfg.bw_percentage[DCB_RX_CONFIG][0] = 100;
+ adapter->dcb_cfg.rx_pba_cfg = pba_equal;
+ adapter->dcb_cfg.round_robin_enable = false;
+ adapter->dcb_set_bitmap = 0x00;
+ ixgbe_copy_dcb_cfg(&adapter->dcb_cfg, &adapter->temp_dcb_cfg,
+ adapter->ring_feature[RING_F_DCB].indices);
+
+#endif
+ if (hw->mac.ops.get_media_type &&
+ (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper))
+ adapter->flags |= IXGBE_FLAG_FAN_FAIL_CAPABLE;
/* default flow control settings */
hw->fc.original_type = ixgbe_fc_none;
@@ -2934,11 +3175,16 @@ static int ixgbe_close(struct net_device *netdev)
* @adapter: private struct
* helper function to napi_add each possible q_vector->napi
*/
-static void ixgbe_napi_add_all(struct ixgbe_adapter *adapter)
+void ixgbe_napi_add_all(struct ixgbe_adapter *adapter)
{
int q_idx, q_vectors;
+ struct net_device *netdev = adapter->netdev;
int (*poll)(struct napi_struct *, int);
+ /* check if we already have our netdev->napi_list populated */
+ if (&netdev->napi_list != netdev->napi_list.next)
+ return;
+
if (adapter->flags & IXGBE_FLAG_MSIX_ENABLED) {
poll = &ixgbe_clean_rxonly;
/* Only enable as many vectors as we have rx queues. */
@@ -2955,7 +3201,7 @@ static void ixgbe_napi_add_all(struct ixgbe_adapter *adapter)
}
}
-static void ixgbe_napi_del_all(struct ixgbe_adapter *adapter)
+void ixgbe_napi_del_all(struct ixgbe_adapter *adapter)
{
int q_idx;
int q_vectors = adapter->num_msix_vectors - NON_Q_VECTORS;
@@ -3032,6 +3278,7 @@ static int ixgbe_suspend(struct pci_dev *pdev, pm_message_t state)
}
ixgbe_reset_interrupt_capability(adapter);
ixgbe_napi_del_all(adapter);
+ INIT_LIST_HEAD(&netdev->napi_list);
kfree(adapter->tx_ring);
kfree(adapter->rx_ring);
@@ -3076,6 +3323,18 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
adapter->stats.mpc[i] += mpc;
total_mpc += adapter->stats.mpc[i];
adapter->stats.rnbc[i] += IXGBE_READ_REG(hw, IXGBE_RNBC(i));
+ adapter->stats.qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
+ adapter->stats.qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC(i));
+ adapter->stats.qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
+ adapter->stats.qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC(i));
+ adapter->stats.pxonrxc[i] += IXGBE_READ_REG(hw,
+ IXGBE_PXONRXC(i));
+ adapter->stats.pxontxc[i] += IXGBE_READ_REG(hw,
+ IXGBE_PXONTXC(i));
+ adapter->stats.pxoffrxc[i] += IXGBE_READ_REG(hw,
+ IXGBE_PXOFFRXC(i));
+ adapter->stats.pxofftxc[i] += IXGBE_READ_REG(hw,
+ IXGBE_PXOFFTXC(i));
}
adapter->stats.gprc += IXGBE_READ_REG(hw, IXGBE_GPRC);
/* work around hardware counting issue */
@@ -3204,15 +3463,16 @@ static void ixgbe_watchdog_task(struct work_struct *work)
u32 rmcs = IXGBE_READ_REG(hw, IXGBE_RMCS);
#define FLOW_RX (frctl & IXGBE_FCTRL_RFCE)
#define FLOW_TX (rmcs & IXGBE_RMCS_TFCE_802_3X)
- DPRINTK(LINK, INFO, "NIC Link is Up %s, "
- "Flow Control: %s\n",
- (link_speed == IXGBE_LINK_SPEED_10GB_FULL ?
- "10 Gbps" :
- (link_speed == IXGBE_LINK_SPEED_1GB_FULL ?
- "1 Gbps" : "unknown speed")),
- ((FLOW_RX && FLOW_TX) ? "RX/TX" :
- (FLOW_RX ? "RX" :
- (FLOW_TX ? "TX" : "None"))));
+ printk(KERN_INFO "ixgbe: %s NIC Link is Up %s, "
+ "Flow Control: %s\n",
+ netdev->name,
+ (link_speed == IXGBE_LINK_SPEED_10GB_FULL ?
+ "10 Gbps" :
+ (link_speed == IXGBE_LINK_SPEED_1GB_FULL ?
+ "1 Gbps" : "unknown speed")),
+ ((FLOW_RX && FLOW_TX) ? "RX/TX" :
+ (FLOW_RX ? "RX" :
+ (FLOW_TX ? "TX" : "None"))));
netif_carrier_on(netdev);
netif_tx_wake_all_queues(netdev);
@@ -3224,7 +3484,8 @@ static void ixgbe_watchdog_task(struct work_struct *work)
adapter->link_up = false;
adapter->link_speed = 0;
if (netif_carrier_ok(netdev)) {
- DPRINTK(LINK, INFO, "NIC Link is Down\n");
+ printk(KERN_INFO "ixgbe: %s NIC Link is Down\n",
+ netdev->name);
netif_carrier_off(netdev);
netif_tx_stop_all_queues(netdev);
}
@@ -3573,6 +3834,14 @@ static int ixgbe_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
tx_flags |= vlan_tx_tag_get(skb);
+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+ tx_flags &= ~IXGBE_TX_FLAGS_VLAN_PRIO_MASK;
+ tx_flags |= (skb->queue_mapping << 13);
+ }
+ tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
+ tx_flags |= IXGBE_TX_FLAGS_VLAN;
+ } else if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
+ tx_flags |= (skb->queue_mapping << 13);
tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
tx_flags |= IXGBE_TX_FLAGS_VLAN;
}
@@ -3687,9 +3956,31 @@ static int ixgbe_link_config(struct ixgbe_hw *hw)
/* must always autoneg for both 1G and 10G link */
hw->mac.autoneg = true;
+ if ((hw->mac.type == ixgbe_mac_82598EB) &&
+ (hw->phy.media_type == ixgbe_media_type_copper))
+ autoneg = IXGBE_LINK_SPEED_82598_AUTONEG;
+
return hw->mac.ops.setup_link_speed(hw, autoneg, true, true);
}
+static const struct net_device_ops ixgbe_netdev_ops = {
+ .ndo_open = ixgbe_open,
+ .ndo_stop = ixgbe_close,
+ .ndo_start_xmit = ixgbe_xmit_frame,
+ .ndo_get_stats = ixgbe_get_stats,
+ .ndo_set_multicast_list = ixgbe_set_rx_mode,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = ixgbe_set_mac,
+ .ndo_change_mtu = ixgbe_change_mtu,
+ .ndo_tx_timeout = ixgbe_tx_timeout,
+ .ndo_vlan_rx_register = ixgbe_vlan_rx_register,
+ .ndo_vlan_rx_add_vid = ixgbe_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = ixgbe_vlan_rx_kill_vid,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = ixgbe_netpoll,
+#endif
+};
+
/**
* ixgbe_probe - Device Initialization Routine
* @pdev: PCI device information struct
@@ -3739,6 +4030,13 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
goto err_pci_reg;
}
+ err = pci_enable_pcie_error_reporting(pdev);
+ if (err) {
+ dev_err(&pdev->dev, "pci_enable_pcie_error_reporting failed "
+ "0x%x\n", err);
+ /* non-fatal, continue */
+ }
+
pci_set_master(pdev);
pci_save_state(pdev);
@@ -3771,23 +4069,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
continue;
}
- netdev->open = &ixgbe_open;
- netdev->stop = &ixgbe_close;
- netdev->hard_start_xmit = &ixgbe_xmit_frame;
- netdev->get_stats = &ixgbe_get_stats;
- netdev->set_rx_mode = &ixgbe_set_rx_mode;
- netdev->set_multicast_list = &ixgbe_set_rx_mode;
- netdev->set_mac_address = &ixgbe_set_mac;
- netdev->change_mtu = &ixgbe_change_mtu;
+ netdev->netdev_ops = &ixgbe_netdev_ops;
ixgbe_set_ethtool_ops(netdev);
- netdev->tx_timeout = &ixgbe_tx_timeout;
netdev->watchdog_timeo = 5 * HZ;
- netdev->vlan_rx_register = ixgbe_vlan_rx_register;
- netdev->vlan_rx_add_vid = ixgbe_vlan_rx_add_vid;
- netdev->vlan_rx_kill_vid = ixgbe_vlan_rx_kill_vid;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- netdev->poll_controller = ixgbe_netpoll;
-#endif
strcpy(netdev->name, pci_name(pdev));
adapter->bd_number = cards_found;
@@ -3805,11 +4089,31 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
/* PHY */
memcpy(&hw->phy.ops, ii->phy_ops, sizeof(hw->phy.ops));
- /* phy->sfp_type = ixgbe_sfp_type_unknown; */
+ hw->phy.sfp_type = ixgbe_sfp_type_unknown;
+
+ /* set up this timer and work struct before calling get_invariants
+ * which might start the timer
+ */
+ init_timer(&adapter->sfp_timer);
+ adapter->sfp_timer.function = &ixgbe_sfp_timer;
+ adapter->sfp_timer.data = (unsigned long) adapter;
+
+ INIT_WORK(&adapter->sfp_task, ixgbe_sfp_task);
err = ii->get_invariants(hw);
- if (err)
+ if (err == IXGBE_ERR_SFP_NOT_PRESENT) {
+ /* start a kernel thread to watch for a module to arrive */
+ set_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
+ mod_timer(&adapter->sfp_timer,
+ round_jiffies(jiffies + (2 * HZ)));
+ err = 0;
+ } else if (err == IXGBE_ERR_SFP_NOT_SUPPORTED) {
+ DPRINTK(PROBE, ERR, "failed to load because an "
+ "unsupported SFP+ module type was detected.\n");
goto err_hw_init;
+ } else if (err) {
+ goto err_hw_init;
+ }
/* setup the private structure */
err = ixgbe_sw_init(adapter);
@@ -3839,6 +4143,13 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
netdev->vlan_features |= NETIF_F_IP_CSUM;
netdev->vlan_features |= NETIF_F_SG;
+ if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
+ adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
+
+#ifdef CONFIG_IXGBE_DCB
+ netdev->dcbnl_ops = &dcbnl_ops;
+#endif
+
if (pci_using_dac)
netdev->features |= NETIF_F_HIGHDMA;
@@ -3873,8 +4184,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
pci_read_config_word(pdev, IXGBE_PCI_LINK_STATUS, &link_status);
link_speed = link_status & IXGBE_PCI_LINK_SPEED;
link_width = link_status & IXGBE_PCI_LINK_WIDTH;
- dev_info(&pdev->dev, "(PCI Express:%s:%s) "
- "%02x:%02x:%02x:%02x:%02x:%02x\n",
+ dev_info(&pdev->dev, "(PCI Express:%s:%s) %pM\n",
((link_speed == IXGBE_PCI_LINK_SPEED_5000) ? "5.0Gb/s" :
(link_speed == IXGBE_PCI_LINK_SPEED_2500) ? "2.5Gb/s" :
"Unknown"),
@@ -3883,8 +4193,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
(link_width == IXGBE_PCI_LINK_WIDTH_2) ? "Width x2" :
(link_width == IXGBE_PCI_LINK_WIDTH_1) ? "Width x1" :
"Unknown"),
- netdev->dev_addr[0], netdev->dev_addr[1], netdev->dev_addr[2],
- netdev->dev_addr[3], netdev->dev_addr[4], netdev->dev_addr[5]);
+ netdev->dev_addr);
ixgbe_read_pba_num_generic(hw, &part_num);
dev_info(&pdev->dev, "MAC: %d, PHY: %d, PBA No: %06x-%03x\n",
hw->mac.type, hw->phy.type,
@@ -3911,8 +4220,6 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
netif_carrier_off(netdev);
netif_tx_stop_all_queues(netdev);
- ixgbe_napi_add_all(adapter);
-
strcpy(netdev->name, "eth%d");
err = register_netdev(netdev);
if (err)
@@ -3938,6 +4245,9 @@ err_hw_init:
err_sw_init:
ixgbe_reset_interrupt_capability(adapter);
err_eeprom:
+ clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
+ del_timer_sync(&adapter->sfp_timer);
+ cancel_work_sync(&adapter->sfp_task);
iounmap(hw->hw_addr);
err_ioremap:
free_netdev(netdev);
@@ -3962,10 +4272,18 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ int err;
set_bit(__IXGBE_DOWN, &adapter->state);
+ /* clear the module not found bit to make sure the worker won't
+ * reschedule
+ */
+ clear_bit(__IXGBE_SFP_MODULE_NOT_FOUND, &adapter->state);
del_timer_sync(&adapter->watchdog_timer);
+ del_timer_sync(&adapter->sfp_timer);
+ cancel_work_sync(&adapter->watchdog_task);
+ cancel_work_sync(&adapter->sfp_task);
flush_scheduled_work();
#ifdef CONFIG_IXGBE_DCA
@@ -3976,7 +4294,8 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
}
#endif
- unregister_netdev(netdev);
+ if (netdev->reg_state == NETREG_REGISTERED)
+ unregister_netdev(netdev);
ixgbe_reset_interrupt_capability(adapter);
@@ -3986,12 +4305,16 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)
pci_release_regions(pdev);
DPRINTK(PROBE, INFO, "complete\n");
- ixgbe_napi_del_all(adapter);
kfree(adapter->tx_ring);
kfree(adapter->rx_ring);
free_netdev(netdev);
+ err = pci_disable_pcie_error_reporting(pdev);
+ if (err)
+ dev_err(&pdev->dev,
+ "pci_disable_pcie_error_reporting failed 0x%x\n", err);
+
pci_disable_device(pdev);
}
@@ -4007,7 +4330,7 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
pci_channel_state_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct ixgbe_adapter *adapter = netdev->priv;
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
netif_device_detach(netdev);
@@ -4028,22 +4351,34 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct ixgbe_adapter *adapter = netdev->priv;
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
+ pci_ers_result_t result;
+ int err;
if (pci_enable_device(pdev)) {
DPRINTK(PROBE, ERR,
"Cannot re-enable PCI device after reset.\n");
- return PCI_ERS_RESULT_DISCONNECT;
- }
- pci_set_master(pdev);
- pci_restore_state(pdev);
+ result = PCI_ERS_RESULT_DISCONNECT;
+ } else {
+ pci_set_master(pdev);
+ pci_restore_state(pdev);
- pci_enable_wake(pdev, PCI_D3hot, 0);
- pci_enable_wake(pdev, PCI_D3cold, 0);
+ pci_enable_wake(pdev, PCI_D3hot, 0);
+ pci_enable_wake(pdev, PCI_D3cold, 0);
- ixgbe_reset(adapter);
+ ixgbe_reset(adapter);
+
+ result = PCI_ERS_RESULT_RECOVERED;
+ }
- return PCI_ERS_RESULT_RECOVERED;
+ err = pci_cleanup_aer_uncorrect_error_status(pdev);
+ if (err) {
+ dev_err(&pdev->dev,
+ "pci_cleanup_aer_uncorrect_error_status failed 0x%0x\n", err);
+ /* non-fatal, continue */
+ }
+
+ return result;
}
/**
@@ -4056,7 +4391,7 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev)
static void ixgbe_io_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct ixgbe_adapter *adapter = netdev->priv;
+ struct ixgbe_adapter *adapter = netdev_priv(netdev);
if (netif_running(netdev)) {
if (ixgbe_up(adapter)) {
diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c
index 764035a8c9a1..5a8669aedf64 100644
--- a/drivers/net/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ixgbe/ixgbe_phy.c
@@ -121,9 +121,15 @@ static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id)
enum ixgbe_phy_type phy_type;
switch (phy_id) {
+ case TN1010_PHY_ID:
+ phy_type = ixgbe_phy_tn;
+ break;
case QT2022_PHY_ID:
phy_type = ixgbe_phy_qt;
break;
+ case ATH_PHY_ID:
+ phy_type = ixgbe_phy_nl;
+ break;
default:
phy_type = ixgbe_phy_unknown;
break;
@@ -426,3 +432,323 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
return 0;
}
+/**
+ * ixgbe_reset_phy_nl - Performs a PHY reset
+ * @hw: pointer to hardware structure
+ **/
+s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw)
+{
+ u16 phy_offset, control, eword, edata, block_crc;
+ bool end_data = false;
+ u16 list_offset, data_offset;
+ u16 phy_data = 0;
+ s32 ret_val = 0;
+ u32 i;
+
+ hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
+ IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data);
+
+ /* reset the PHY and poll for completion */
+ hw->phy.ops.write_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
+ IXGBE_MDIO_PHY_XS_DEV_TYPE,
+ (phy_data | IXGBE_MDIO_PHY_XS_RESET));
+
+ for (i = 0; i < 100; i++) {
+ hw->phy.ops.read_reg(hw, IXGBE_MDIO_PHY_XS_CONTROL,
+ IXGBE_MDIO_PHY_XS_DEV_TYPE, &phy_data);
+ if ((phy_data & IXGBE_MDIO_PHY_XS_RESET) == 0)
+ break;
+ msleep(10);
+ }
+
+ if ((phy_data & IXGBE_MDIO_PHY_XS_RESET) != 0) {
+ hw_dbg(hw, "PHY reset did not complete.\n");
+ ret_val = IXGBE_ERR_PHY;
+ goto out;
+ }
+
+ /* Get init offsets */
+ ret_val = ixgbe_get_sfp_init_sequence_offsets(hw, &list_offset,
+ &data_offset);
+ if (ret_val != 0)
+ goto out;
+
+ ret_val = hw->eeprom.ops.read(hw, data_offset, &block_crc);
+ data_offset++;
+ while (!end_data) {
+ /*
+ * Read control word from PHY init contents offset
+ */
+ ret_val = hw->eeprom.ops.read(hw, data_offset, &eword);
+ control = (eword & IXGBE_CONTROL_MASK_NL) >>
+ IXGBE_CONTROL_SHIFT_NL;
+ edata = eword & IXGBE_DATA_MASK_NL;
+ switch (control) {
+ case IXGBE_DELAY_NL:
+ data_offset++;
+ hw_dbg(hw, "DELAY: %d MS\n", edata);
+ msleep(edata);
+ break;
+ case IXGBE_DATA_NL:
+ hw_dbg(hw, "DATA: \n");
+ data_offset++;
+ hw->eeprom.ops.read(hw, data_offset++,
+ &phy_offset);
+ for (i = 0; i < edata; i++) {
+ hw->eeprom.ops.read(hw, data_offset, &eword);
+ hw->phy.ops.write_reg(hw, phy_offset,
+ IXGBE_TWINAX_DEV, eword);
+ hw_dbg(hw, "Wrote %4.4x to %4.4x\n", eword,
+ phy_offset);
+ data_offset++;
+ phy_offset++;
+ }
+ break;
+ case IXGBE_CONTROL_NL:
+ data_offset++;
+ hw_dbg(hw, "CONTROL: \n");
+ if (edata == IXGBE_CONTROL_EOL_NL) {
+ hw_dbg(hw, "EOL\n");
+ end_data = true;
+ } else if (edata == IXGBE_CONTROL_SOL_NL) {
+ hw_dbg(hw, "SOL\n");
+ } else {
+ hw_dbg(hw, "Bad control value\n");
+ ret_val = IXGBE_ERR_PHY;
+ goto out;
+ }
+ break;
+ default:
+ hw_dbg(hw, "Bad control type\n");
+ ret_val = IXGBE_ERR_PHY;
+ goto out;
+ }
+ }
+
+out:
+ return ret_val;
+}
+
+/**
+ * ixgbe_identify_sfp_module_generic - Identifies SFP module and assigns
+ * the PHY type.
+ * @hw: pointer to hardware structure
+ *
+ * Searches for and indentifies the SFP module. Assings appropriate PHY type.
+ **/
+s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
+{
+ s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
+ u32 vendor_oui = 0;
+ u8 identifier = 0;
+ u8 comp_codes_1g = 0;
+ u8 comp_codes_10g = 0;
+ u8 oui_bytes[4] = {0, 0, 0, 0};
+ u8 transmission_media = 0;
+
+ status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER,
+ &identifier);
+
+ if (status == IXGBE_ERR_SFP_NOT_PRESENT) {
+ hw->phy.sfp_type = ixgbe_sfp_type_not_present;
+ goto out;
+ }
+
+ if (identifier == IXGBE_SFF_IDENTIFIER_SFP) {
+ hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_1GBE_COMP_CODES,
+ &comp_codes_1g);
+ hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_10GBE_COMP_CODES,
+ &comp_codes_10g);
+ hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_TRANSMISSION_MEDIA,
+ &transmission_media);
+
+ /* ID Module
+ * =========
+ * 0 SFP_DA_CU
+ * 1 SFP_SR
+ * 2 SFP_LR
+ */
+ if (transmission_media & IXGBE_SFF_TWIN_AX_CAPABLE)
+ hw->phy.sfp_type = ixgbe_sfp_type_da_cu;
+ else if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
+ hw->phy.sfp_type = ixgbe_sfp_type_sr;
+ else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
+ hw->phy.sfp_type = ixgbe_sfp_type_lr;
+ else
+ hw->phy.sfp_type = ixgbe_sfp_type_unknown;
+
+ /* Determine PHY vendor */
+ if (hw->phy.type == ixgbe_phy_unknown) {
+ hw->phy.id = identifier;
+ hw->phy.ops.read_i2c_eeprom(hw,
+ IXGBE_SFF_VENDOR_OUI_BYTE0,
+ &oui_bytes[0]);
+ hw->phy.ops.read_i2c_eeprom(hw,
+ IXGBE_SFF_VENDOR_OUI_BYTE1,
+ &oui_bytes[1]);
+ hw->phy.ops.read_i2c_eeprom(hw,
+ IXGBE_SFF_VENDOR_OUI_BYTE2,
+ &oui_bytes[2]);
+
+ vendor_oui =
+ ((oui_bytes[0] << IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT) |
+ (oui_bytes[1] << IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT) |
+ (oui_bytes[2] << IXGBE_SFF_VENDOR_OUI_BYTE2_SHIFT));
+
+ switch (vendor_oui) {
+ case IXGBE_SFF_VENDOR_OUI_TYCO:
+ if (transmission_media &
+ IXGBE_SFF_TWIN_AX_CAPABLE)
+ hw->phy.type = ixgbe_phy_tw_tyco;
+ break;
+ case IXGBE_SFF_VENDOR_OUI_FTL:
+ hw->phy.type = ixgbe_phy_sfp_ftl;
+ break;
+ case IXGBE_SFF_VENDOR_OUI_AVAGO:
+ hw->phy.type = ixgbe_phy_sfp_avago;
+ break;
+ default:
+ if (transmission_media &
+ IXGBE_SFF_TWIN_AX_CAPABLE)
+ hw->phy.type = ixgbe_phy_tw_unknown;
+ else
+ hw->phy.type = ixgbe_phy_sfp_unknown;
+ break;
+ }
+ }
+ status = 0;
+ }
+
+out:
+ return status;
+}
+
+/**
+ * ixgbe_get_sfp_init_sequence_offsets - Checks the MAC's EEPROM to see
+ * if it supports a given SFP+ module type, if so it returns the offsets to the
+ * phy init sequence block.
+ * @hw: pointer to hardware structure
+ * @list_offset: offset to the SFP ID list
+ * @data_offset: offset to the SFP data block
+ **/
+s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
+ u16 *list_offset,
+ u16 *data_offset)
+{
+ u16 sfp_id;
+
+ if (hw->phy.sfp_type == ixgbe_sfp_type_unknown)
+ return IXGBE_ERR_SFP_NOT_SUPPORTED;
+
+ if (hw->phy.sfp_type == ixgbe_sfp_type_not_present)
+ return IXGBE_ERR_SFP_NOT_PRESENT;
+
+ if ((hw->device_id == IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM) &&
+ (hw->phy.sfp_type == ixgbe_sfp_type_da_cu))
+ return IXGBE_ERR_SFP_NOT_SUPPORTED;
+
+ /* Read offset to PHY init contents */
+ hw->eeprom.ops.read(hw, IXGBE_PHY_INIT_OFFSET_NL, list_offset);
+
+ if ((!*list_offset) || (*list_offset == 0xFFFF))
+ return IXGBE_ERR_PHY;
+
+ /* Shift offset to first ID word */
+ (*list_offset)++;
+
+ /*
+ * Find the matching SFP ID in the EEPROM
+ * and program the init sequence
+ */
+ hw->eeprom.ops.read(hw, *list_offset, &sfp_id);
+
+ while (sfp_id != IXGBE_PHY_INIT_END_NL) {
+ if (sfp_id == hw->phy.sfp_type) {
+ (*list_offset)++;
+ hw->eeprom.ops.read(hw, *list_offset, data_offset);
+ if ((!*data_offset) || (*data_offset == 0xFFFF)) {
+ hw_dbg(hw, "SFP+ module not supported\n");
+ return IXGBE_ERR_SFP_NOT_SUPPORTED;
+ } else {
+ break;
+ }
+ } else {
+ (*list_offset) += 2;
+ if (hw->eeprom.ops.read(hw, *list_offset, &sfp_id))
+ return IXGBE_ERR_PHY;
+ }
+ }
+
+ if (sfp_id == IXGBE_PHY_INIT_END_NL) {
+ hw_dbg(hw, "No matching SFP+ module found\n");
+ return IXGBE_ERR_SFP_NOT_SUPPORTED;
+ }
+
+ return 0;
+}
+
+/**
+ * ixgbe_check_phy_link_tnx - Determine link and speed status
+ * @hw: pointer to hardware structure
+ *
+ * Reads the VS1 register to determine if link is up and the current speed for
+ * the PHY.
+ **/
+s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
+ bool *link_up)
+{
+ s32 status = 0;
+ u32 time_out;
+ u32 max_time_out = 10;
+ u16 phy_link = 0;
+ u16 phy_speed = 0;
+ u16 phy_data = 0;
+
+ /* Initialize speed and link to default case */
+ *link_up = false;
+ *speed = IXGBE_LINK_SPEED_10GB_FULL;
+
+ /*
+ * Check current speed and link status of the PHY register.
+ * This is a vendor specific register and may have to
+ * be changed for other copper PHYs.
+ */
+ for (time_out = 0; time_out < max_time_out; time_out++) {
+ udelay(10);
+ status = hw->phy.ops.read_reg(hw,
+ IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS,
+ IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+ &phy_data);
+ phy_link = phy_data &
+ IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS;
+ phy_speed = phy_data &
+ IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS;
+ if (phy_link == IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS) {
+ *link_up = true;
+ if (phy_speed ==
+ IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS)
+ *speed = IXGBE_LINK_SPEED_1GB_FULL;
+ break;
+ }
+ }
+
+ return status;
+}
+
+/**
+ * ixgbe_get_phy_firmware_version_tnx - Gets the PHY Firmware Version
+ * @hw: pointer to hardware structure
+ * @firmware_version: pointer to the PHY Firmware Version
+ **/
+s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
+ u16 *firmware_version)
+{
+ s32 status = 0;
+
+ status = hw->phy.ops.read_reg(hw, TNX_FW_REV,
+ IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE,
+ firmware_version);
+
+ return status;
+}
+
diff --git a/drivers/net/ixgbe/ixgbe_phy.h b/drivers/net/ixgbe/ixgbe_phy.h
index 9bfe3f2b1d8f..43a97bc420f5 100644
--- a/drivers/net/ixgbe/ixgbe_phy.h
+++ b/drivers/net/ixgbe/ixgbe_phy.h
@@ -63,6 +63,18 @@
#define IXGBE_SFF_VENDOR_OUI_FTL 0x00906500
#define IXGBE_SFF_VENDOR_OUI_AVAGO 0x00176A00
+/* I2C SDA and SCL timing parameters for standard mode */
+#define IXGBE_I2C_T_HD_STA 4
+#define IXGBE_I2C_T_LOW 5
+#define IXGBE_I2C_T_HIGH 4
+#define IXGBE_I2C_T_SU_STA 5
+#define IXGBE_I2C_T_HD_DATA 5
+#define IXGBE_I2C_T_SU_DATA 1
+#define IXGBE_I2C_T_RISE 1
+#define IXGBE_I2C_T_FALL 1
+#define IXGBE_I2C_T_SU_STO 4
+#define IXGBE_I2C_T_BUF 5
+
s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw);
s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw);
@@ -77,4 +89,17 @@ s32 ixgbe_setup_phy_link_speed_generic(struct ixgbe_hw *hw,
bool autoneg,
bool autoneg_wait_to_complete);
+/* PHY specific */
+s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw,
+ ixgbe_link_speed *speed,
+ bool *link_up);
+s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
+ u16 *firmware_version);
+
+s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw);
+s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw);
+s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
+ u16 *list_offset,
+ u16 *data_offset);
+
#endif /* _IXGBE_PHY_H_ */
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h
index c6f8fa1c4e59..83a11ff9ffd1 100644
--- a/drivers/net/ixgbe/ixgbe_type.h
+++ b/drivers/net/ixgbe/ixgbe_type.h
@@ -36,8 +36,12 @@
/* Device IDs */
#define IXGBE_DEV_ID_82598AF_DUAL_PORT 0x10C6
#define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7
+#define IXGBE_DEV_ID_82598EB_SFP_LOM 0x10DB
+#define IXGBE_DEV_ID_82598AT 0x10C8
#define IXGBE_DEV_ID_82598EB_CX4 0x10DD
#define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC
+#define IXGBE_DEV_ID_82598_DA_DUAL_PORT 0x10F1
+#define IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM 0x10E1
#define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4
/* General Registers */
@@ -452,6 +456,7 @@
#define IXGBE_MDIO_PHY_XS_DEV_TYPE 0x4
#define IXGBE_MDIO_AUTO_NEG_DEV_TYPE 0x7
#define IXGBE_MDIO_VENDOR_SPECIFIC_1_DEV_TYPE 0x1E /* Device 30 */
+#define IXGBE_TWINAX_DEV 1
#define IXGBE_MDIO_COMMAND_TIMEOUT 100 /* PHY Timeout for 1 GB mode */
@@ -487,12 +492,27 @@
#define IXGBE_PHY_REVISION_MASK 0xFFFFFFF0
#define IXGBE_MAX_PHY_ADDR 32
-/* PHY IDs*/
+/* PHY IDs */
+#define TN1010_PHY_ID 0x00A19410
+#define TNX_FW_REV 0xB
#define QT2022_PHY_ID 0x0043A400
+#define ATH_PHY_ID 0x03429050
/* PHY Types */
#define IXGBE_M88E1145_E_PHY_ID 0x01410CD0
+/* Special PHY Init Routine */
+#define IXGBE_PHY_INIT_OFFSET_NL 0x002B
+#define IXGBE_PHY_INIT_END_NL 0xFFFF
+#define IXGBE_CONTROL_MASK_NL 0xF000
+#define IXGBE_DATA_MASK_NL 0x0FFF
+#define IXGBE_CONTROL_SHIFT_NL 12
+#define IXGBE_DELAY_NL 0
+#define IXGBE_DATA_NL 1
+#define IXGBE_CONTROL_NL 0x000F
+#define IXGBE_CONTROL_EOL_NL 0x0FFF
+#define IXGBE_CONTROL_SOL_NL 0x0000
+
/* General purpose Interrupt Enable */
#define IXGBE_SDP0_GPIEN 0x00000001 /* SDP0 */
#define IXGBE_SDP1_GPIEN 0x00000002 /* SDP1 */
@@ -1202,8 +1222,10 @@ enum ixgbe_mac_type {
enum ixgbe_phy_type {
ixgbe_phy_unknown = 0,
+ ixgbe_phy_tn,
ixgbe_phy_qt,
ixgbe_phy_xaui,
+ ixgbe_phy_nl,
ixgbe_phy_tw_tyco,
ixgbe_phy_tw_unknown,
ixgbe_phy_sfp_avago,
@@ -1225,6 +1247,7 @@ enum ixgbe_sfp_type {
ixgbe_sfp_type_da_cu = 0,
ixgbe_sfp_type_sr = 1,
ixgbe_sfp_type_lr = 2,
+ ixgbe_sfp_type_not_present = 0xFFFE,
ixgbe_sfp_type_unknown = 0xFFFF
};
@@ -1396,6 +1419,8 @@ struct ixgbe_phy_operations {
s32 (*setup_link)(struct ixgbe_hw *);
s32 (*setup_link_speed)(struct ixgbe_hw *, ixgbe_link_speed, bool,
bool);
+ s32 (*check_link)(struct ixgbe_hw *, ixgbe_link_speed *, bool *);
+ s32 (*get_firmware_version)(struct ixgbe_hw *, u16 *);
s32 (*read_i2c_byte)(struct ixgbe_hw *, u8, u8, u8 *);
s32 (*write_i2c_byte)(struct ixgbe_hw *, u8, u8, u8);
s32 (*read_i2c_eeprom)(struct ixgbe_hw *, u8 , u8 *);
@@ -1486,6 +1511,7 @@ struct ixgbe_info {
#define IXGBE_ERR_PHY_ADDR_INVALID -17
#define IXGBE_ERR_I2C -18
#define IXGBE_ERR_SFP_NOT_SUPPORTED -19
+#define IXGBE_ERR_SFP_NOT_PRESENT -20
#define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF
#endif /* _IXGBE_TYPE_H_ */
diff --git a/drivers/net/ixp2000/ixpdev.c b/drivers/net/ixp2000/ixpdev.c
index 7b70c66504a0..014745720560 100644
--- a/drivers/net/ixp2000/ixpdev.c
+++ b/drivers/net/ixp2000/ixpdev.c
@@ -114,8 +114,6 @@ static int ixpdev_rx(struct net_device *dev, int processed, int budget)
skb_put(skb, desc->pkt_length);
skb->protocol = eth_type_trans(skb, nds[desc->channel]);
- dev->last_rx = jiffies;
-
netif_receive_skb(skb);
}
@@ -143,7 +141,7 @@ static int ixpdev_poll(struct napi_struct *napi, int budget)
break;
} while (ixp2000_reg_read(IXP2000_IRQ_THD_RAW_STATUS_A_0) & 0x00ff);
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
ixp2000_reg_write(IXP2000_IRQ_THD_ENABLE_SET_A_0, 0x00ff);
return rx;
@@ -206,7 +204,7 @@ static irqreturn_t ixpdev_interrupt(int irq, void *dev_id)
ixp2000_reg_wrb(IXP2000_IRQ_THD_ENABLE_CLEAR_A_0, 0x00ff);
if (likely(napi_schedule_prep(&ip->napi))) {
- __netif_rx_schedule(dev, &ip->napi);
+ __netif_rx_schedule(&ip->napi);
} else {
printk(KERN_CRIT "ixp2000: irq while polling!!\n");
}
diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c
index 07944820f745..334ff9e12cdd 100644
--- a/drivers/net/jazzsonic.c
+++ b/drivers/net/jazzsonic.c
@@ -208,7 +208,6 @@ static int __init jazz_sonic_probe(struct platform_device *pdev)
struct sonic_local *lp;
struct resource *res;
int err = 0;
- DECLARE_MAC_BUF(mac);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
@@ -233,8 +232,7 @@ static int __init jazz_sonic_probe(struct platform_device *pdev)
if (err)
goto out1;
- printk("%s: MAC %s IRQ %d\n",
- dev->name, print_mac(mac, dev->dev_addr), dev->irq);
+ printk("%s: MAC %pM IRQ %d\n", dev->name, dev->dev_addr, dev->irq);
return 0;
diff --git a/drivers/net/jme.c b/drivers/net/jme.c
index 665e70d620fc..08b34051c646 100644
--- a/drivers/net/jme.c
+++ b/drivers/net/jme.c
@@ -435,15 +435,18 @@ jme_check_link(struct net_device *netdev, int testonly)
GHC_DPX);
switch (phylink & PHY_LINK_SPEED_MASK) {
case PHY_LINK_SPEED_10M:
- ghc |= GHC_SPEED_10M;
+ ghc |= GHC_SPEED_10M |
+ GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE;
strcat(linkmsg, "10 Mbps, ");
break;
case PHY_LINK_SPEED_100M:
- ghc |= GHC_SPEED_100M;
+ ghc |= GHC_SPEED_100M |
+ GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE;
strcat(linkmsg, "100 Mbps, ");
break;
case PHY_LINK_SPEED_1000M:
- ghc |= GHC_SPEED_1000M;
+ ghc |= GHC_SPEED_1000M |
+ GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY;
strcat(linkmsg, "1000 Mbps, ");
break;
default:
@@ -463,14 +466,6 @@ jme_check_link(struct net_device *netdev, int testonly)
TXTRHD_TXREN |
((8 << TXTRHD_TXRL_SHIFT) & TXTRHD_TXRL));
}
- strcat(linkmsg, (phylink & PHY_LINK_DUPLEX) ?
- "Full-Duplex, " :
- "Half-Duplex, ");
-
- if (phylink & PHY_LINK_MDI_STAT)
- strcat(linkmsg, "MDI-X");
- else
- strcat(linkmsg, "MDI");
gpreg1 = GPREG1_DEFAULT;
if (is_buggy250(jme->pdev->device, jme->chiprev)) {
@@ -492,11 +487,17 @@ jme_check_link(struct net_device *netdev, int testonly)
break;
}
}
- jwrite32(jme, JME_GPREG1, gpreg1);
- jme->reg_ghc = ghc;
+ jwrite32(jme, JME_GPREG1, gpreg1);
jwrite32(jme, JME_GHC, ghc);
+ jme->reg_ghc = ghc;
+ strcat(linkmsg, (phylink & PHY_LINK_DUPLEX) ?
+ "Full-Duplex, " :
+ "Half-Duplex, ");
+ strcat(linkmsg, (phylink & PHY_LINK_MDI_STAT) ?
+ "MDI-X" :
+ "MDI");
msg_link(jme, "Link is up at %s.\n", linkmsg);
netif_carrier_on(netdev);
} else {
@@ -931,7 +932,6 @@ jme_alloc_and_feed_skb(struct jme_adapter *jme, int idx)
cpu_to_le16(RXWBFLAG_DEST_MUL))
++(NET_STAT(jme).multicast);
- jme->dev->last_rx = jiffies;
NET_STAT(jme).rx_bytes += framesize;
++(NET_STAT(jme).rx_packets);
}
@@ -1250,7 +1250,6 @@ static int
jme_poll(JME_NAPI_HOLDER(holder), JME_NAPI_WEIGHT(budget))
{
struct jme_adapter *jme = jme_napi_priv(holder);
- struct net_device *netdev = jme->dev;
int rest;
rest = jme_process_receive(jme, JME_NAPI_WEIGHT_VAL(budget));
@@ -2591,14 +2590,6 @@ static const struct ethtool_ops jme_ethtool_ops = {
static int
jme_pci_dma64(struct pci_dev *pdev)
{
- if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK))
- if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
- return 1;
-
- if (!pci_set_dma_mask(pdev, DMA_40BIT_MASK))
- if (!pci_set_consistent_dma_mask(pdev, DMA_40BIT_MASK))
- return 1;
-
if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK))
if (!pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK))
return 0;
@@ -2626,6 +2617,18 @@ jme_check_hw_ver(struct jme_adapter *jme)
jme->chiprev = (chipmode & CM_CHIPREV_MASK) >> CM_CHIPREV_SHIFT;
}
+static const struct net_device_ops jme_netdev_ops = {
+ .ndo_open = jme_open,
+ .ndo_stop = jme_close,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_start_xmit = jme_start_xmit,
+ .ndo_set_mac_address = jme_set_macaddr,
+ .ndo_set_multicast_list = jme_set_multi,
+ .ndo_change_mtu = jme_change_mtu,
+ .ndo_tx_timeout = jme_tx_timeout,
+ .ndo_vlan_rx_register = jme_vlan_rx_register,
+};
+
static int __devinit
jme_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
@@ -2675,17 +2678,9 @@ jme_init_one(struct pci_dev *pdev,
rc = -ENOMEM;
goto err_out_release_regions;
}
- netdev->open = jme_open;
- netdev->stop = jme_close;
- netdev->hard_start_xmit = jme_start_xmit;
- netdev->set_mac_address = jme_set_macaddr;
- netdev->set_multicast_list = jme_set_multi;
- netdev->change_mtu = jme_change_mtu;
+ netdev->netdev_ops = &jme_netdev_ops;
netdev->ethtool_ops = &jme_ethtool_ops;
- netdev->tx_timeout = jme_tx_timeout;
netdev->watchdog_timeo = TX_TIMEOUT;
- netdev->vlan_rx_register = jme_vlan_rx_register;
- NETDEV_GET_STATS(netdev, &jme_get_stats);
netdev->features = NETIF_F_HW_CSUM |
NETIF_F_SG |
NETIF_F_TSO |
@@ -2861,18 +2856,10 @@ jme_init_one(struct pci_dev *pdev,
goto err_out_free_shadow;
}
- msg_probe(jme,
- "JMC250 gigabit%s ver:%x rev:%x "
- "macaddr:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ msg_probe(jme, "JMC250 gigabit%s ver:%x rev:%x macaddr:%pM\n",
(jme->fpgaver != 0) ? " (FPGA)" : "",
(jme->fpgaver != 0) ? jme->fpgaver : jme->chiprev,
- jme->rev,
- netdev->dev_addr[0],
- netdev->dev_addr[1],
- netdev->dev_addr[2],
- netdev->dev_addr[3],
- netdev->dev_addr[4],
- netdev->dev_addr[5]);
+ jme->rev, netdev->dev_addr);
return 0;
diff --git a/drivers/net/jme.h b/drivers/net/jme.h
index f863aee6648b..5154411b5e6b 100644
--- a/drivers/net/jme.h
+++ b/drivers/net/jme.h
@@ -22,7 +22,7 @@
*/
#ifndef __JME_H_INCLUDED__
-#define __JME_H_INCLUDEE__
+#define __JME_H_INCLUDED__
#define DRV_NAME "jme"
#define DRV_VERSION "1.0.3"
@@ -398,15 +398,15 @@ struct jme_ring {
#define JME_NAPI_WEIGHT(w) int w
#define JME_NAPI_WEIGHT_VAL(w) w
#define JME_NAPI_WEIGHT_SET(w, r)
-#define JME_RX_COMPLETE(dev, napis) netif_rx_complete(dev, napis)
+#define JME_RX_COMPLETE(dev, napis) netif_rx_complete(napis)
#define JME_NAPI_ENABLE(priv) napi_enable(&priv->napi);
#define JME_NAPI_DISABLE(priv) \
if (!napi_disable_pending(&priv->napi)) \
napi_disable(&priv->napi);
#define JME_RX_SCHEDULE_PREP(priv) \
- netif_rx_schedule_prep(priv->dev, &priv->napi)
+ netif_rx_schedule_prep(&priv->napi)
#define JME_RX_SCHEDULE(priv) \
- __netif_rx_schedule(priv->dev, &priv->napi);
+ __netif_rx_schedule(&priv->napi);
/*
* Jmac Adapter Private data
@@ -815,16 +815,30 @@ static inline u32 smi_phy_addr(int x)
* Global Host Control
*/
enum jme_ghc_bit_mask {
- GHC_SWRST = 0x40000000,
- GHC_DPX = 0x00000040,
- GHC_SPEED = 0x00000030,
- GHC_LINK_POLL = 0x00000001,
+ GHC_SWRST = 0x40000000,
+ GHC_DPX = 0x00000040,
+ GHC_SPEED = 0x00000030,
+ GHC_LINK_POLL = 0x00000001,
};
enum jme_ghc_speed_val {
- GHC_SPEED_10M = 0x00000010,
- GHC_SPEED_100M = 0x00000020,
- GHC_SPEED_1000M = 0x00000030,
+ GHC_SPEED_10M = 0x00000010,
+ GHC_SPEED_100M = 0x00000020,
+ GHC_SPEED_1000M = 0x00000030,
+};
+
+enum jme_ghc_to_clk {
+ GHC_TO_CLK_OFF = 0x00000000,
+ GHC_TO_CLK_GPHY = 0x00400000,
+ GHC_TO_CLK_PCIE = 0x00800000,
+ GHC_TO_CLK_INVALID = 0x00C00000,
+};
+
+enum jme_ghc_txmac_clk {
+ GHC_TXMAC_CLK_OFF = 0x00000000,
+ GHC_TXMAC_CLK_GPHY = 0x00100000,
+ GHC_TXMAC_CLK_PCIE = 0x00200000,
+ GHC_TXMAC_CLK_INVALID = 0x00300000,
};
/*
diff --git a/drivers/net/korina.c b/drivers/net/korina.c
index e18576316bda..4a5580c1126a 100644
--- a/drivers/net/korina.c
+++ b/drivers/net/korina.c
@@ -327,7 +327,7 @@ static irqreturn_t korina_rx_dma_interrupt(int irq, void *dev_id)
dmas = readl(&lp->rx_dma_regs->dmas);
if (dmas & (DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR)) {
- netif_rx_schedule_prep(dev, &lp->napi);
+ netif_rx_schedule_prep(&lp->napi);
dmasm = readl(&lp->rx_dma_regs->dmasm);
writel(dmasm | (DMA_STAT_DONE |
@@ -409,7 +409,6 @@ static int korina_rx(struct net_device *dev, int limit)
/* Pass the packet to upper layers */
netif_receive_skb(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
@@ -467,7 +466,7 @@ static int korina_poll(struct napi_struct *napi, int budget)
work_done = korina_rx(dev, budget);
if (work_done < budget) {
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
writel(readl(&lp->rx_dma_regs->dmasm) &
~(DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR),
diff --git a/drivers/net/lance.c b/drivers/net/lance.c
index 977ed3401bb3..d7afb938ea62 100644
--- a/drivers/net/lance.c
+++ b/drivers/net/lance.c
@@ -359,7 +359,7 @@ int __init init_module(void)
static void cleanup_card(struct net_device *dev)
{
- struct lance_private *lp = dev->priv;
+ struct lance_private *lp = dev->ml_priv;
if (dev->dma != 4)
free_dma(dev->dma);
release_region(dev->base_addr, LANCE_TOTAL_SIZE);
@@ -418,7 +418,7 @@ static int __init do_lance_probe(struct net_device *dev)
if (card < NUM_CARDS) { /*Signature OK*/
result = lance_probe1(dev, ioaddr, 0, 0);
if (!result) {
- struct lance_private *lp = dev->priv;
+ struct lance_private *lp = dev->ml_priv;
int ver = lp->chip_version;
r->name = chip_table[ver].name;
@@ -466,7 +466,6 @@ static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int
unsigned long flags;
int err = -ENOMEM;
void __iomem *bios;
- DECLARE_MAC_BUF(mac);
/* First we look for special cases.
Check for HP's on-board ethernet by looking for 'HP' in the BIOS.
@@ -520,7 +519,7 @@ static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int
}
}
- /* We can't allocate dev->priv from alloc_etherdev() because it must
+ /* We can't allocate private data from alloc_etherdev() because it must
a ISA DMA-able region. */
chipname = chip_table[lance_version].name;
printk("%s: %s at %#3x, ", dev->name, chipname, ioaddr);
@@ -529,7 +528,7 @@ static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int
The first six bytes are the station address. */
for (i = 0; i < 6; i++)
dev->dev_addr[i] = inb(ioaddr + i);
- printk("%s", print_mac(mac, dev->dev_addr));
+ printk("%pM", dev->dev_addr);
dev->base_addr = ioaddr;
/* Make certain the data structures used by the LANCE are aligned and DMAble. */
@@ -538,7 +537,7 @@ static int __init lance_probe1(struct net_device *dev, int ioaddr, int irq, int
if(lp==NULL)
return -ENODEV;
if (lance_debug > 6) printk(" (#0x%05lx)", (unsigned long)lp);
- dev->priv = lp;
+ dev->ml_priv = lp;
lp->name = chipname;
lp->rx_buffs = (unsigned long)kmalloc(PKT_BUF_SZ*RX_RING_SIZE,
GFP_DMA | GFP_KERNEL);
@@ -742,7 +741,7 @@ out_lp:
static int
lance_open(struct net_device *dev)
{
- struct lance_private *lp = dev->priv;
+ struct lance_private *lp = dev->ml_priv;
int ioaddr = dev->base_addr;
int i;
@@ -830,7 +829,7 @@ lance_open(struct net_device *dev)
static void
lance_purge_ring(struct net_device *dev)
{
- struct lance_private *lp = dev->priv;
+ struct lance_private *lp = dev->ml_priv;
int i;
/* Free all the skbuffs in the Rx and Tx queues. */
@@ -854,7 +853,7 @@ lance_purge_ring(struct net_device *dev)
static void
lance_init_ring(struct net_device *dev, gfp_t gfp)
{
- struct lance_private *lp = dev->priv;
+ struct lance_private *lp = dev->ml_priv;
int i;
lp->cur_rx = lp->cur_tx = 0;
@@ -896,7 +895,7 @@ lance_init_ring(struct net_device *dev, gfp_t gfp)
static void
lance_restart(struct net_device *dev, unsigned int csr0_bits, int must_reinit)
{
- struct lance_private *lp = dev->priv;
+ struct lance_private *lp = dev->ml_priv;
if (must_reinit ||
(chip_table[lp->chip_version].flags & LANCE_MUST_REINIT_RING)) {
@@ -910,7 +909,7 @@ lance_restart(struct net_device *dev, unsigned int csr0_bits, int must_reinit)
static void lance_tx_timeout (struct net_device *dev)
{
- struct lance_private *lp = (struct lance_private *) dev->priv;
+ struct lance_private *lp = (struct lance_private *) dev->ml_priv;
int ioaddr = dev->base_addr;
outw (0, ioaddr + LANCE_ADDR);
@@ -944,7 +943,7 @@ static void lance_tx_timeout (struct net_device *dev)
static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct lance_private *lp = dev->priv;
+ struct lance_private *lp = dev->ml_priv;
int ioaddr = dev->base_addr;
int entry;
unsigned long flags;
@@ -1021,7 +1020,7 @@ static irqreturn_t lance_interrupt(int irq, void *dev_id)
int must_restart;
ioaddr = dev->base_addr;
- lp = dev->priv;
+ lp = dev->ml_priv;
spin_lock (&lp->devlock);
@@ -1134,7 +1133,7 @@ static irqreturn_t lance_interrupt(int irq, void *dev_id)
static int
lance_rx(struct net_device *dev)
{
- struct lance_private *lp = dev->priv;
+ struct lance_private *lp = dev->ml_priv;
int entry = lp->cur_rx & RX_RING_MOD_MASK;
int i;
@@ -1191,7 +1190,6 @@ lance_rx(struct net_device *dev)
pkt_len);
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
- dev->last_rx = jiffies;
lp->stats.rx_packets++;
lp->stats.rx_bytes+=pkt_len;
}
@@ -1213,7 +1211,7 @@ static int
lance_close(struct net_device *dev)
{
int ioaddr = dev->base_addr;
- struct lance_private *lp = dev->priv;
+ struct lance_private *lp = dev->ml_priv;
netif_stop_queue (dev);
@@ -1246,7 +1244,7 @@ lance_close(struct net_device *dev)
static struct net_device_stats *lance_get_stats(struct net_device *dev)
{
- struct lance_private *lp = dev->priv;
+ struct lance_private *lp = dev->ml_priv;
if (chip_table[lp->chip_version].flags & LANCE_HAS_MISSED_FRAME) {
short ioaddr = dev->base_addr;
diff --git a/drivers/net/lib82596.c b/drivers/net/lib82596.c
index b59f442bbf36..7415f517491d 100644
--- a/drivers/net/lib82596.c
+++ b/drivers/net/lib82596.c
@@ -739,7 +739,6 @@ memory_squeeze:
skb->len = pkt_len;
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
}
@@ -1034,12 +1033,8 @@ static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
static void print_eth(unsigned char *add, char *str)
{
- DECLARE_MAC_BUF(mac);
- DECLARE_MAC_BUF(mac2);
-
- printk(KERN_DEBUG "i596 0x%p, %s --> %s %02X%02X, %s\n",
- add, print_mac(mac, add + 6), print_mac(mac2, add),
- add[12], add[13], str);
+ printk(KERN_DEBUG "i596 0x%p, %pM --> %pM %02X%02X, %s\n",
+ add, add + 6, add, add[12], add[13], str);
}
static int __devinit i82596_probe(struct net_device *dev)
@@ -1343,7 +1338,6 @@ static void set_multicast_list(struct net_device *dev)
struct i596_private *lp = netdev_priv(dev);
struct i596_dma *dma = lp->dma;
int config = 0, cnt;
- DECLARE_MAC_BUF(mac);
DEB(DEB_MULTI,
printk(KERN_DEBUG
@@ -1407,8 +1401,8 @@ static void set_multicast_list(struct net_device *dev)
if (i596_debug > 1)
DEB(DEB_MULTI,
printk(KERN_DEBUG
- "%s: Adding address %s\n",
- dev->name, print_mac(mac, cp)));
+ "%s: Adding address %pM\n",
+ dev->name, cp));
}
DMA_WBACK_INV(dev, &dma->mc_cmd, sizeof(struct mc_cmd));
i596_add_cmd(dev, &cmd->cmd);
diff --git a/drivers/net/lib8390.c b/drivers/net/lib8390.c
index f80dcc11fe26..789b6cb744b2 100644
--- a/drivers/net/lib8390.c
+++ b/drivers/net/lib8390.c
@@ -108,14 +108,13 @@ int ei_debug = 1;
/* Index to functions. */
static void ei_tx_intr(struct net_device *dev);
static void ei_tx_err(struct net_device *dev);
-static void ei_tx_timeout(struct net_device *dev);
+void ei_tx_timeout(struct net_device *dev);
static void ei_receive(struct net_device *dev);
static void ei_rx_overrun(struct net_device *dev);
/* Routines generic to NS8390-based boards. */
static void NS8390_trigger_send(struct net_device *dev, unsigned int length,
int start_page);
-static void set_multicast_list(struct net_device *dev);
static void do_set_multicast_list(struct net_device *dev);
static void __NS8390_init(struct net_device *dev, int startp);
@@ -206,10 +205,6 @@ static int __ei_open(struct net_device *dev)
unsigned long flags;
struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
- /* The card I/O part of the driver (e.g. 3c503) can hook a Tx timeout
- wrapper that does e.g. media check & then calls ei_tx_timeout. */
- if (dev->tx_timeout == NULL)
- dev->tx_timeout = ei_tx_timeout;
if (dev->watchdog_timeo <= 0)
dev->watchdog_timeo = TX_TIMEOUT;
@@ -258,7 +253,7 @@ static int __ei_close(struct net_device *dev)
* completed (or failed) - i.e. never posted a Tx related interrupt.
*/
-static void ei_tx_timeout(struct net_device *dev)
+static void __ei_tx_timeout(struct net_device *dev)
{
unsigned long e8390_base = dev->base_addr;
struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
@@ -304,7 +299,7 @@ static void ei_tx_timeout(struct net_device *dev)
* Sends a packet to an 8390 network device.
*/
-static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static int __ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned long e8390_base = dev->base_addr;
struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
@@ -764,7 +759,6 @@ static void ei_receive(struct net_device *dev)
ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
if (pkt_stat & ENRSR_PHY)
@@ -883,7 +877,7 @@ static void ei_rx_overrun(struct net_device *dev)
* Collect the stats. This is called unlocked and from several contexts.
*/
-static struct net_device_stats *get_stats(struct net_device *dev)
+static struct net_device_stats *__ei_get_stats(struct net_device *dev)
{
unsigned long ioaddr = dev->base_addr;
struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
@@ -992,7 +986,7 @@ static void do_set_multicast_list(struct net_device *dev)
* not called too often. Must protect against both bh and irq users
*/
-static void set_multicast_list(struct net_device *dev)
+static void __ei_set_multicast_list(struct net_device *dev)
{
unsigned long flags;
struct ei_device *ei_local = (struct ei_device*)netdev_priv(dev);
@@ -1016,10 +1010,6 @@ static void ethdev_setup(struct net_device *dev)
if (ei_debug > 1)
printk(version);
- dev->hard_start_xmit = &ei_start_xmit;
- dev->get_stats = get_stats;
- dev->set_multicast_list = &set_multicast_list;
-
ether_setup(dev);
spin_lock_init(&ei_local->page_lock);
diff --git a/drivers/net/lne390.c b/drivers/net/lne390.c
index b36989097883..41cbaaef0654 100644
--- a/drivers/net/lne390.c
+++ b/drivers/net/lne390.c
@@ -53,9 +53,6 @@ static const char *version =
static int lne390_probe1(struct net_device *dev, int ioaddr);
-static int lne390_open(struct net_device *dev);
-static int lne390_close(struct net_device *dev);
-
static void lne390_reset_8390(struct net_device *dev);
static void lne390_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page);
@@ -169,7 +166,6 @@ static int __init lne390_probe1(struct net_device *dev, int ioaddr)
{
int i, revision, ret;
unsigned long eisa_id;
- DECLARE_MAC_BUF(mac);
if (inb_p(ioaddr + LNE390_ID_PORT) == 0xff) return -ENODEV;
@@ -203,8 +199,8 @@ static int __init lne390_probe1(struct net_device *dev, int ioaddr)
for(i = 0; i < ETHER_ADDR_LEN; i++)
dev->dev_addr[i] = inb(ioaddr + LNE390_SA_PROM + i);
- printk("lne390.c: LNE390%X in EISA slot %d, address %s.\n",
- 0xa+revision, ioaddr/0x1000, print_mac(mac, dev->dev_addr));
+ printk("lne390.c: LNE390%X in EISA slot %d, address %pM.\n",
+ 0xa+revision, ioaddr/0x1000, dev->dev_addr);
printk("lne390.c: ");
@@ -279,11 +275,7 @@ static int __init lne390_probe1(struct net_device *dev, int ioaddr)
ei_status.block_output = &lne390_block_output;
ei_status.get_8390_hdr = &lne390_get_8390_hdr;
- dev->open = &lne390_open;
- dev->stop = &lne390_close;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = ei_poll;
-#endif
+ dev->netdev_ops = &ei_netdev_ops;
NS8390_init(dev, 0);
ret = register_netdev(dev);
@@ -375,21 +367,6 @@ static void lne390_block_output(struct net_device *dev, int count,
memcpy_toio(shmem, buf, count);
}
-static int lne390_open(struct net_device *dev)
-{
- ei_open(dev);
- return 0;
-}
-
-static int lne390_close(struct net_device *dev)
-{
-
- if (ei_debug > 1)
- printk("%s: Shutting down ethercard.\n", dev->name);
-
- ei_close(dev);
- return 0;
-}
#ifdef MODULE
#define MAX_LNE_CARDS 4 /* Max number of LNE390 cards per module */
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index b1ac63ab8c16..b7d438a367f3 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -76,8 +76,6 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
skb->protocol = eth_type_trans(skb,dev);
- dev->last_rx = jiffies;
-
/* it's OK to use per_cpu_ptr() because BHs are off */
pcpu_lstats = dev->ml_priv;
lb_stats = per_cpu_ptr(pcpu_lstats, smp_processor_id());
@@ -89,7 +87,7 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev)
return 0;
}
-static struct net_device_stats *get_stats(struct net_device *dev)
+static struct net_device_stats *loopback_get_stats(struct net_device *dev)
{
const struct pcpu_lstats *pcpu_lstats;
struct net_device_stats *stats = &dev->stats;
@@ -145,15 +143,19 @@ static void loopback_dev_free(struct net_device *dev)
free_netdev(dev);
}
+static const struct net_device_ops loopback_ops = {
+ .ndo_init = loopback_dev_init,
+ .ndo_start_xmit= loopback_xmit,
+ .ndo_get_stats = loopback_get_stats,
+};
+
/*
* The loopback device is special. There is only one instance
* per network namespace.
*/
static void loopback_setup(struct net_device *dev)
{
- dev->get_stats = &get_stats;
dev->mtu = (16 * 1024) + 20 + 20 + 12;
- dev->hard_start_xmit = loopback_xmit;
dev->hard_header_len = ETH_HLEN; /* 14 */
dev->addr_len = ETH_ALEN; /* 6 */
dev->tx_queue_len = 0;
@@ -167,8 +169,8 @@ static void loopback_setup(struct net_device *dev)
| NETIF_F_NETNS_LOCAL;
dev->ethtool_ops = &loopback_ethtool_ops;
dev->header_ops = &eth_header_ops;
- dev->init = loopback_dev_init;
- dev->destructor = loopback_dev_free;
+ dev->netdev_ops = &loopback_ops;
+ dev->destructor = loopback_dev_free;
}
/* Setup and register the loopback device. */
@@ -206,17 +208,8 @@ static __net_exit void loopback_net_exit(struct net *net)
unregister_netdev(dev);
}
-static struct pernet_operations __net_initdata loopback_net_ops = {
+/* Registered in net/core/dev.c */
+struct pernet_operations __net_initdata loopback_net_ops = {
.init = loopback_net_init,
.exit = loopback_net_exit,
};
-
-static int __init loopback_init(void)
-{
- return register_pernet_device(&loopback_net_ops);
-}
-
-/* Loopback is special. It should be initialized before any other network
- * device and network subsystem.
- */
-fs_initcall(loopback_init);
diff --git a/drivers/net/lp486e.c b/drivers/net/lp486e.c
index 83fa9d82a004..4d1a059921c6 100644
--- a/drivers/net/lp486e.c
+++ b/drivers/net/lp486e.c
@@ -390,7 +390,7 @@ i596_timeout(struct net_device *dev, char *msg, int ct) {
struct i596_private *lp;
int boguscnt = ct;
- lp = (struct i596_private *) dev->priv;
+ lp = netdev_priv(dev);
while (lp->scb.command) {
if (--boguscnt == 0) {
printk("%s: %s timed out - stat %4.4x, cmd %4.4x\n",
@@ -411,7 +411,7 @@ init_rx_bufs(struct net_device *dev, int num) {
int i;
// struct i596_rbd *rbd;
- lp = (struct i596_private *) dev->priv;
+ lp = netdev_priv(dev);
lp->scb.pa_rfd = I596_NULL;
for (i = 0; i < num; i++) {
@@ -468,7 +468,7 @@ remove_rx_bufs(struct net_device *dev) {
struct i596_private *lp;
struct i596_rfd *rfd;
- lp = (struct i596_private *) dev->priv;
+ lp = netdev_priv(dev);
lp->rx_tail->pa_next = I596_NULL;
do {
@@ -517,7 +517,7 @@ CLEAR_INT(void) {
/* selftest or dump */
static void
i596_port_do(struct net_device *dev, int portcmd, char *cmdname) {
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = netdev_priv(dev);
u16 *outp;
int i, m;
@@ -541,7 +541,7 @@ i596_port_do(struct net_device *dev, int portcmd, char *cmdname) {
static int
i596_scp_setup(struct net_device *dev) {
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = netdev_priv(dev);
int boguscnt;
/* Setup SCP, ISCP, SCB */
@@ -622,7 +622,7 @@ init_i596(struct net_device *dev) {
if (i596_scp_setup(dev))
return 1;
- lp = (struct i596_private *) dev->priv;
+ lp = netdev_priv(dev);
lp->scb.command = 0;
memcpy ((void *)lp->i596_config, init_setup, 14);
@@ -676,7 +676,6 @@ i596_rx_one(struct net_device *dev, struct i596_private *lp,
skb->protocol = eth_type_trans(skb,dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
} else {
#if 0
@@ -705,7 +704,7 @@ i596_rx_one(struct net_device *dev, struct i596_private *lp,
static int
i596_rx(struct net_device *dev) {
- struct i596_private *lp = (struct i596_private *) dev->priv;
+ struct i596_private *lp = netdev_priv(dev);
struct i596_rfd *rfd;
int frames = 0;
@@ -738,7 +737,7 @@ i596_cleanup_cmd(struct net_device *dev) {
struct i596_private *lp;
struct i596_cmd *cmd;
- lp = (struct i596_private *) dev->priv;
+ lp = netdev_priv(dev);
while (lp->cmd_head) {
cmd = (struct i596_cmd *)lp->cmd_head;
@@ -806,7 +805,7 @@ static void i596_reset(struct net_device *dev, struct i596_private *lp, int ioad
}
static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd) {
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = netdev_priv(dev);
int ioaddr = dev->base_addr;
unsigned long flags;
@@ -912,7 +911,7 @@ static int i596_start_xmit (struct sk_buff *skb, struct net_device *dev) {
static void
i596_tx_timeout (struct net_device *dev) {
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = netdev_priv(dev);
int ioaddr = dev->base_addr;
/* Transmitter timeout, serious problems. */
@@ -970,7 +969,7 @@ static int __init lp486e_probe(struct net_device *dev) {
return -EBUSY;
}
- lp = (struct i596_private *) dev->priv;
+ lp = netdev_priv(dev);
spin_lock_init(&lp->cmd_lock);
/*
@@ -1147,7 +1146,7 @@ static irqreturn_t
i596_interrupt(int irq, void *dev_instance)
{
struct net_device *dev = dev_instance;
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = netdev_priv(dev);
unsigned short status, ack_cmd = 0;
int frames_in = 0;
@@ -1215,7 +1214,7 @@ i596_interrupt(int irq, void *dev_instance)
}
static int i596_close(struct net_device *dev) {
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = netdev_priv(dev);
netif_stop_queue(dev);
@@ -1242,7 +1241,7 @@ static int i596_close(struct net_device *dev) {
*/
static void set_multicast_list(struct net_device *dev) {
- struct i596_private *lp = dev->priv;
+ struct i596_private *lp = netdev_priv(dev);
struct i596_cmd *cmd;
if (i596_debug > 1)
diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c
index 98e3eb2697c9..57716e22660c 100644
--- a/drivers/net/mac8390.c
+++ b/drivers/net/mac8390.c
@@ -304,7 +304,7 @@ struct net_device * __init mac8390_probe(int unit)
if (!MACH_IS_MAC)
return ERR_PTR(-ENODEV);
- dev = ____alloc_ei_netdev(0);
+ dev = alloc_ei_netdev();
if (!dev)
return ERR_PTR(-ENOMEM);
@@ -478,6 +478,20 @@ void cleanup_module(void)
#endif /* MODULE */
+static const struct net_device_ops mac8390_netdev_ops = {
+ .ndo_open = mac8390_open,
+ .ndo_stop = mac8390_close,
+ .ndo_start_xmit = ei_start_xmit,
+ .ndo_tx_timeout = ei_tx_timeout,
+ .ndo_get_stats = ei_get_stats,
+ .ndo_set_multicast_list = ei_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = ei_poll,
+#endif
+};
+
static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * ndev,
enum mac8390_type type)
{
@@ -503,11 +517,7 @@ static int __init mac8390_initdev(struct net_device * dev, struct nubus_dev * nd
int access_bitmode = 0;
/* Now fill in our stuff */
- dev->open = &mac8390_open;
- dev->stop = &mac8390_close;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = __ei_poll;
-#endif
+ dev->netdev_ops = &mac8390_netdev_ops;
/* GAR, ei_status is actually a macro even though it looks global */
ei_status.name = cardname[type];
diff --git a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c
index 4ce8afd481c3..380a1a54d530 100644
--- a/drivers/net/mac89x0.c
+++ b/drivers/net/mac89x0.c
@@ -181,7 +181,6 @@ struct net_device * __init mac89x0_probe(int unit)
unsigned long ioaddr;
unsigned short sig;
int err = -ENODEV;
- DECLARE_MAC_BUF(mac);
if (!MACH_IS_MAC)
return ERR_PTR(-ENODEV);
@@ -279,8 +278,7 @@ struct net_device * __init mac89x0_probe(int unit)
/* print the IRQ and ethernet address. */
- printk(" IRQ %d ADDR %s\n",
- dev->irq, print_mac(mac, dev->dev_addr));
+ printk(" IRQ %d ADDR %pM\n", dev->irq, dev->dev_addr);
dev->open = net_open;
dev->stop = net_close;
@@ -518,7 +516,6 @@ net_rx(struct net_device *dev)
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
- dev->last_rx = jiffies;
lp->stats.rx_packets++;
lp->stats.rx_bytes += length;
}
@@ -628,14 +625,3 @@ cleanup_module(void)
free_netdev(dev_cs89x0);
}
#endif /* MODULE */
-
-/*
- * Local variables:
- * compile-command: "m68k-linux-gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -c -o mac89x0.o mac89x0.c"
- * version-control: t
- * kept-new-versions: 5
- * c-indent-level: 8
- * tab-width: 8
- * End:
- *
- */
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 01f7a31bac76..a04da4ecaa88 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -435,7 +435,6 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag,
bp->stats.rx_packets++;
bp->stats.rx_bytes += len;
- bp->dev->last_rx = jiffies;
dev_dbg(&bp->pdev->dev, "received skb of length %u, csum: %08x\n",
skb->len, skb->csum);
netif_receive_skb(skb);
@@ -520,7 +519,7 @@ static int macb_poll(struct napi_struct *napi, int budget)
* this function was called last time, and no packets
* have been received since.
*/
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
goto out;
}
@@ -531,13 +530,13 @@ static int macb_poll(struct napi_struct *napi, int budget)
dev_warn(&bp->pdev->dev,
"No RX buffers complete, status = %02lx\n",
(unsigned long)status);
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
goto out;
}
work_done = macb_rx(bp, budget);
if (work_done < budget)
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
/*
* We've done what we can to clean the buffers. Make sure we
@@ -572,7 +571,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
}
if (status & MACB_RX_INT_FLAGS) {
- if (netif_rx_schedule_prep(dev, &bp->napi)) {
+ if (netif_rx_schedule_prep(&bp->napi)) {
/*
* There's no point taking any more interrupts
* until we have processed the buffers
@@ -580,7 +579,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
macb_writel(bp, IDR, MACB_RX_INT_FLAGS);
dev_dbg(&bp->pdev->dev,
"scheduling RX softirq\n");
- __netif_rx_schedule(dev, &bp->napi);
+ __netif_rx_schedule(&bp->napi);
}
}
@@ -1104,7 +1103,6 @@ static int __init macb_probe(struct platform_device *pdev)
unsigned long pclk_hz;
u32 config;
int err = -ENXIO;
- DECLARE_MAC_BUF(mac);
regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!regs) {
@@ -1223,10 +1221,8 @@ static int __init macb_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dev);
- printk(KERN_INFO "%s: Atmel MACB at 0x%08lx irq %d "
- "(%s)\n",
- dev->name, dev->base_addr, dev->irq,
- print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "%s: Atmel MACB at 0x%08lx irq %d (%pM)\n",
+ dev->name, dev->base_addr, dev->irq, dev->dev_addr);
phydev = bp->phy_dev;
printk(KERN_INFO "%s: attached PHY driver [%s] "
diff --git a/drivers/net/mace.c b/drivers/net/mace.c
index 451acdca2a21..feebbd92aff2 100644
--- a/drivers/net/mace.c
+++ b/drivers/net/mace.c
@@ -101,7 +101,6 @@ static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_i
struct mace_data *mp;
const unsigned char *addr;
int j, rev, rc = -EBUSY;
- DECLARE_MAC_BUF(mac);
if (macio_resource_count(mdev) != 3 || macio_irq_count(mdev) != 3) {
printk(KERN_ERR "can't use MACE %s: need 3 addrs and 3 irqs\n",
@@ -144,7 +143,7 @@ static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_i
}
SET_NETDEV_DEV(dev, &mdev->ofdev.dev);
- mp = dev->priv;
+ mp = netdev_priv(dev);
mp->mdev = mdev;
macio_set_drvdata(mdev, dev);
@@ -165,7 +164,7 @@ static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_i
in_8(&mp->mace->chipid_lo);
- mp = (struct mace_data *) dev->priv;
+ mp = netdev_priv(dev);
mp->maccc = ENXMT | ENRCV;
mp->tx_dma = ioremap(macio_resource_start(mdev, 1), 0x1000);
@@ -241,8 +240,8 @@ static int __devinit mace_probe(struct macio_dev *mdev, const struct of_device_i
goto err_free_rx_irq;
}
- printk(KERN_INFO "%s: MACE at %s, chip revision %d.%d\n",
- dev->name, print_mac(mac, dev->dev_addr),
+ printk(KERN_INFO "%s: MACE at %pM, chip revision %d.%d\n",
+ dev->name, dev->dev_addr,
mp->chipid >> 8, mp->chipid & 0xff);
return 0;
@@ -276,7 +275,7 @@ static int __devexit mace_remove(struct macio_dev *mdev)
macio_set_drvdata(mdev, NULL);
- mp = dev->priv;
+ mp = netdev_priv(dev);
unregister_netdev(dev);
@@ -312,7 +311,7 @@ static void dbdma_reset(volatile struct dbdma_regs __iomem *dma)
static void mace_reset(struct net_device *dev)
{
- struct mace_data *mp = (struct mace_data *) dev->priv;
+ struct mace_data *mp = netdev_priv(dev);
volatile struct mace __iomem *mb = mp->mace;
int i;
@@ -367,7 +366,7 @@ static void mace_reset(struct net_device *dev)
static void __mace_set_address(struct net_device *dev, void *addr)
{
- struct mace_data *mp = (struct mace_data *) dev->priv;
+ struct mace_data *mp = netdev_priv(dev);
volatile struct mace __iomem *mb = mp->mace;
unsigned char *p = addr;
int i;
@@ -388,7 +387,7 @@ static void __mace_set_address(struct net_device *dev, void *addr)
static int mace_set_address(struct net_device *dev, void *addr)
{
- struct mace_data *mp = (struct mace_data *) dev->priv;
+ struct mace_data *mp = netdev_priv(dev);
volatile struct mace __iomem *mb = mp->mace;
unsigned long flags;
@@ -423,7 +422,7 @@ static inline void mace_clean_rings(struct mace_data *mp)
static int mace_open(struct net_device *dev)
{
- struct mace_data *mp = (struct mace_data *) dev->priv;
+ struct mace_data *mp = netdev_priv(dev);
volatile struct mace __iomem *mb = mp->mace;
volatile struct dbdma_regs __iomem *rd = mp->rx_dma;
volatile struct dbdma_regs __iomem *td = mp->tx_dma;
@@ -493,7 +492,7 @@ static int mace_open(struct net_device *dev)
static int mace_close(struct net_device *dev)
{
- struct mace_data *mp = (struct mace_data *) dev->priv;
+ struct mace_data *mp = netdev_priv(dev);
volatile struct mace __iomem *mb = mp->mace;
volatile struct dbdma_regs __iomem *rd = mp->rx_dma;
volatile struct dbdma_regs __iomem *td = mp->tx_dma;
@@ -513,7 +512,7 @@ static int mace_close(struct net_device *dev)
static inline void mace_set_timeout(struct net_device *dev)
{
- struct mace_data *mp = (struct mace_data *) dev->priv;
+ struct mace_data *mp = netdev_priv(dev);
if (mp->timeout_active)
del_timer(&mp->tx_timeout);
@@ -526,7 +525,7 @@ static inline void mace_set_timeout(struct net_device *dev)
static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
{
- struct mace_data *mp = (struct mace_data *) dev->priv;
+ struct mace_data *mp = netdev_priv(dev);
volatile struct dbdma_regs __iomem *td = mp->tx_dma;
volatile struct dbdma_cmd *cp, *np;
unsigned long flags;
@@ -581,7 +580,7 @@ static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
static void mace_set_multicast(struct net_device *dev)
{
- struct mace_data *mp = (struct mace_data *) dev->priv;
+ struct mace_data *mp = netdev_priv(dev);
volatile struct mace __iomem *mb = mp->mace;
int i, j;
u32 crc;
@@ -656,7 +655,7 @@ static void mace_handle_misc_intrs(struct mace_data *mp, int intr, struct net_de
static irqreturn_t mace_interrupt(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *) dev_id;
- struct mace_data *mp = (struct mace_data *) dev->priv;
+ struct mace_data *mp = netdev_priv(dev);
volatile struct mace __iomem *mb = mp->mace;
volatile struct dbdma_regs __iomem *td = mp->tx_dma;
volatile struct dbdma_cmd *cp;
@@ -802,7 +801,7 @@ static irqreturn_t mace_interrupt(int irq, void *dev_id)
static void mace_tx_timeout(unsigned long data)
{
struct net_device *dev = (struct net_device *) data;
- struct mace_data *mp = (struct mace_data *) dev->priv;
+ struct mace_data *mp = netdev_priv(dev);
volatile struct mace __iomem *mb = mp->mace;
volatile struct dbdma_regs __iomem *td = mp->tx_dma;
volatile struct dbdma_regs __iomem *rd = mp->rx_dma;
@@ -873,7 +872,7 @@ static irqreturn_t mace_txdma_intr(int irq, void *dev_id)
static irqreturn_t mace_rxdma_intr(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *) dev_id;
- struct mace_data *mp = (struct mace_data *) dev->priv;
+ struct mace_data *mp = netdev_priv(dev);
volatile struct dbdma_regs __iomem *rd = mp->rx_dma;
volatile struct dbdma_cmd *cp, *np;
int i, nb, stat, next;
@@ -929,7 +928,6 @@ static irqreturn_t mace_rxdma_intr(int irq, void *dev_id)
skb->protocol = eth_type_trans(skb, dev);
dev->stats.rx_bytes += skb->len;
netif_rx(skb);
- dev->last_rx = jiffies;
mp->rx_bufs[i] = NULL;
++dev->stats.rx_packets;
}
diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c
index 85587a6667b9..274e99bb63ac 100644
--- a/drivers/net/macmace.c
+++ b/drivers/net/macmace.c
@@ -194,7 +194,6 @@ static int __devinit mace_probe(struct platform_device *pdev)
unsigned char checksum = 0;
static int found = 0;
int err;
- DECLARE_MAC_BUF(mac);
if (found || macintosh_config->ether_type != MAC_ETHER_MACE)
return -ENODEV;
@@ -249,8 +248,8 @@ static int __devinit mace_probe(struct platform_device *pdev)
dev->set_multicast_list = mace_set_multicast;
dev->set_mac_address = mace_set_address;
- printk(KERN_INFO "%s: 68K MACE, hardware address %s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "%s: 68K MACE, hardware address %pM\n",
+ dev->name, dev->dev_addr);
err = register_netdev(dev);
if (!err)
@@ -674,7 +673,6 @@ static void mace_dma_rx_frame(struct net_device *dev, struct mace_frame *mf)
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += frame_length;
}
diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c
index e64c2086d33c..205bb05c25d6 100644
--- a/drivers/net/macsonic.c
+++ b/drivers/net/macsonic.c
@@ -220,7 +220,6 @@ static int __init mac_onboard_sonic_ethernet_addr(struct net_device *dev)
struct sonic_local *lp = netdev_priv(dev);
const int prom_addr = ONBOARD_SONIC_PROM_BASE;
int i;
- DECLARE_MAC_BUF(mac);
/* On NuBus boards we can sometimes look in the ROM resources.
No such luck for comm-slot/onboard. */
@@ -264,8 +263,8 @@ static int __init mac_onboard_sonic_ethernet_addr(struct net_device *dev)
dev->dev_addr[1] = val >> 8;
dev->dev_addr[0] = val & 0xff;
- printk(KERN_INFO "HW Address from CAM 15: %s\n",
- print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "HW Address from CAM 15: %pM\n",
+ dev->dev_addr);
} else return 0;
if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
@@ -560,7 +559,6 @@ static int __init mac_sonic_probe(struct platform_device *pdev)
struct net_device *dev;
struct sonic_local *lp;
int err;
- DECLARE_MAC_BUF(mac);
dev = alloc_etherdev(sizeof(struct sonic_local));
if (!dev)
@@ -584,8 +582,7 @@ found:
if (err)
goto out;
- printk("%s: MAC %s IRQ %d\n",
- dev->name, print_mac(mac, dev->dev_addr), dev->irq);
+ printk("%s: MAC %pM IRQ %d\n", dev->name, dev->dev_addr, dev->irq);
return 0;
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 590039cbb146..7e24b5048686 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -87,7 +87,6 @@ static void macvlan_broadcast(struct sk_buff *skb,
dev->stats.rx_bytes += skb->len + ETH_HLEN;
dev->stats.rx_packets++;
dev->stats.multicast++;
- dev->last_rx = jiffies;
nskb->dev = dev;
if (!compare_ether_addr(eth->h_dest, dev->broadcast))
@@ -136,7 +135,6 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
dev->stats.rx_bytes += skb->len + ETH_HLEN;
dev->stats.rx_packets++;
- dev->last_rx = jiffies;
skb->dev = dev;
skb->pkt_type = PACKET_HOST;
@@ -145,7 +143,7 @@ static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
return NULL;
}
-static int macvlan_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static int macvlan_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
const struct macvlan_dev *vlan = netdev_priv(dev);
unsigned int len = skb->len;
@@ -336,24 +334,53 @@ static u32 macvlan_ethtool_get_rx_csum(struct net_device *dev)
return lowerdev->ethtool_ops->get_rx_csum(lowerdev);
}
+static int macvlan_ethtool_get_settings(struct net_device *dev,
+ struct ethtool_cmd *cmd)
+{
+ const struct macvlan_dev *vlan = netdev_priv(dev);
+ struct net_device *lowerdev = vlan->lowerdev;
+
+ if (!lowerdev->ethtool_ops->get_settings)
+ return -EOPNOTSUPP;
+
+ return lowerdev->ethtool_ops->get_settings(lowerdev, cmd);
+}
+
+static u32 macvlan_ethtool_get_flags(struct net_device *dev)
+{
+ const struct macvlan_dev *vlan = netdev_priv(dev);
+ struct net_device *lowerdev = vlan->lowerdev;
+
+ if (!lowerdev->ethtool_ops->get_flags)
+ return 0;
+ return lowerdev->ethtool_ops->get_flags(lowerdev);
+}
+
static const struct ethtool_ops macvlan_ethtool_ops = {
.get_link = ethtool_op_get_link,
+ .get_settings = macvlan_ethtool_get_settings,
.get_rx_csum = macvlan_ethtool_get_rx_csum,
.get_drvinfo = macvlan_ethtool_get_drvinfo,
+ .get_flags = macvlan_ethtool_get_flags,
+};
+
+static const struct net_device_ops macvlan_netdev_ops = {
+ .ndo_init = macvlan_init,
+ .ndo_open = macvlan_open,
+ .ndo_stop = macvlan_stop,
+ .ndo_start_xmit = macvlan_start_xmit,
+ .ndo_change_mtu = macvlan_change_mtu,
+ .ndo_change_rx_flags = macvlan_change_rx_flags,
+ .ndo_set_mac_address = macvlan_set_mac_address,
+ .ndo_set_multicast_list = macvlan_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
};
static void macvlan_setup(struct net_device *dev)
{
ether_setup(dev);
- dev->init = macvlan_init;
- dev->open = macvlan_open;
- dev->stop = macvlan_stop;
- dev->change_mtu = macvlan_change_mtu;
- dev->change_rx_flags = macvlan_change_rx_flags;
- dev->set_mac_address = macvlan_set_mac_address;
- dev->set_multicast_list = macvlan_set_multicast_list;
- dev->hard_start_xmit = macvlan_hard_start_xmit;
+ dev->netdev_ops = &macvlan_netdev_ops;
dev->destructor = free_netdev;
dev->header_ops = &macvlan_hard_header_ops,
dev->ethtool_ops = &macvlan_ethtool_ops;
diff --git a/drivers/net/meth.c b/drivers/net/meth.c
index a1e22ed1f6ee..c336a1f42510 100644
--- a/drivers/net/meth.c
+++ b/drivers/net/meth.c
@@ -94,10 +94,9 @@ char o2meth_eaddr[8]={0,0,0,0,0,0,0,0};
static inline void load_eaddr(struct net_device *dev)
{
int i;
- DECLARE_MAC_BUF(mac);
u64 macaddr;
- DPRINTK("Loading MAC Address: %s\n", print_mac(mac, dev->dev_addr));
+ DPRINTK("Loading MAC Address: %pM\n", dev->dev_addr);
macaddr = 0;
for (i = 0; i < 6; i++)
macaddr |= (u64)dev->dev_addr[i] << ((5 - i) * 8);
@@ -421,7 +420,6 @@ static void meth_rx(struct net_device* dev, unsigned long int_status)
skb_put(skb_c, len);
priv->rx_skbs[priv->rx_write] = skb;
skb_c->protocol = eth_type_trans(skb_c, dev);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
netif_rx(skb_c);
diff --git a/drivers/net/mlx4/cq.c b/drivers/net/mlx4/cq.c
index b7ad2829d67e..ac57b6a42c6e 100644
--- a/drivers/net/mlx4/cq.c
+++ b/drivers/net/mlx4/cq.c
@@ -189,7 +189,7 @@ EXPORT_SYMBOL_GPL(mlx4_cq_resize);
int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
struct mlx4_uar *uar, u64 db_rec, struct mlx4_cq *cq,
- int collapsed)
+ unsigned vector, int collapsed)
{
struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_cq_table *cq_table = &priv->cq_table;
@@ -198,6 +198,11 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
u64 mtt_addr;
int err;
+ if (vector >= dev->caps.num_comp_vectors)
+ return -EINVAL;
+
+ cq->vector = vector;
+
cq->cqn = mlx4_bitmap_alloc(&cq_table->bitmap);
if (cq->cqn == -1)
return -ENOMEM;
@@ -227,7 +232,7 @@ int mlx4_cq_alloc(struct mlx4_dev *dev, int nent, struct mlx4_mtt *mtt,
cq_context->flags = cpu_to_be32(!!collapsed << 18);
cq_context->logsize_usrpage = cpu_to_be32((ilog2(nent) << 24) | uar->index);
- cq_context->comp_eqn = priv->eq_table.eq[MLX4_EQ_COMP].eqn;
+ cq_context->comp_eqn = priv->eq_table.eq[vector].eqn;
cq_context->log_page_size = mtt->page_shift - MLX4_ICM_PAGE_SHIFT;
mtt_addr = mlx4_mtt_addr(dev, mtt);
@@ -276,7 +281,7 @@ void mlx4_cq_free(struct mlx4_dev *dev, struct mlx4_cq *cq)
if (err)
mlx4_warn(dev, "HW2SW_CQ failed (%d) for CQN %06x\n", err, cq->cqn);
- synchronize_irq(priv->eq_table.eq[MLX4_EQ_COMP].irq);
+ synchronize_irq(priv->eq_table.eq[cq->vector].irq);
spin_lock_irq(&cq_table->lock);
radix_tree_delete(&cq_table->tree, cq->cqn);
diff --git a/drivers/net/mlx4/en_cq.c b/drivers/net/mlx4/en_cq.c
index 1368a8010af4..91f50de84be9 100644
--- a/drivers/net/mlx4/en_cq.c
+++ b/drivers/net/mlx4/en_cq.c
@@ -51,10 +51,13 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv,
int err;
cq->size = entries;
- if (mode == RX)
+ if (mode == RX) {
cq->buf_size = cq->size * sizeof(struct mlx4_cqe);
- else
+ cq->vector = ring % mdev->dev->caps.num_comp_vectors;
+ } else {
cq->buf_size = sizeof(struct mlx4_cqe);
+ cq->vector = 0;
+ }
cq->ring = ring;
cq->is_tx = mode;
@@ -68,6 +71,8 @@ int mlx4_en_create_cq(struct mlx4_en_priv *priv,
err = mlx4_en_map_buffer(&cq->wqres.buf);
if (err)
mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size);
+ else
+ cq->buf = (struct mlx4_cqe *) cq->wqres.buf.direct.buf;
return err;
}
@@ -82,11 +87,10 @@ int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
cq->mcq.arm_db = cq->wqres.db.db + 1;
*cq->mcq.set_ci_db = 0;
*cq->mcq.arm_db = 0;
- cq->buf = (struct mlx4_cqe *) cq->wqres.buf.direct.buf;
memset(cq->buf, 0, cq->buf_size);
err = mlx4_cq_alloc(mdev->dev, cq->size, &cq->wqres.mtt, &mdev->priv_uar,
- cq->wqres.db.dma, &cq->mcq, cq->is_tx);
+ cq->wqres.db.dma, &cq->mcq, cq->vector, cq->is_tx);
if (err)
return err;
@@ -136,7 +140,6 @@ 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)
{
- cq->armed = 1;
mlx4_cq_arm(&cq->mcq, MLX4_CQ_DB_REQ_NOT, priv->mdev->uar_map,
&priv->mdev->uar_lock);
diff --git a/drivers/net/mlx4/en_main.c b/drivers/net/mlx4/en_main.c
index 4b9794e97a79..c1c05852a95e 100644
--- a/drivers/net/mlx4/en_main.c
+++ b/drivers/net/mlx4/en_main.c
@@ -170,9 +170,9 @@ static void *mlx4_en_add(struct mlx4_dev *dev)
mlx4_info(mdev, "Using %d tx rings for port:%d\n",
mdev->profile.prof[i].tx_ring_num, i);
if (!mdev->profile.prof[i].rx_ring_num) {
- mdev->profile.prof[i].rx_ring_num = 1;
+ mdev->profile.prof[i].rx_ring_num = dev->caps.num_comp_vectors;
mlx4_info(mdev, "Defaulting to %d rx rings for port:%d\n",
- 1, i);
+ mdev->profile.prof[i].rx_ring_num, i);
} else
mlx4_info(mdev, "Using %d rx rings for port:%d\n",
mdev->profile.prof[i].rx_ring_num, i);
diff --git a/drivers/net/mlx4/en_netdev.c b/drivers/net/mlx4/en_netdev.c
index 96e709d6440a..ebada3c7aff2 100644
--- a/drivers/net/mlx4/en_netdev.c
+++ b/drivers/net/mlx4/en_netdev.c
@@ -369,7 +369,6 @@ static struct net_device_stats *mlx4_en_get_stats(struct net_device *dev)
static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
{
- struct mlx4_en_dev *mdev = priv->mdev;
struct mlx4_en_cq *cq;
int i;
@@ -379,15 +378,8 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
* satisfy our coelsing target.
* - moder_time is set to a fixed value.
*/
- priv->rx_frames = (mdev->profile.rx_moder_cnt ==
- MLX4_EN_AUTO_CONF) ?
- MLX4_EN_RX_COAL_TARGET /
- priv->dev->mtu + 1 :
- mdev->profile.rx_moder_cnt;
- priv->rx_usecs = (mdev->profile.rx_moder_time ==
- MLX4_EN_AUTO_CONF) ?
- MLX4_EN_RX_COAL_TIME :
- mdev->profile.rx_moder_time;
+ priv->rx_frames = MLX4_EN_RX_COAL_TARGET / priv->dev->mtu + 1;
+ priv->rx_usecs = MLX4_EN_RX_COAL_TIME;
mlx4_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);
@@ -411,7 +403,7 @@ static void mlx4_en_set_default_moderation(struct mlx4_en_priv *priv)
priv->pkt_rate_high = MLX4_EN_RX_RATE_HIGH;
priv->rx_usecs_high = MLX4_EN_RX_COAL_TIME_HIGH;
priv->sample_interval = MLX4_EN_SAMPLE_INTERVAL;
- priv->adaptive_rx_coal = mdev->profile.auto_moder;
+ priv->adaptive_rx_coal = 1;
priv->last_moder_time = MLX4_EN_AUTO_CONF;
priv->last_moder_jiffies = 0;
priv->last_moder_packets = 0;
@@ -953,6 +945,23 @@ static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
+static const struct net_device_ops mlx4_netdev_ops = {
+ .ndo_open = mlx4_en_open,
+ .ndo_stop = mlx4_en_close,
+ .ndo_start_xmit = mlx4_en_xmit,
+ .ndo_get_stats = mlx4_en_get_stats,
+ .ndo_set_multicast_list = mlx4_en_set_multicast,
+ .ndo_set_mac_address = mlx4_en_set_mac,
+ .ndo_change_mtu = mlx4_en_change_mtu,
+ .ndo_tx_timeout = mlx4_en_tx_timeout,
+ .ndo_vlan_rx_register = mlx4_en_vlan_rx_register,
+ .ndo_vlan_rx_add_vid = mlx4_en_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = mlx4_en_vlan_rx_kill_vid,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = mlx4_en_netpoll,
+#endif
+};
+
int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
struct mlx4_en_port_profile *prof)
{
@@ -1029,22 +1038,9 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
/*
* Initialize netdev entry points
*/
-
- dev->open = &mlx4_en_open;
- dev->stop = &mlx4_en_close;
- dev->hard_start_xmit = &mlx4_en_xmit;
- dev->get_stats = &mlx4_en_get_stats;
- dev->set_multicast_list = &mlx4_en_set_multicast;
- dev->set_mac_address = &mlx4_en_set_mac;
- dev->change_mtu = &mlx4_en_change_mtu;
- dev->tx_timeout = &mlx4_en_tx_timeout;
+ dev->netdev_ops = &mlx4_netdev_ops;
dev->watchdog_timeo = MLX4_EN_WATCHDOG_TIMEOUT;
- dev->vlan_rx_register = mlx4_en_vlan_rx_register;
- dev->vlan_rx_add_vid = mlx4_en_vlan_rx_add_vid;
- dev->vlan_rx_kill_vid = mlx4_en_vlan_rx_kill_vid;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = mlx4_en_netpoll;
-#endif
+
SET_ETHTOOL_OPS(dev, &mlx4_en_ethtool_ops);
/* Set defualt MAC */
diff --git a/drivers/net/mlx4/en_params.c b/drivers/net/mlx4/en_params.c
index 95706ee1c019..047b37f5a747 100644
--- a/drivers/net/mlx4/en_params.c
+++ b/drivers/net/mlx4/en_params.c
@@ -60,24 +60,11 @@ MLX4_EN_PARM_INT(num_lro, MLX4_EN_MAX_LRO_DESCRIPTORS,
"Number of LRO sessions per ring or disabled (0)");
/* Priority pausing */
-MLX4_EN_PARM_INT(pptx, MLX4_EN_DEF_TX_PAUSE,
- "Pause policy on TX: 0 never generate pause frames "
- "1 generate pause frames according to RX buffer threshold");
-MLX4_EN_PARM_INT(pprx, MLX4_EN_DEF_RX_PAUSE,
- "Pause policy on RX: 0 ignore received pause frames "
- "1 respect received pause frames");
MLX4_EN_PARM_INT(pfctx, 0, "Priority based Flow Control policy on TX[7:0]."
" Per priority bit mask");
MLX4_EN_PARM_INT(pfcrx, 0, "Priority based Flow Control policy on RX[7:0]."
" Per priority bit mask");
-/* Interrupt moderation tunning */
-MLX4_EN_PARM_INT(rx_moder_cnt, MLX4_EN_AUTO_CONF,
- "Max coalesced descriptors for Rx interrupt moderation");
-MLX4_EN_PARM_INT(rx_moder_time, MLX4_EN_AUTO_CONF,
- "Timeout following last packet for Rx interrupt moderation");
-MLX4_EN_PARM_INT(auto_moder, 1, "Enable dynamic interrupt moderation");
-
MLX4_EN_PARM_INT(rx_ring_num1, 0, "Number or Rx rings for port 1 (0 = #cores)");
MLX4_EN_PARM_INT(rx_ring_num2, 0, "Number or Rx rings for port 2 (0 = #cores)");
@@ -92,16 +79,13 @@ int mlx4_en_get_profile(struct mlx4_en_dev *mdev)
struct mlx4_en_profile *params = &mdev->profile;
int i;
- params->rx_moder_cnt = min_t(int, rx_moder_cnt, MLX4_EN_AUTO_CONF);
- params->rx_moder_time = min_t(int, rx_moder_time, MLX4_EN_AUTO_CONF);
- params->auto_moder = auto_moder;
params->rss_xor = (rss_xor != 0);
params->rss_mask = rss_mask & 0x1f;
params->num_lro = min_t(int, num_lro , MLX4_EN_MAX_LRO_DESCRIPTORS);
for (i = 1; i <= MLX4_MAX_PORTS; i++) {
- params->prof[i].rx_pause = pprx;
+ params->prof[i].rx_pause = 1;
params->prof[i].rx_ppp = pfcrx;
- params->prof[i].tx_pause = pptx;
+ params->prof[i].tx_pause = 1;
params->prof[i].tx_ppp = pfctx;
}
if (pfcrx || pfctx) {
diff --git a/drivers/net/mlx4/en_rx.c b/drivers/net/mlx4/en_rx.c
index 6232227f56c3..c61b0bdca1a4 100644
--- a/drivers/net/mlx4/en_rx.c
+++ b/drivers/net/mlx4/en_rx.c
@@ -443,7 +443,8 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv)
/* Fill Rx buffers */
ring->full = 0;
}
- if (mlx4_en_fill_rx_buffers(priv))
+ err = mlx4_en_fill_rx_buffers(priv);
+ if (err)
goto err_buffers;
for (ring_ind = 0; ring_ind < priv->rx_ring_num; ring_ind++) {
@@ -776,8 +777,6 @@ int mlx4_en_process_rx_cq(struct net_device *dev, struct mlx4_en_cq *cq, int bud
} else
netif_receive_skb(skb);
- dev->last_rx = jiffies;
-
next:
++cq->mcq.cons_index;
index = (cq->mcq.cons_index) & ring->size_mask;
@@ -815,7 +814,7 @@ void mlx4_en_rx_irq(struct mlx4_cq *mcq)
struct mlx4_en_priv *priv = netdev_priv(cq->dev);
if (priv->port_up)
- netif_rx_schedule(cq->dev, &cq->napi);
+ netif_rx_schedule(&cq->napi);
else
mlx4_en_arm_cq(priv, cq);
}
@@ -835,7 +834,7 @@ int mlx4_en_poll_rx_cq(struct napi_struct *napi, int budget)
INC_PERF_COUNTER(priv->pstats.napi_quota);
else {
/* Done for now */
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
mlx4_en_arm_cq(priv, cq);
}
return done;
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c
index 8592f8fb8475..ff4d75205c25 100644
--- a/drivers/net/mlx4/en_tx.c
+++ b/drivers/net/mlx4/en_tx.c
@@ -379,8 +379,8 @@ static void mlx4_en_process_tx_cq(struct net_device *dev, struct mlx4_en_cq *cq)
/* Wakeup Tx queue if this ring stopped it */
if (unlikely(ring->blocked)) {
- if (((u32) (ring->prod - ring->cons) <=
- ring->size - HEADROOM - MAX_DESC_TXBBS) && !cq->armed) {
+ if ((u32) (ring->prod - ring->cons) <=
+ ring->size - HEADROOM - MAX_DESC_TXBBS) {
/* TODO: support multiqueue netdevs. Currently, we block
* when *any* ring is full. Note that:
@@ -404,14 +404,11 @@ void mlx4_en_tx_irq(struct mlx4_cq *mcq)
struct mlx4_en_priv *priv = netdev_priv(cq->dev);
struct mlx4_en_tx_ring *ring = &priv->tx_ring[cq->ring];
- spin_lock_irq(&ring->comp_lock);
- cq->armed = 0;
+ if (!spin_trylock(&ring->comp_lock))
+ return;
mlx4_en_process_tx_cq(cq->dev, cq);
- if (ring->blocked)
- mlx4_en_arm_cq(priv, cq);
- else
- mod_timer(&cq->timer, jiffies + 1);
- spin_unlock_irq(&ring->comp_lock);
+ mod_timer(&cq->timer, jiffies + 1);
+ spin_unlock(&ring->comp_lock);
}
@@ -424,8 +421,10 @@ void mlx4_en_poll_tx_cq(unsigned long data)
INC_PERF_COUNTER(priv->pstats.tx_poll);
- netif_tx_lock(priv->dev);
- spin_lock_irq(&ring->comp_lock);
+ if (!spin_trylock(&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);
@@ -435,8 +434,7 @@ void mlx4_en_poll_tx_cq(unsigned long data)
if (inflight && priv->port_up)
mod_timer(&cq->timer, jiffies + MLX4_EN_TX_POLL_TIMEOUT);
- spin_unlock_irq(&ring->comp_lock);
- netif_tx_unlock(priv->dev);
+ spin_unlock(&ring->comp_lock);
}
static struct mlx4_en_tx_desc *mlx4_en_bounce_to_desc(struct mlx4_en_priv *priv,
@@ -479,7 +477,10 @@ static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind)
/* Poll the CQ every mlx4_en_TX_MODER_POLL packets */
if ((++ring->poll_cnt & (MLX4_EN_TX_POLL_MODER - 1)) == 0)
- mlx4_en_process_tx_cq(priv->dev, cq);
+ if (spin_trylock(&ring->comp_lock)) {
+ mlx4_en_process_tx_cq(priv->dev, cq);
+ spin_unlock(&ring->comp_lock);
+ }
}
static void *get_frag_ptr(struct sk_buff *skb)
diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c
index de169338cd90..2c19bff7cbab 100644
--- a/drivers/net/mlx4/eq.c
+++ b/drivers/net/mlx4/eq.c
@@ -243,10 +243,6 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq)
* least that often.
*/
if (unlikely(set_ci >= MLX4_NUM_SPARE_EQE)) {
- /*
- * Conditional on hca_type is OK here because
- * this is a rare case, not the fast path.
- */
eq_set_ci(eq, 0);
set_ci = 0;
}
@@ -266,7 +262,7 @@ static irqreturn_t mlx4_interrupt(int irq, void *dev_ptr)
writel(priv->eq_table.clr_mask, priv->eq_table.clr_int);
- for (i = 0; i < MLX4_NUM_EQ; ++i)
+ for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i)
work |= mlx4_eq_int(dev, &priv->eq_table.eq[i]);
return IRQ_RETVAL(work);
@@ -304,6 +300,17 @@ static int mlx4_HW2SW_EQ(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
MLX4_CMD_TIME_CLASS_A);
}
+static int mlx4_num_eq_uar(struct mlx4_dev *dev)
+{
+ /*
+ * Each UAR holds 4 EQ doorbells. To figure out how many UARs
+ * we need to map, take the difference of highest index and
+ * the lowest index we'll use and add 1.
+ */
+ return (dev->caps.num_comp_vectors + 1 + dev->caps.reserved_eqs) / 4 -
+ dev->caps.reserved_eqs / 4 + 1;
+}
+
static void __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, struct mlx4_eq *eq)
{
struct mlx4_priv *priv = mlx4_priv(dev);
@@ -483,9 +490,11 @@ static void mlx4_free_irqs(struct mlx4_dev *dev)
if (eq_table->have_irq)
free_irq(dev->pdev->irq, dev);
- for (i = 0; i < MLX4_NUM_EQ; ++i)
+ for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i)
if (eq_table->eq[i].have_irq)
free_irq(eq_table->eq[i].irq, eq_table->eq + i);
+
+ kfree(eq_table->irq_names);
}
static int mlx4_map_clr_int(struct mlx4_dev *dev)
@@ -551,57 +560,93 @@ void mlx4_unmap_eq_icm(struct mlx4_dev *dev)
__free_page(priv->eq_table.icm_page);
}
+int mlx4_alloc_eq_table(struct mlx4_dev *dev)
+{
+ struct mlx4_priv *priv = mlx4_priv(dev);
+
+ priv->eq_table.eq = kcalloc(dev->caps.num_eqs - dev->caps.reserved_eqs,
+ sizeof *priv->eq_table.eq, GFP_KERNEL);
+ if (!priv->eq_table.eq)
+ return -ENOMEM;
+
+ return 0;
+}
+
+void mlx4_free_eq_table(struct mlx4_dev *dev)
+{
+ kfree(mlx4_priv(dev)->eq_table.eq);
+}
+
int mlx4_init_eq_table(struct mlx4_dev *dev)
{
struct mlx4_priv *priv = mlx4_priv(dev);
int err;
int i;
+ priv->eq_table.uar_map = kcalloc(sizeof *priv->eq_table.uar_map,
+ mlx4_num_eq_uar(dev), GFP_KERNEL);
+ if (!priv->eq_table.uar_map) {
+ err = -ENOMEM;
+ goto err_out_free;
+ }
+
err = mlx4_bitmap_init(&priv->eq_table.bitmap, dev->caps.num_eqs,
dev->caps.num_eqs - 1, dev->caps.reserved_eqs, 0);
if (err)
- return err;
+ goto err_out_free;
- for (i = 0; i < ARRAY_SIZE(priv->eq_table.uar_map); ++i)
+ for (i = 0; i < mlx4_num_eq_uar(dev); ++i)
priv->eq_table.uar_map[i] = NULL;
err = mlx4_map_clr_int(dev);
if (err)
- goto err_out_free;
+ goto err_out_bitmap;
priv->eq_table.clr_mask =
swab32(1 << (priv->eq_table.inta_pin & 31));
priv->eq_table.clr_int = priv->clr_base +
(priv->eq_table.inta_pin < 32 ? 4 : 0);
- err = mlx4_create_eq(dev, dev->caps.num_cqs + MLX4_NUM_SPARE_EQE,
- (dev->flags & MLX4_FLAG_MSI_X) ? MLX4_EQ_COMP : 0,
- &priv->eq_table.eq[MLX4_EQ_COMP]);
- if (err)
- goto err_out_unmap;
+ priv->eq_table.irq_names = kmalloc(16 * dev->caps.num_comp_vectors, GFP_KERNEL);
+ if (!priv->eq_table.irq_names) {
+ err = -ENOMEM;
+ goto err_out_bitmap;
+ }
+
+ for (i = 0; i < dev->caps.num_comp_vectors; ++i) {
+ err = mlx4_create_eq(dev, dev->caps.num_cqs + MLX4_NUM_SPARE_EQE,
+ (dev->flags & MLX4_FLAG_MSI_X) ? i : 0,
+ &priv->eq_table.eq[i]);
+ if (err)
+ goto err_out_unmap;
+ }
err = mlx4_create_eq(dev, MLX4_NUM_ASYNC_EQE + MLX4_NUM_SPARE_EQE,
- (dev->flags & MLX4_FLAG_MSI_X) ? MLX4_EQ_ASYNC : 0,
- &priv->eq_table.eq[MLX4_EQ_ASYNC]);
+ (dev->flags & MLX4_FLAG_MSI_X) ? dev->caps.num_comp_vectors : 0,
+ &priv->eq_table.eq[dev->caps.num_comp_vectors]);
if (err)
goto err_out_comp;
if (dev->flags & MLX4_FLAG_MSI_X) {
- static const char *eq_name[] = {
- [MLX4_EQ_COMP] = DRV_NAME " (comp)",
- [MLX4_EQ_ASYNC] = DRV_NAME " (async)"
- };
+ static const char async_eq_name[] = "mlx4-async";
+ const char *eq_name;
+
+ for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i) {
+ if (i < dev->caps.num_comp_vectors) {
+ snprintf(priv->eq_table.irq_names + i * 16, 16,
+ "mlx4-comp-%d", i);
+ eq_name = priv->eq_table.irq_names + i * 16;
+ } else
+ eq_name = async_eq_name;
- for (i = 0; i < MLX4_NUM_EQ; ++i) {
err = request_irq(priv->eq_table.eq[i].irq,
- mlx4_msi_x_interrupt,
- 0, eq_name[i], priv->eq_table.eq + i);
+ mlx4_msi_x_interrupt, 0, eq_name,
+ priv->eq_table.eq + i);
if (err)
goto err_out_async;
priv->eq_table.eq[i].have_irq = 1;
}
-
} else {
err = request_irq(dev->pdev->irq, mlx4_interrupt,
IRQF_SHARED, DRV_NAME, dev);
@@ -612,28 +657,36 @@ int mlx4_init_eq_table(struct mlx4_dev *dev)
}
err = mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 0,
- priv->eq_table.eq[MLX4_EQ_ASYNC].eqn);
+ priv->eq_table.eq[dev->caps.num_comp_vectors].eqn);
if (err)
mlx4_warn(dev, "MAP_EQ for async EQ %d failed (%d)\n",
- priv->eq_table.eq[MLX4_EQ_ASYNC].eqn, err);
+ priv->eq_table.eq[dev->caps.num_comp_vectors].eqn, err);
- for (i = 0; i < MLX4_NUM_EQ; ++i)
+ for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i)
eq_set_ci(&priv->eq_table.eq[i], 1);
return 0;
err_out_async:
- mlx4_free_eq(dev, &priv->eq_table.eq[MLX4_EQ_ASYNC]);
+ mlx4_free_eq(dev, &priv->eq_table.eq[dev->caps.num_comp_vectors]);
err_out_comp:
- mlx4_free_eq(dev, &priv->eq_table.eq[MLX4_EQ_COMP]);
+ i = dev->caps.num_comp_vectors - 1;
err_out_unmap:
+ while (i >= 0) {
+ mlx4_free_eq(dev, &priv->eq_table.eq[i]);
+ --i;
+ }
mlx4_unmap_clr_int(dev);
mlx4_free_irqs(dev);
-err_out_free:
+err_out_bitmap:
mlx4_bitmap_cleanup(&priv->eq_table.bitmap);
+
+err_out_free:
+ kfree(priv->eq_table.uar_map);
+
return err;
}
@@ -643,18 +696,20 @@ void mlx4_cleanup_eq_table(struct mlx4_dev *dev)
int i;
mlx4_MAP_EQ(dev, MLX4_ASYNC_EVENT_MASK, 1,
- priv->eq_table.eq[MLX4_EQ_ASYNC].eqn);
+ priv->eq_table.eq[dev->caps.num_comp_vectors].eqn);
mlx4_free_irqs(dev);
- for (i = 0; i < MLX4_NUM_EQ; ++i)
+ for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i)
mlx4_free_eq(dev, &priv->eq_table.eq[i]);
mlx4_unmap_clr_int(dev);
- for (i = 0; i < ARRAY_SIZE(priv->eq_table.uar_map); ++i)
+ for (i = 0; i < mlx4_num_eq_uar(dev); ++i)
if (priv->eq_table.uar_map[i])
iounmap(priv->eq_table.uar_map[i]);
mlx4_bitmap_cleanup(&priv->eq_table.bitmap);
+
+ kfree(priv->eq_table.uar_map);
}
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 90a0281d15ea..710c79e7a2db 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -421,9 +421,7 @@ static int mlx4_init_cmpt_table(struct mlx4_dev *dev, u64 cmpt_base,
((u64) (MLX4_CMPT_TYPE_EQ *
cmpt_entry_sz) << MLX4_CMPT_SHIFT),
cmpt_entry_sz,
- roundup_pow_of_two(MLX4_NUM_EQ +
- dev->caps.reserved_eqs),
- MLX4_NUM_EQ + dev->caps.reserved_eqs, 0, 0);
+ dev->caps.num_eqs, dev->caps.num_eqs, 0, 0);
if (err)
goto err_cq;
@@ -810,12 +808,12 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
if (dev->flags & MLX4_FLAG_MSI_X) {
mlx4_warn(dev, "NOP command failed to generate MSI-X "
"interrupt IRQ %d).\n",
- priv->eq_table.eq[MLX4_EQ_ASYNC].irq);
+ priv->eq_table.eq[dev->caps.num_comp_vectors].irq);
mlx4_warn(dev, "Trying again without MSI-X.\n");
} else {
mlx4_err(dev, "NOP command failed to generate interrupt "
"(IRQ %d), aborting.\n",
- priv->eq_table.eq[MLX4_EQ_ASYNC].irq);
+ priv->eq_table.eq[dev->caps.num_comp_vectors].irq);
mlx4_err(dev, "BIOS or ACPI interrupt routing problem?\n");
}
@@ -908,31 +906,50 @@ err_uar_table_free:
static void mlx4_enable_msi_x(struct mlx4_dev *dev)
{
struct mlx4_priv *priv = mlx4_priv(dev);
- struct msix_entry entries[MLX4_NUM_EQ];
+ struct msix_entry *entries;
+ int nreq;
int err;
int i;
if (msi_x) {
- for (i = 0; i < MLX4_NUM_EQ; ++i)
+ nreq = min(dev->caps.num_eqs - dev->caps.reserved_eqs,
+ num_possible_cpus() + 1);
+ entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL);
+ if (!entries)
+ goto no_msi;
+
+ for (i = 0; i < nreq; ++i)
entries[i].entry = i;
- err = pci_enable_msix(dev->pdev, entries, ARRAY_SIZE(entries));
+ retry:
+ err = pci_enable_msix(dev->pdev, entries, nreq);
if (err) {
- if (err > 0)
- mlx4_info(dev, "Only %d MSI-X vectors available, "
- "not using MSI-X\n", err);
+ /* Try again if at least 2 vectors are available */
+ if (err > 1) {
+ mlx4_info(dev, "Requested %d vectors, "
+ "but only %d MSI-X vectors available, "
+ "trying again\n", nreq, err);
+ nreq = err;
+ goto retry;
+ }
+
goto no_msi;
}
- for (i = 0; i < MLX4_NUM_EQ; ++i)
+ dev->caps.num_comp_vectors = nreq - 1;
+ for (i = 0; i < nreq; ++i)
priv->eq_table.eq[i].irq = entries[i].vector;
dev->flags |= MLX4_FLAG_MSI_X;
+
+ kfree(entries);
return;
}
no_msi:
- for (i = 0; i < MLX4_NUM_EQ; ++i)
+ dev->caps.num_comp_vectors = 1;
+
+ for (i = 0; i < 2; ++i)
priv->eq_table.eq[i].irq = dev->pdev->irq;
}
@@ -1074,6 +1091,10 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
if (err)
goto err_cmd;
+ err = mlx4_alloc_eq_table(dev);
+ if (err)
+ goto err_close;
+
mlx4_enable_msi_x(dev);
err = mlx4_setup_hca(dev);
@@ -1084,7 +1105,7 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
}
if (err)
- goto err_close;
+ goto err_free_eq;
for (port = 1; port <= dev->caps.num_ports; port++) {
err = mlx4_init_port_info(dev, port);
@@ -1114,6 +1135,9 @@ err_port:
mlx4_cleanup_pd_table(dev);
mlx4_cleanup_uar_table(dev);
+err_free_eq:
+ mlx4_free_eq_table(dev);
+
err_close:
if (dev->flags & MLX4_FLAG_MSI_X)
pci_disable_msix(pdev);
@@ -1177,6 +1201,7 @@ static void mlx4_remove_one(struct pci_dev *pdev)
iounmap(priv->kar);
mlx4_uar_free(dev, &priv->driver_uar);
mlx4_cleanup_uar_table(dev);
+ mlx4_free_eq_table(dev);
mlx4_close_hca(dev);
mlx4_cmd_cleanup(dev);
diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c
index 592c01ae2c5d..6053c357a470 100644
--- a/drivers/net/mlx4/mcg.c
+++ b/drivers/net/mlx4/mcg.c
@@ -118,17 +118,7 @@ static int find_mgm(struct mlx4_dev *dev,
return err;
if (0)
- mlx4_dbg(dev, "Hash for %04x:%04x:%04x:%04x:"
- "%04x:%04x:%04x:%04x is %04x\n",
- be16_to_cpu(((__be16 *) gid)[0]),
- be16_to_cpu(((__be16 *) gid)[1]),
- be16_to_cpu(((__be16 *) gid)[2]),
- be16_to_cpu(((__be16 *) gid)[3]),
- be16_to_cpu(((__be16 *) gid)[4]),
- be16_to_cpu(((__be16 *) gid)[5]),
- be16_to_cpu(((__be16 *) gid)[6]),
- be16_to_cpu(((__be16 *) gid)[7]),
- *hash);
+ mlx4_dbg(dev, "Hash for %pI6 is %04x\n", gid, *hash);
*index = *hash;
*prev = -1;
@@ -215,7 +205,7 @@ int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
if (block_mcast_loopback)
mgm->qp[members_count++] = cpu_to_be32((qp->qpn & MGM_QPN_MASK) |
- (1 << MGM_BLCK_LB_BIT));
+ (1U << MGM_BLCK_LB_BIT));
else
mgm->qp[members_count++] = cpu_to_be32(qp->qpn & MGM_QPN_MASK);
@@ -277,16 +267,7 @@ int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16])
goto out;
if (index == -1) {
- mlx4_err(dev, "MGID %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x "
- "not found\n",
- be16_to_cpu(((__be16 *) gid)[0]),
- be16_to_cpu(((__be16 *) gid)[1]),
- be16_to_cpu(((__be16 *) gid)[2]),
- be16_to_cpu(((__be16 *) gid)[3]),
- be16_to_cpu(((__be16 *) gid)[4]),
- be16_to_cpu(((__be16 *) gid)[5]),
- be16_to_cpu(((__be16 *) gid)[6]),
- be16_to_cpu(((__be16 *) gid)[7]));
+ mlx4_err(dev, "MGID %pI6 not found\n", gid);
err = -EINVAL;
goto out;
}
diff --git a/drivers/net/mlx4/mlx4.h b/drivers/net/mlx4/mlx4.h
index 34c909deaff3..e0213bad61c7 100644
--- a/drivers/net/mlx4/mlx4.h
+++ b/drivers/net/mlx4/mlx4.h
@@ -63,12 +63,6 @@ enum {
};
enum {
- MLX4_EQ_ASYNC,
- MLX4_EQ_COMP,
- MLX4_NUM_EQ
-};
-
-enum {
MLX4_NUM_PDS = 1 << 15
};
@@ -205,10 +199,11 @@ struct mlx4_cq_table {
struct mlx4_eq_table {
struct mlx4_bitmap bitmap;
+ char *irq_names;
void __iomem *clr_int;
- void __iomem *uar_map[(MLX4_NUM_EQ + 6) / 4];
+ void __iomem **uar_map;
u32 clr_mask;
- struct mlx4_eq eq[MLX4_NUM_EQ];
+ struct mlx4_eq *eq;
u64 icm_virt;
struct page *icm_page;
dma_addr_t icm_dma;
@@ -328,6 +323,9 @@ void mlx4_bitmap_cleanup(struct mlx4_bitmap *bitmap);
int mlx4_reset(struct mlx4_dev *dev);
+int mlx4_alloc_eq_table(struct mlx4_dev *dev);
+void mlx4_free_eq_table(struct mlx4_dev *dev);
+
int mlx4_init_pd_table(struct mlx4_dev *dev);
int mlx4_init_uar_table(struct mlx4_dev *dev);
int mlx4_init_mr_table(struct mlx4_dev *dev);
diff --git a/drivers/net/mlx4/mlx4_en.h b/drivers/net/mlx4/mlx4_en.h
index 98ddc0811f93..e78209768def 100644
--- a/drivers/net/mlx4/mlx4_en.h
+++ b/drivers/net/mlx4/mlx4_en.h
@@ -58,17 +58,17 @@
#define mlx4_dbg(mlevel, priv, format, arg...) \
if (NETIF_MSG_##mlevel & priv->msg_enable) \
printk(KERN_DEBUG "%s %s: " format , DRV_NAME ,\
- (&priv->mdev->pdev->dev)->bus_id , ## arg)
+ (dev_name(&priv->mdev->pdev->dev)) , ## arg)
#define mlx4_err(mdev, format, arg...) \
printk(KERN_ERR "%s %s: " format , DRV_NAME ,\
- (&mdev->pdev->dev)->bus_id , ## arg)
+ (dev_name(&mdev->pdev->dev)) , ## arg)
#define mlx4_info(mdev, format, arg...) \
printk(KERN_INFO "%s %s: " format , DRV_NAME ,\
- (&mdev->pdev->dev)->bus_id , ## arg)
+ (dev_name(&mdev->pdev->dev)) , ## arg)
#define mlx4_warn(mdev, format, arg...) \
printk(KERN_WARNING "%s %s: " format , DRV_NAME ,\
- (&mdev->pdev->dev)->bus_id , ## arg)
+ (dev_name(&mdev->pdev->dev)) , ## arg)
/*
* Device constants
@@ -311,7 +311,6 @@ struct mlx4_en_cq {
enum cq_type is_tx;
u16 moder_time;
u16 moder_cnt;
- int armed;
struct mlx4_cqe *buf;
#define MLX4_EN_OPCODE_ERROR 0x1e
};
@@ -334,9 +333,6 @@ struct mlx4_en_profile {
u8 rss_mask;
u32 active_ports;
u32 small_pkt_int;
- int rx_moder_cnt;
- int rx_moder_time;
- int auto_moder;
u8 no_reset;
struct mlx4_en_port_profile prof[MLX4_MAX_PORTS + 1];
};
diff --git a/drivers/net/mlx4/profile.c b/drivers/net/mlx4/profile.c
index 9ca42b213d54..919fb9eb1b62 100644
--- a/drivers/net/mlx4/profile.c
+++ b/drivers/net/mlx4/profile.c
@@ -107,7 +107,9 @@ u64 mlx4_make_profile(struct mlx4_dev *dev,
profile[MLX4_RES_AUXC].num = request->num_qp;
profile[MLX4_RES_SRQ].num = request->num_srq;
profile[MLX4_RES_CQ].num = request->num_cq;
- profile[MLX4_RES_EQ].num = MLX4_NUM_EQ + dev_cap->reserved_eqs;
+ profile[MLX4_RES_EQ].num = min(dev_cap->max_eqs,
+ dev_cap->reserved_eqs +
+ num_possible_cpus() + 1);
profile[MLX4_RES_DMPT].num = request->num_mpt;
profile[MLX4_RES_CMPT].num = MLX4_NUM_CMPTS;
profile[MLX4_RES_MTT].num = request->num_mtt;
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
index e513f76f2a9f..7253a499d9c8 100644
--- a/drivers/net/mv643xx_eth.c
+++ b/drivers/net/mv643xx_eth.c
@@ -51,8 +51,8 @@
#include <linux/workqueue.h>
#include <linux/phy.h>
#include <linux/mv643xx_eth.h>
-#include <asm/io.h>
-#include <asm/types.h>
+#include <linux/io.h>
+#include <linux/types.h>
#include <asm/system.h>
static char mv643xx_eth_driver_name[] = "mv643xx_eth";
@@ -78,16 +78,17 @@ static char mv643xx_eth_driver_version[] = "1.4";
#define WINDOW_PROTECT(w) (0x0294 + ((w) << 4))
/*
- * Per-port registers.
+ * Main per-port registers. These live at offset 0x0400 for
+ * port #0, 0x0800 for port #1, and 0x0c00 for port #2.
*/
-#define PORT_CONFIG(p) (0x0400 + ((p) << 10))
+#define PORT_CONFIG 0x0000
#define UNICAST_PROMISCUOUS_MODE 0x00000001
-#define PORT_CONFIG_EXT(p) (0x0404 + ((p) << 10))
-#define MAC_ADDR_LOW(p) (0x0414 + ((p) << 10))
-#define MAC_ADDR_HIGH(p) (0x0418 + ((p) << 10))
-#define SDMA_CONFIG(p) (0x041c + ((p) << 10))
-#define PORT_SERIAL_CONTROL(p) (0x043c + ((p) << 10))
-#define PORT_STATUS(p) (0x0444 + ((p) << 10))
+#define PORT_CONFIG_EXT 0x0004
+#define MAC_ADDR_LOW 0x0014
+#define MAC_ADDR_HIGH 0x0018
+#define SDMA_CONFIG 0x001c
+#define PORT_SERIAL_CONTROL 0x003c
+#define PORT_STATUS 0x0044
#define TX_FIFO_EMPTY 0x00000400
#define TX_IN_PROGRESS 0x00000080
#define PORT_SPEED_MASK 0x00000030
@@ -97,31 +98,35 @@ static char mv643xx_eth_driver_version[] = "1.4";
#define FLOW_CONTROL_ENABLED 0x00000008
#define FULL_DUPLEX 0x00000004
#define LINK_UP 0x00000002
-#define TXQ_COMMAND(p) (0x0448 + ((p) << 10))
-#define TXQ_FIX_PRIO_CONF(p) (0x044c + ((p) << 10))
-#define TX_BW_RATE(p) (0x0450 + ((p) << 10))
-#define TX_BW_MTU(p) (0x0458 + ((p) << 10))
-#define TX_BW_BURST(p) (0x045c + ((p) << 10))
-#define INT_CAUSE(p) (0x0460 + ((p) << 10))
+#define TXQ_COMMAND 0x0048
+#define TXQ_FIX_PRIO_CONF 0x004c
+#define TX_BW_RATE 0x0050
+#define TX_BW_MTU 0x0058
+#define TX_BW_BURST 0x005c
+#define INT_CAUSE 0x0060
#define INT_TX_END 0x07f80000
#define INT_RX 0x000003fc
#define INT_EXT 0x00000002
-#define INT_CAUSE_EXT(p) (0x0464 + ((p) << 10))
+#define INT_CAUSE_EXT 0x0064
#define INT_EXT_LINK_PHY 0x00110000
#define INT_EXT_TX 0x000000ff
-#define INT_MASK(p) (0x0468 + ((p) << 10))
-#define INT_MASK_EXT(p) (0x046c + ((p) << 10))
-#define TX_FIFO_URGENT_THRESHOLD(p) (0x0474 + ((p) << 10))
-#define TXQ_FIX_PRIO_CONF_MOVED(p) (0x04dc + ((p) << 10))
-#define TX_BW_RATE_MOVED(p) (0x04e0 + ((p) << 10))
-#define TX_BW_MTU_MOVED(p) (0x04e8 + ((p) << 10))
-#define TX_BW_BURST_MOVED(p) (0x04ec + ((p) << 10))
-#define RXQ_CURRENT_DESC_PTR(p, q) (0x060c + ((p) << 10) + ((q) << 4))
-#define RXQ_COMMAND(p) (0x0680 + ((p) << 10))
-#define TXQ_CURRENT_DESC_PTR(p, q) (0x06c0 + ((p) << 10) + ((q) << 2))
-#define TXQ_BW_TOKENS(p, q) (0x0700 + ((p) << 10) + ((q) << 4))
-#define TXQ_BW_CONF(p, q) (0x0704 + ((p) << 10) + ((q) << 4))
-#define TXQ_BW_WRR_CONF(p, q) (0x0708 + ((p) << 10) + ((q) << 4))
+#define INT_MASK 0x0068
+#define INT_MASK_EXT 0x006c
+#define TX_FIFO_URGENT_THRESHOLD 0x0074
+#define TXQ_FIX_PRIO_CONF_MOVED 0x00dc
+#define TX_BW_RATE_MOVED 0x00e0
+#define TX_BW_MTU_MOVED 0x00e8
+#define TX_BW_BURST_MOVED 0x00ec
+#define RXQ_CURRENT_DESC_PTR(q) (0x020c + ((q) << 4))
+#define RXQ_COMMAND 0x0280
+#define TXQ_CURRENT_DESC_PTR(q) (0x02c0 + ((q) << 2))
+#define TXQ_BW_TOKENS(q) (0x0300 + ((q) << 4))
+#define TXQ_BW_CONF(q) (0x0304 + ((q) << 4))
+#define TXQ_BW_WRR_CONF(q) (0x0308 + ((q) << 4))
+
+/*
+ * Misc per-port registers.
+ */
#define MIB_COUNTERS(p) (0x1000 + ((p) << 7))
#define SPECIAL_MCAST_TABLE(p) (0x1400 + ((p) << 10))
#define OTHER_MCAST_TABLE(p) (0x1500 + ((p) << 10))
@@ -138,14 +143,14 @@ static char mv643xx_eth_driver_version[] = "1.4";
#if defined(__BIG_ENDIAN)
#define PORT_SDMA_CONFIG_DEFAULT_VALUE \
- RX_BURST_SIZE_16_64BIT | \
- TX_BURST_SIZE_16_64BIT
+ (RX_BURST_SIZE_16_64BIT | \
+ TX_BURST_SIZE_16_64BIT)
#elif defined(__LITTLE_ENDIAN)
#define PORT_SDMA_CONFIG_DEFAULT_VALUE \
- RX_BURST_SIZE_16_64BIT | \
+ (RX_BURST_SIZE_16_64BIT | \
BLM_RX_NO_SWAP | \
BLM_TX_NO_SWAP | \
- TX_BURST_SIZE_16_64BIT
+ TX_BURST_SIZE_16_64BIT)
#else
#error One of __BIG_ENDIAN or __LITTLE_ENDIAN must be defined
#endif
@@ -351,6 +356,7 @@ struct tx_queue {
struct mv643xx_eth_private {
struct mv643xx_eth_shared_private *shared;
+ void __iomem *base;
int port_num;
struct net_device *dev;
@@ -401,11 +407,21 @@ static inline u32 rdl(struct mv643xx_eth_private *mp, int offset)
return readl(mp->shared->base + offset);
}
+static inline u32 rdlp(struct mv643xx_eth_private *mp, int offset)
+{
+ return readl(mp->base + offset);
+}
+
static inline void wrl(struct mv643xx_eth_private *mp, int offset, u32 data)
{
writel(data, mp->shared->base + offset);
}
+static inline void wrlp(struct mv643xx_eth_private *mp, int offset, u32 data)
+{
+ writel(data, mp->base + offset);
+}
+
/* rxq/txq helper functions *************************************************/
static struct mv643xx_eth_private *rxq_to_mp(struct rx_queue *rxq)
@@ -421,7 +437,7 @@ static struct mv643xx_eth_private *txq_to_mp(struct tx_queue *txq)
static void rxq_enable(struct rx_queue *rxq)
{
struct mv643xx_eth_private *mp = rxq_to_mp(rxq);
- wrl(mp, RXQ_COMMAND(mp->port_num), 1 << rxq->index);
+ wrlp(mp, RXQ_COMMAND, 1 << rxq->index);
}
static void rxq_disable(struct rx_queue *rxq)
@@ -429,26 +445,25 @@ static void rxq_disable(struct rx_queue *rxq)
struct mv643xx_eth_private *mp = rxq_to_mp(rxq);
u8 mask = 1 << rxq->index;
- wrl(mp, RXQ_COMMAND(mp->port_num), mask << 8);
- while (rdl(mp, RXQ_COMMAND(mp->port_num)) & mask)
+ wrlp(mp, RXQ_COMMAND, mask << 8);
+ while (rdlp(mp, RXQ_COMMAND) & mask)
udelay(10);
}
static void txq_reset_hw_ptr(struct tx_queue *txq)
{
struct mv643xx_eth_private *mp = txq_to_mp(txq);
- int off = TXQ_CURRENT_DESC_PTR(mp->port_num, txq->index);
u32 addr;
addr = (u32)txq->tx_desc_dma;
addr += txq->tx_curr_desc * sizeof(struct tx_desc);
- wrl(mp, off, addr);
+ wrlp(mp, TXQ_CURRENT_DESC_PTR(txq->index), addr);
}
static void txq_enable(struct tx_queue *txq)
{
struct mv643xx_eth_private *mp = txq_to_mp(txq);
- wrl(mp, TXQ_COMMAND(mp->port_num), 1 << txq->index);
+ wrlp(mp, TXQ_COMMAND, 1 << txq->index);
}
static void txq_disable(struct tx_queue *txq)
@@ -456,8 +471,8 @@ static void txq_disable(struct tx_queue *txq)
struct mv643xx_eth_private *mp = txq_to_mp(txq);
u8 mask = 1 << txq->index;
- wrl(mp, TXQ_COMMAND(mp->port_num), mask << 8);
- while (rdl(mp, TXQ_COMMAND(mp->port_num)) & mask)
+ wrlp(mp, TXQ_COMMAND, mask << 8);
+ while (rdlp(mp, TXQ_COMMAND) & mask)
udelay(10);
}
@@ -528,37 +543,38 @@ static int rxq_process(struct rx_queue *rxq, int budget)
* on, or the error summary bit is set, the packet needs
* to be dropped.
*/
- if (((cmd_sts & (RX_FIRST_DESC | RX_LAST_DESC)) !=
- (RX_FIRST_DESC | RX_LAST_DESC))
- || (cmd_sts & ERROR_SUMMARY)) {
- stats->rx_dropped++;
-
- if ((cmd_sts & (RX_FIRST_DESC | RX_LAST_DESC)) !=
- (RX_FIRST_DESC | RX_LAST_DESC)) {
- if (net_ratelimit())
- dev_printk(KERN_ERR, &mp->dev->dev,
- "received packet spanning "
- "multiple descriptors\n");
- }
+ if ((cmd_sts & (RX_FIRST_DESC | RX_LAST_DESC | ERROR_SUMMARY))
+ != (RX_FIRST_DESC | RX_LAST_DESC))
+ goto err;
- if (cmd_sts & ERROR_SUMMARY)
- stats->rx_errors++;
+ /*
+ * The -4 is for the CRC in the trailer of the
+ * received packet
+ */
+ skb_put(skb, byte_cnt - 2 - 4);
- dev_kfree_skb(skb);
- } else {
- /*
- * The -4 is for the CRC in the trailer of the
- * received packet
- */
- skb_put(skb, byte_cnt - 2 - 4);
-
- if (cmd_sts & LAYER_4_CHECKSUM_OK)
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- skb->protocol = eth_type_trans(skb, mp->dev);
- netif_receive_skb(skb);
+ if (cmd_sts & LAYER_4_CHECKSUM_OK)
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+ skb->protocol = eth_type_trans(skb, mp->dev);
+ netif_receive_skb(skb);
+
+ continue;
+
+err:
+ stats->rx_dropped++;
+
+ if ((cmd_sts & (RX_FIRST_DESC | RX_LAST_DESC)) !=
+ (RX_FIRST_DESC | RX_LAST_DESC)) {
+ if (net_ratelimit())
+ dev_printk(KERN_ERR, &mp->dev->dev,
+ "received packet spanning "
+ "multiple descriptors\n");
}
- mp->dev->last_rx = jiffies;
+ if (cmd_sts & ERROR_SUMMARY)
+ stats->rx_errors++;
+
+ dev_kfree_skb(skb);
}
if (rx < budget)
@@ -577,6 +593,7 @@ static int rxq_refill(struct rx_queue *rxq, int budget)
struct sk_buff *skb;
int unaligned;
int rx;
+ struct rx_desc *rx_desc;
skb = __skb_dequeue(&mp->rx_recycle);
if (skb == NULL)
@@ -599,13 +616,14 @@ static int rxq_refill(struct rx_queue *rxq, int budget)
if (rxq->rx_used_desc == rxq->rx_ring_size)
rxq->rx_used_desc = 0;
- rxq->rx_desc_area[rx].buf_ptr = dma_map_single(NULL, skb->data,
- mp->skb_size, DMA_FROM_DEVICE);
- rxq->rx_desc_area[rx].buf_size = mp->skb_size;
+ rx_desc = rxq->rx_desc_area + rx;
+
+ rx_desc->buf_ptr = dma_map_single(NULL, skb->data,
+ mp->skb_size, DMA_FROM_DEVICE);
+ rx_desc->buf_size = mp->skb_size;
rxq->rx_skb[rx] = skb;
wmb();
- rxq->rx_desc_area[rx].cmd_sts = BUFFER_OWNED_BY_DMA |
- RX_ENABLE_INTERRUPT;
+ rx_desc->cmd_sts = BUFFER_OWNED_BY_DMA | RX_ENABLE_INTERRUPT;
wmb();
/*
@@ -638,21 +656,6 @@ static inline unsigned int has_tiny_unaligned_frags(struct sk_buff *skb)
return 0;
}
-static int txq_alloc_desc_index(struct tx_queue *txq)
-{
- int tx_desc_curr;
-
- BUG_ON(txq->tx_desc_count >= txq->tx_ring_size);
-
- tx_desc_curr = txq->tx_curr_desc++;
- if (txq->tx_curr_desc == txq->tx_ring_size)
- txq->tx_curr_desc = 0;
-
- BUG_ON(txq->tx_curr_desc == txq->tx_used_desc);
-
- return tx_desc_curr;
-}
-
static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb)
{
int nr_frags = skb_shinfo(skb)->nr_frags;
@@ -664,7 +667,9 @@ static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb)
struct tx_desc *desc;
this_frag = &skb_shinfo(skb)->frags[frag];
- tx_index = txq_alloc_desc_index(txq);
+ tx_index = txq->tx_curr_desc++;
+ if (txq->tx_curr_desc == txq->tx_ring_size)
+ txq->tx_curr_desc = 0;
desc = &txq->tx_desc_area[tx_index];
/*
@@ -746,7 +751,9 @@ no_csum:
cmd_sts |= 5 << TX_IHL_SHIFT;
}
- tx_index = txq_alloc_desc_index(txq);
+ tx_index = txq->tx_curr_desc++;
+ if (txq->tx_curr_desc == txq->tx_ring_size)
+ txq->tx_curr_desc = 0;
desc = &txq->tx_desc_area[tx_index];
if (nr_frags) {
@@ -831,10 +838,10 @@ static void txq_kick(struct tx_queue *txq)
__netif_tx_lock(nq, smp_processor_id());
- if (rdl(mp, TXQ_COMMAND(mp->port_num)) & (1 << txq->index))
+ if (rdlp(mp, TXQ_COMMAND) & (1 << txq->index))
goto out;
- hw_desc_ptr = rdl(mp, TXQ_CURRENT_DESC_PTR(mp->port_num, txq->index));
+ hw_desc_ptr = rdlp(mp, TXQ_CURRENT_DESC_PTR(txq->index));
expected_ptr = (u32)txq->tx_desc_dma +
txq->tx_curr_desc * sizeof(struct tx_desc);
@@ -941,14 +948,14 @@ static void tx_set_rate(struct mv643xx_eth_private *mp, int rate, int burst)
switch (mp->shared->tx_bw_control) {
case TX_BW_CONTROL_OLD_LAYOUT:
- wrl(mp, TX_BW_RATE(mp->port_num), token_rate);
- wrl(mp, TX_BW_MTU(mp->port_num), mtu);
- wrl(mp, TX_BW_BURST(mp->port_num), bucket_size);
+ wrlp(mp, TX_BW_RATE, token_rate);
+ wrlp(mp, TX_BW_MTU, mtu);
+ wrlp(mp, TX_BW_BURST, bucket_size);
break;
case TX_BW_CONTROL_NEW_LAYOUT:
- wrl(mp, TX_BW_RATE_MOVED(mp->port_num), token_rate);
- wrl(mp, TX_BW_MTU_MOVED(mp->port_num), mtu);
- wrl(mp, TX_BW_BURST_MOVED(mp->port_num), bucket_size);
+ wrlp(mp, TX_BW_RATE_MOVED, token_rate);
+ wrlp(mp, TX_BW_MTU_MOVED, mtu);
+ wrlp(mp, TX_BW_BURST_MOVED, bucket_size);
break;
}
}
@@ -967,9 +974,8 @@ static void txq_set_rate(struct tx_queue *txq, int rate, int burst)
if (bucket_size > 65535)
bucket_size = 65535;
- wrl(mp, TXQ_BW_TOKENS(mp->port_num, txq->index), token_rate << 14);
- wrl(mp, TXQ_BW_CONF(mp->port_num, txq->index),
- (bucket_size << 10) | token_rate);
+ wrlp(mp, TXQ_BW_TOKENS(txq->index), token_rate << 14);
+ wrlp(mp, TXQ_BW_CONF(txq->index), (bucket_size << 10) | token_rate);
}
static void txq_set_fixed_prio_mode(struct tx_queue *txq)
@@ -984,17 +990,17 @@ static void txq_set_fixed_prio_mode(struct tx_queue *txq)
off = 0;
switch (mp->shared->tx_bw_control) {
case TX_BW_CONTROL_OLD_LAYOUT:
- off = TXQ_FIX_PRIO_CONF(mp->port_num);
+ off = TXQ_FIX_PRIO_CONF;
break;
case TX_BW_CONTROL_NEW_LAYOUT:
- off = TXQ_FIX_PRIO_CONF_MOVED(mp->port_num);
+ off = TXQ_FIX_PRIO_CONF_MOVED;
break;
}
if (off) {
- val = rdl(mp, off);
+ val = rdlp(mp, off);
val |= 1 << txq->index;
- wrl(mp, off, val);
+ wrlp(mp, off, val);
}
}
@@ -1010,26 +1016,25 @@ static void txq_set_wrr(struct tx_queue *txq, int weight)
off = 0;
switch (mp->shared->tx_bw_control) {
case TX_BW_CONTROL_OLD_LAYOUT:
- off = TXQ_FIX_PRIO_CONF(mp->port_num);
+ off = TXQ_FIX_PRIO_CONF;
break;
case TX_BW_CONTROL_NEW_LAYOUT:
- off = TXQ_FIX_PRIO_CONF_MOVED(mp->port_num);
+ off = TXQ_FIX_PRIO_CONF_MOVED;
break;
}
if (off) {
- val = rdl(mp, off);
+ val = rdlp(mp, off);
val &= ~(1 << txq->index);
- wrl(mp, off, val);
+ wrlp(mp, off, val);
/*
* Configure WRR weight for this queue.
*/
- off = TXQ_BW_WRR_CONF(mp->port_num, txq->index);
- val = rdl(mp, off);
+ val = rdlp(mp, off);
val = (val & ~0xff) | (weight & 0xff);
- wrl(mp, off, val);
+ wrlp(mp, TXQ_BW_WRR_CONF(txq->index), val);
}
}
@@ -1084,20 +1089,20 @@ static int smi_bus_read(struct mii_bus *bus, int addr, int reg)
int ret;
if (smi_wait_ready(msp)) {
- printk("mv643xx_eth: SMI bus busy timeout\n");
+ printk(KERN_WARNING "mv643xx_eth: SMI bus busy timeout\n");
return -ETIMEDOUT;
}
writel(SMI_OPCODE_READ | (reg << 21) | (addr << 16), smi_reg);
if (smi_wait_ready(msp)) {
- printk("mv643xx_eth: SMI bus busy timeout\n");
+ printk(KERN_WARNING "mv643xx_eth: SMI bus busy timeout\n");
return -ETIMEDOUT;
}
ret = readl(smi_reg);
if (!(ret & SMI_READ_VALID)) {
- printk("mv643xx_eth: SMI bus read not valid\n");
+ printk(KERN_WARNING "mv643xx_eth: SMI bus read not valid\n");
return -ENODEV;
}
@@ -1110,7 +1115,7 @@ static int smi_bus_write(struct mii_bus *bus, int addr, int reg, u16 val)
void __iomem *smi_reg = msp->base + SMI_REG;
if (smi_wait_ready(msp)) {
- printk("mv643xx_eth: SMI bus busy timeout\n");
+ printk(KERN_WARNING "mv643xx_eth: SMI bus busy timeout\n");
return -ETIMEDOUT;
}
@@ -1118,7 +1123,7 @@ static int smi_bus_write(struct mii_bus *bus, int addr, int reg, u16 val)
(addr << 16) | (val & 0xffff), smi_reg);
if (smi_wait_ready(msp)) {
- printk("mv643xx_eth: SMI bus busy timeout\n");
+ printk(KERN_WARNING "mv643xx_eth: SMI bus busy timeout\n");
return -ETIMEDOUT;
}
@@ -1271,7 +1276,8 @@ static const struct mv643xx_eth_stats mv643xx_eth_stats[] = {
MIBSTAT(late_collision),
};
-static int mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int
+mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct mv643xx_eth_private *mp = netdev_priv(dev);
int err;
@@ -1289,12 +1295,14 @@ static int mv643xx_eth_get_settings(struct net_device *dev, struct ethtool_cmd *
return err;
}
-static int mv643xx_eth_get_settings_phyless(struct net_device *dev, struct ethtool_cmd *cmd)
+static int
+mv643xx_eth_get_settings_phyless(struct net_device *dev,
+ struct ethtool_cmd *cmd)
{
struct mv643xx_eth_private *mp = netdev_priv(dev);
u32 port_status;
- port_status = rdl(mp, PORT_STATUS(mp->port_num));
+ port_status = rdlp(mp, PORT_STATUS);
cmd->supported = SUPPORTED_MII;
cmd->advertising = ADVERTISED_MII;
@@ -1323,7 +1331,8 @@ static int mv643xx_eth_get_settings_phyless(struct net_device *dev, struct ethto
return 0;
}
-static int mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int
+mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
struct mv643xx_eth_private *mp = netdev_priv(dev);
@@ -1335,7 +1344,9 @@ static int mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *
return phy_ethtool_sset(mp->phy, cmd);
}
-static int mv643xx_eth_set_settings_phyless(struct net_device *dev, struct ethtool_cmd *cmd)
+static int
+mv643xx_eth_set_settings_phyless(struct net_device *dev,
+ struct ethtool_cmd *cmd)
{
return -EINVAL;
}
@@ -1443,11 +1454,8 @@ static const struct ethtool_ops mv643xx_eth_ethtool_ops_phyless = {
/* address handling *********************************************************/
static void uc_addr_get(struct mv643xx_eth_private *mp, unsigned char *addr)
{
- unsigned int mac_h;
- unsigned int mac_l;
-
- mac_h = rdl(mp, MAC_ADDR_HIGH(mp->port_num));
- mac_l = rdl(mp, MAC_ADDR_LOW(mp->port_num));
+ unsigned int mac_h = rdlp(mp, MAC_ADDR_HIGH);
+ unsigned int mac_l = rdlp(mp, MAC_ADDR_LOW);
addr[0] = (mac_h >> 24) & 0xff;
addr[1] = (mac_h >> 16) & 0xff;
@@ -1457,57 +1465,71 @@ static void uc_addr_get(struct mv643xx_eth_private *mp, unsigned char *addr)
addr[5] = mac_l & 0xff;
}
-static void init_mac_tables(struct mv643xx_eth_private *mp)
+static void uc_addr_set(struct mv643xx_eth_private *mp, unsigned char *addr)
{
- int i;
-
- for (i = 0; i < 0x100; i += 4) {
- wrl(mp, SPECIAL_MCAST_TABLE(mp->port_num) + i, 0);
- wrl(mp, OTHER_MCAST_TABLE(mp->port_num) + i, 0);
- }
-
- for (i = 0; i < 0x10; i += 4)
- wrl(mp, UNICAST_TABLE(mp->port_num) + i, 0);
+ wrlp(mp, MAC_ADDR_HIGH,
+ (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | addr[3]);
+ wrlp(mp, MAC_ADDR_LOW, (addr[4] << 8) | addr[5]);
}
-static void set_filter_table_entry(struct mv643xx_eth_private *mp,
- int table, unsigned char entry)
+static u32 uc_addr_filter_mask(struct net_device *dev)
{
- unsigned int table_reg;
-
- /* Set "accepts frame bit" at specified table entry */
- table_reg = rdl(mp, table + (entry & 0xfc));
- table_reg |= 0x01 << (8 * (entry & 3));
- wrl(mp, table + (entry & 0xfc), table_reg);
-}
+ struct dev_addr_list *uc_ptr;
+ u32 nibbles;
-static void uc_addr_set(struct mv643xx_eth_private *mp, unsigned char *addr)
-{
- unsigned int mac_h;
- unsigned int mac_l;
- int table;
+ if (dev->flags & IFF_PROMISC)
+ return 0;
- mac_l = (addr[4] << 8) | addr[5];
- mac_h = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | addr[3];
+ nibbles = 1 << (dev->dev_addr[5] & 0x0f);
+ for (uc_ptr = dev->uc_list; uc_ptr != NULL; uc_ptr = uc_ptr->next) {
+ if (memcmp(dev->dev_addr, uc_ptr->da_addr, 5))
+ return 0;
+ if ((dev->dev_addr[5] ^ uc_ptr->da_addr[5]) & 0xf0)
+ return 0;
- wrl(mp, MAC_ADDR_LOW(mp->port_num), mac_l);
- wrl(mp, MAC_ADDR_HIGH(mp->port_num), mac_h);
+ nibbles |= 1 << (uc_ptr->da_addr[5] & 0x0f);
+ }
- table = UNICAST_TABLE(mp->port_num);
- set_filter_table_entry(mp, table, addr[5] & 0x0f);
+ return nibbles;
}
-static int mv643xx_eth_set_mac_address(struct net_device *dev, void *addr)
+static void mv643xx_eth_program_unicast_filter(struct net_device *dev)
{
struct mv643xx_eth_private *mp = netdev_priv(dev);
+ u32 port_config;
+ u32 nibbles;
+ int i;
- /* +2 is for the offset of the HW addr type */
- memcpy(dev->dev_addr, addr + 2, 6);
-
- init_mac_tables(mp);
uc_addr_set(mp, dev->dev_addr);
- return 0;
+ port_config = rdlp(mp, PORT_CONFIG);
+ nibbles = uc_addr_filter_mask(dev);
+ if (!nibbles) {
+ port_config |= UNICAST_PROMISCUOUS_MODE;
+ wrlp(mp, PORT_CONFIG, port_config);
+ return;
+ }
+
+ for (i = 0; i < 16; i += 4) {
+ int off = UNICAST_TABLE(mp->port_num) + i;
+ u32 v;
+
+ v = 0;
+ if (nibbles & 1)
+ v |= 0x00000001;
+ if (nibbles & 2)
+ v |= 0x00000100;
+ if (nibbles & 4)
+ v |= 0x00010000;
+ if (nibbles & 8)
+ v |= 0x01000000;
+ nibbles >>= 4;
+
+ wrl(mp, off, v);
+ }
+
+ port_config &= ~UNICAST_PROMISCUOUS_MODE;
+ wrlp(mp, PORT_CONFIG, port_config);
}
static int addr_crc(unsigned char *addr)
@@ -1528,24 +1550,22 @@ static int addr_crc(unsigned char *addr)
return crc;
}
-static void mv643xx_eth_set_rx_mode(struct net_device *dev)
+static void mv643xx_eth_program_multicast_filter(struct net_device *dev)
{
struct mv643xx_eth_private *mp = netdev_priv(dev);
- u32 port_config;
+ u32 *mc_spec;
+ u32 *mc_other;
struct dev_addr_list *addr;
int i;
- port_config = rdl(mp, PORT_CONFIG(mp->port_num));
- if (dev->flags & IFF_PROMISC)
- port_config |= UNICAST_PROMISCUOUS_MODE;
- else
- port_config &= ~UNICAST_PROMISCUOUS_MODE;
- wrl(mp, PORT_CONFIG(mp->port_num), port_config);
-
if (dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) {
- int port_num = mp->port_num;
- u32 accept = 0x01010101;
+ int port_num;
+ u32 accept;
+ int i;
+oom:
+ port_num = mp->port_num;
+ accept = 0x01010101;
for (i = 0; i < 0x100; i += 4) {
wrl(mp, SPECIAL_MCAST_TABLE(port_num) + i, accept);
wrl(mp, OTHER_MCAST_TABLE(port_num) + i, accept);
@@ -1553,28 +1573,55 @@ static void mv643xx_eth_set_rx_mode(struct net_device *dev)
return;
}
- for (i = 0; i < 0x100; i += 4) {
- wrl(mp, SPECIAL_MCAST_TABLE(mp->port_num) + i, 0);
- wrl(mp, OTHER_MCAST_TABLE(mp->port_num) + i, 0);
- }
+ mc_spec = kmalloc(0x200, GFP_KERNEL);
+ if (mc_spec == NULL)
+ goto oom;
+ mc_other = mc_spec + (0x100 >> 2);
+
+ memset(mc_spec, 0, 0x100);
+ memset(mc_other, 0, 0x100);
for (addr = dev->mc_list; addr != NULL; addr = addr->next) {
u8 *a = addr->da_addr;
- int table;
-
- if (addr->da_addrlen != 6)
- continue;
+ u32 *table;
+ int entry;
if (memcmp(a, "\x01\x00\x5e\x00\x00", 5) == 0) {
- table = SPECIAL_MCAST_TABLE(mp->port_num);
- set_filter_table_entry(mp, table, a[5]);
+ table = mc_spec;
+ entry = a[5];
} else {
- int crc = addr_crc(a);
-
- table = OTHER_MCAST_TABLE(mp->port_num);
- set_filter_table_entry(mp, table, crc);
+ table = mc_other;
+ entry = addr_crc(a);
}
+
+ table[entry >> 2] |= 1 << (entry & 3);
}
+
+ for (i = 0; i < 0x100; i += 4) {
+ wrl(mp, SPECIAL_MCAST_TABLE(mp->port_num) + i, mc_spec[i >> 2]);
+ wrl(mp, OTHER_MCAST_TABLE(mp->port_num) + i, mc_other[i >> 2]);
+ }
+
+ kfree(mc_spec);
+}
+
+static void mv643xx_eth_set_rx_mode(struct net_device *dev)
+{
+ mv643xx_eth_program_unicast_filter(dev);
+ mv643xx_eth_program_multicast_filter(dev);
+}
+
+static int mv643xx_eth_set_mac_address(struct net_device *dev, void *addr)
+{
+ struct sockaddr *sa = addr;
+
+ memcpy(dev->dev_addr, sa->sa_data, ETH_ALEN);
+
+ netif_addr_lock_bh(dev);
+ mv643xx_eth_program_unicast_filter(dev);
+ netif_addr_unlock_bh(dev);
+
+ return 0;
}
@@ -1758,26 +1805,25 @@ static int mv643xx_eth_collect_events(struct mv643xx_eth_private *mp)
u32 int_cause;
u32 int_cause_ext;
- int_cause = rdl(mp, INT_CAUSE(mp->port_num)) &
- (INT_TX_END | INT_RX | INT_EXT);
+ int_cause = rdlp(mp, INT_CAUSE) & (INT_TX_END | INT_RX | INT_EXT);
if (int_cause == 0)
return 0;
int_cause_ext = 0;
if (int_cause & INT_EXT)
- int_cause_ext = rdl(mp, INT_CAUSE_EXT(mp->port_num));
+ int_cause_ext = rdlp(mp, INT_CAUSE_EXT);
int_cause &= INT_TX_END | INT_RX;
if (int_cause) {
- wrl(mp, INT_CAUSE(mp->port_num), ~int_cause);
+ wrlp(mp, INT_CAUSE, ~int_cause);
mp->work_tx_end |= ((int_cause & INT_TX_END) >> 19) &
- ~(rdl(mp, TXQ_COMMAND(mp->port_num)) & 0xff);
+ ~(rdlp(mp, TXQ_COMMAND) & 0xff);
mp->work_rx |= (int_cause & INT_RX) >> 2;
}
int_cause_ext &= INT_EXT_LINK_PHY | INT_EXT_TX;
if (int_cause_ext) {
- wrl(mp, INT_CAUSE_EXT(mp->port_num), ~int_cause_ext);
+ wrlp(mp, INT_CAUSE_EXT, ~int_cause_ext);
if (int_cause_ext & INT_EXT_LINK_PHY)
mp->work_link = 1;
mp->work_tx |= int_cause_ext & INT_EXT_TX;
@@ -1794,7 +1840,7 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id)
if (unlikely(!mv643xx_eth_collect_events(mp)))
return IRQ_NONE;
- wrl(mp, INT_MASK(mp->port_num), 0);
+ wrlp(mp, INT_MASK, 0);
napi_schedule(&mp->napi);
return IRQ_HANDLED;
@@ -1808,7 +1854,7 @@ static void handle_link_event(struct mv643xx_eth_private *mp)
int duplex;
int fc;
- port_status = rdl(mp, PORT_STATUS(mp->port_num));
+ port_status = rdlp(mp, PORT_STATUS);
if (!(port_status & LINK_UP)) {
if (netif_carrier_ok(dev)) {
int i;
@@ -1908,7 +1954,7 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget)
if (mp->work_rx_oom)
mod_timer(&mp->rx_oom, jiffies + (HZ / 10));
napi_complete(napi);
- wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_EXT);
+ wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT);
}
return work_done;
@@ -1957,17 +2003,17 @@ static void port_start(struct mv643xx_eth_private *mp)
/*
* Configure basic link parameters.
*/
- pscr = rdl(mp, PORT_SERIAL_CONTROL(mp->port_num));
+ pscr = rdlp(mp, PORT_SERIAL_CONTROL);
pscr |= SERIAL_PORT_ENABLE;
- wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr);
+ wrlp(mp, PORT_SERIAL_CONTROL, pscr);
pscr |= DO_NOT_FORCE_LINK_FAIL;
if (mp->phy == NULL)
pscr |= FORCE_LINK_PASS;
- wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr);
+ wrlp(mp, PORT_SERIAL_CONTROL, pscr);
- wrl(mp, SDMA_CONFIG(mp->port_num), PORT_SDMA_CONFIG_DEFAULT_VALUE);
+ wrlp(mp, SDMA_CONFIG, PORT_SDMA_CONFIG_DEFAULT_VALUE);
/*
* Configure TX path and queues.
@@ -1984,31 +2030,30 @@ static void port_start(struct mv643xx_eth_private *mp)
/*
* Add configured unicast address to address filter table.
*/
- uc_addr_set(mp, mp->dev->dev_addr);
+ mv643xx_eth_program_unicast_filter(mp->dev);
/*
* Receive all unmatched unicast, TCP, UDP, BPDU and broadcast
* frames to RX queue #0, and include the pseudo-header when
* calculating receive checksums.
*/
- wrl(mp, PORT_CONFIG(mp->port_num), 0x02000000);
+ wrlp(mp, PORT_CONFIG, 0x02000000);
/*
* Treat BPDUs as normal multicasts, and disable partition mode.
*/
- wrl(mp, PORT_CONFIG_EXT(mp->port_num), 0x00000000);
+ wrlp(mp, PORT_CONFIG_EXT, 0x00000000);
/*
* Enable the receive queues.
*/
for (i = 0; i < mp->rxq_count; i++) {
struct rx_queue *rxq = mp->rxq + i;
- int off = RXQ_CURRENT_DESC_PTR(mp->port_num, i);
u32 addr;
addr = (u32)rxq->rx_desc_dma;
addr += rxq->rx_curr_desc * sizeof(struct rx_desc);
- wrl(mp, off, addr);
+ wrlp(mp, RXQ_CURRENT_DESC_PTR(i), addr);
rxq_enable(rxq);
}
@@ -2019,7 +2064,7 @@ static void set_rx_coal(struct mv643xx_eth_private *mp, unsigned int delay)
unsigned int coal = ((mp->shared->t_clk / 1000000) * delay) / 64;
u32 val;
- val = rdl(mp, SDMA_CONFIG(mp->port_num));
+ val = rdlp(mp, SDMA_CONFIG);
if (mp->shared->extended_rx_coal_limit) {
if (coal > 0xffff)
coal = 0xffff;
@@ -2032,7 +2077,7 @@ static void set_rx_coal(struct mv643xx_eth_private *mp, unsigned int delay)
val &= ~0x003fff00;
val |= (coal & 0x3fff) << 8;
}
- wrl(mp, SDMA_CONFIG(mp->port_num), val);
+ wrlp(mp, SDMA_CONFIG, val);
}
static void set_tx_coal(struct mv643xx_eth_private *mp, unsigned int delay)
@@ -2041,7 +2086,7 @@ static void set_tx_coal(struct mv643xx_eth_private *mp, unsigned int delay)
if (coal > 0x3fff)
coal = 0x3fff;
- wrl(mp, TX_FIFO_URGENT_THRESHOLD(mp->port_num), (coal & 0x3fff) << 4);
+ wrlp(mp, TX_FIFO_URGENT_THRESHOLD, (coal & 0x3fff) << 4);
}
static void mv643xx_eth_recalc_skb_size(struct mv643xx_eth_private *mp)
@@ -2070,9 +2115,9 @@ static int mv643xx_eth_open(struct net_device *dev)
int err;
int i;
- wrl(mp, INT_CAUSE(mp->port_num), 0);
- wrl(mp, INT_CAUSE_EXT(mp->port_num), 0);
- rdl(mp, INT_CAUSE_EXT(mp->port_num));
+ wrlp(mp, INT_CAUSE, 0);
+ wrlp(mp, INT_CAUSE_EXT, 0);
+ rdlp(mp, INT_CAUSE_EXT);
err = request_irq(dev->irq, mv643xx_eth_irq,
IRQF_SHARED, dev->name, dev);
@@ -2081,8 +2126,6 @@ static int mv643xx_eth_open(struct net_device *dev)
return -EAGAIN;
}
- init_mac_tables(mp);
-
mv643xx_eth_recalc_skb_size(mp);
napi_enable(&mp->napi);
@@ -2121,8 +2164,8 @@ static int mv643xx_eth_open(struct net_device *dev)
set_rx_coal(mp, 0);
set_tx_coal(mp, 0);
- wrl(mp, INT_MASK_EXT(mp->port_num), INT_EXT_LINK_PHY | INT_EXT_TX);
- wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_EXT);
+ wrlp(mp, INT_MASK_EXT, INT_EXT_LINK_PHY | INT_EXT_TX);
+ wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT);
return 0;
@@ -2147,7 +2190,7 @@ static void port_reset(struct mv643xx_eth_private *mp)
txq_disable(mp->txq + i);
while (1) {
- u32 ps = rdl(mp, PORT_STATUS(mp->port_num));
+ u32 ps = rdlp(mp, PORT_STATUS);
if ((ps & (TX_IN_PROGRESS | TX_FIFO_EMPTY)) == TX_FIFO_EMPTY)
break;
@@ -2155,11 +2198,11 @@ static void port_reset(struct mv643xx_eth_private *mp)
}
/* Reset the Enable bit in the Configuration Register */
- data = rdl(mp, PORT_SERIAL_CONTROL(mp->port_num));
+ data = rdlp(mp, PORT_SERIAL_CONTROL);
data &= ~(SERIAL_PORT_ENABLE |
DO_NOT_FORCE_LINK_FAIL |
FORCE_LINK_PASS);
- wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), data);
+ wrlp(mp, PORT_SERIAL_CONTROL, data);
}
static int mv643xx_eth_stop(struct net_device *dev)
@@ -2167,8 +2210,8 @@ static int mv643xx_eth_stop(struct net_device *dev)
struct mv643xx_eth_private *mp = netdev_priv(dev);
int i;
- wrl(mp, INT_MASK(mp->port_num), 0x00000000);
- rdl(mp, INT_MASK(mp->port_num));
+ wrlp(mp, INT_MASK, 0x00000000);
+ rdlp(mp, INT_MASK);
del_timer_sync(&mp->mib_counters_timer);
@@ -2261,12 +2304,12 @@ static void mv643xx_eth_netpoll(struct net_device *dev)
{
struct mv643xx_eth_private *mp = netdev_priv(dev);
- wrl(mp, INT_MASK(mp->port_num), 0x00000000);
- rdl(mp, INT_MASK(mp->port_num));
+ wrlp(mp, INT_MASK, 0x00000000);
+ rdlp(mp, INT_MASK);
mv643xx_eth_irq(dev->irq, dev);
- wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_EXT);
+ wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT);
}
#endif
@@ -2314,8 +2357,8 @@ static void infer_hw_params(struct mv643xx_eth_shared_private *msp)
* [21:8], or a 16-bit coal limit in bits [25,21:7] of the
* SDMA config register.
*/
- writel(0x02000000, msp->base + SDMA_CONFIG(0));
- if (readl(msp->base + SDMA_CONFIG(0)) & 0x02000000)
+ writel(0x02000000, msp->base + 0x0400 + SDMA_CONFIG);
+ if (readl(msp->base + 0x0400 + SDMA_CONFIG) & 0x02000000)
msp->extended_rx_coal_limit = 1;
else
msp->extended_rx_coal_limit = 0;
@@ -2325,12 +2368,12 @@ static void infer_hw_params(struct mv643xx_eth_shared_private *msp)
* yes, whether its associated registers are in the old or
* the new place.
*/
- writel(1, msp->base + TX_BW_MTU_MOVED(0));
- if (readl(msp->base + TX_BW_MTU_MOVED(0)) & 1) {
+ writel(1, msp->base + 0x0400 + TX_BW_MTU_MOVED);
+ if (readl(msp->base + 0x0400 + TX_BW_MTU_MOVED) & 1) {
msp->tx_bw_control = TX_BW_CONTROL_NEW_LAYOUT;
} else {
- writel(7, msp->base + TX_BW_RATE(0));
- if (readl(msp->base + TX_BW_RATE(0)) & 7)
+ writel(7, msp->base + 0x0400 + TX_BW_RATE);
+ if (readl(msp->base + 0x0400 + TX_BW_RATE) & 7)
msp->tx_bw_control = TX_BW_CONTROL_OLD_LAYOUT;
else
msp->tx_bw_control = TX_BW_CONTROL_ABSENT;
@@ -2339,7 +2382,7 @@ static void infer_hw_params(struct mv643xx_eth_shared_private *msp)
static int mv643xx_eth_shared_probe(struct platform_device *pdev)
{
- static int mv643xx_eth_version_printed = 0;
+ static int mv643xx_eth_version_printed;
struct mv643xx_eth_shared_platform_data *pd = pdev->dev.platform_data;
struct mv643xx_eth_shared_private *msp;
struct resource *res;
@@ -2563,10 +2606,10 @@ static void init_pscr(struct mv643xx_eth_private *mp, int speed, int duplex)
{
u32 pscr;
- pscr = rdl(mp, PORT_SERIAL_CONTROL(mp->port_num));
+ pscr = rdlp(mp, PORT_SERIAL_CONTROL);
if (pscr & SERIAL_PORT_ENABLE) {
pscr &= ~SERIAL_PORT_ENABLE;
- wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr);
+ wrlp(mp, PORT_SERIAL_CONTROL, pscr);
}
pscr = MAX_RX_PACKET_9700BYTE | SERIAL_PORT_CONTROL_RESERVED;
@@ -2584,7 +2627,7 @@ static void init_pscr(struct mv643xx_eth_private *mp, int speed, int duplex)
pscr |= SET_FULL_DUPLEX_MODE;
}
- wrl(mp, PORT_SERIAL_CONTROL(mp->port_num), pscr);
+ wrlp(mp, PORT_SERIAL_CONTROL, pscr);
}
static int mv643xx_eth_probe(struct platform_device *pdev)
@@ -2593,7 +2636,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
struct mv643xx_eth_private *mp;
struct net_device *dev;
struct resource *res;
- DECLARE_MAC_BUF(mac);
int err;
pd = pdev->dev.platform_data;
@@ -2617,6 +2659,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, mp);
mp->shared = platform_get_drvdata(pd->shared);
+ mp->base = mp->shared->base + 0x0400 + (pd->port_number << 10);
mp->port_num = pd->port_number;
mp->dev = dev;
@@ -2664,7 +2707,7 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
dev->hard_start_xmit = mv643xx_eth_xmit;
dev->open = mv643xx_eth_open;
dev->stop = mv643xx_eth_stop;
- dev->set_multicast_list = mv643xx_eth_set_rx_mode;
+ dev->set_rx_mode = mv643xx_eth_set_rx_mode;
dev->set_mac_address = mv643xx_eth_set_mac_address;
dev->do_ioctl = mv643xx_eth_ioctl;
dev->change_mtu = mv643xx_eth_change_mtu;
@@ -2687,8 +2730,8 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
if (err)
goto out;
- dev_printk(KERN_NOTICE, &dev->dev, "port %d with MAC address %s\n",
- mp->port_num, print_mac(mac, dev->dev_addr));
+ dev_printk(KERN_NOTICE, &dev->dev, "port %d with MAC address %pM\n",
+ mp->port_num, dev->dev_addr);
if (mp->tx_desc_sram_size > 0)
dev_printk(KERN_NOTICE, &dev->dev, "configured with sram\n");
@@ -2721,8 +2764,8 @@ static void mv643xx_eth_shutdown(struct platform_device *pdev)
struct mv643xx_eth_private *mp = platform_get_drvdata(pdev);
/* Mask all interrupts on ethernet port */
- wrl(mp, INT_MASK(mp->port_num), 0);
- rdl(mp, INT_MASK(mp->port_num));
+ wrlp(mp, INT_MASK, 0);
+ rdlp(mp, INT_MASK);
if (netif_running(mp->dev))
port_reset(mp);
diff --git a/drivers/net/mvme147.c b/drivers/net/mvme147.c
index 06ca4252155f..435e5a847c43 100644
--- a/drivers/net/mvme147.c
+++ b/drivers/net/mvme147.c
@@ -67,7 +67,6 @@ struct net_device * __init mvme147lance_probe(int unit)
u_long *addr;
u_long address;
int err;
- DECLARE_MAC_BUF(mac);
if (!MACH_IS_MVME147 || called)
return ERR_PTR(-ENODEV);
@@ -102,11 +101,11 @@ struct net_device * __init mvme147lance_probe(int unit)
dev->dev_addr[3]=address&0xff;
printk("%s: MVME147 at 0x%08lx, irq %d, "
- "Hardware Address %s\n",
+ "Hardware Address %pM\n",
dev->name, dev->base_addr, MVME147_LANCE_IRQ,
- print_mac(mac, dev->dev_addr));
+ dev->dev_addr);
- lp = (struct m147lance_private *)dev->priv;
+ lp = netdev_priv(dev);
lp->ram = __get_dma_pages(GFP_ATOMIC, 3); /* 16K */
if (!lp->ram)
{
@@ -190,7 +189,7 @@ int __init init_module(void)
void __exit cleanup_module(void)
{
- struct m147lance_private *lp = dev_mvme147_lance->priv;
+ struct m147lance_private *lp = netdev_priv(dev_mvme147_lance);
unregister_netdev(dev_mvme147_lance);
free_pages(lp->ram, 3);
free_netdev(dev_mvme147_lance);
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index b37867097308..5e70180bf569 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -75,7 +75,7 @@
#include "myri10ge_mcp.h"
#include "myri10ge_mcp_gen_header.h"
-#define MYRI10GE_VERSION_STR "1.4.3-1.378"
+#define MYRI10GE_VERSION_STR "1.4.4-1.395"
MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -1024,7 +1024,7 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
ss->dca_tag = NULL;
}
}
-#endif /* CONFIG_DCA */
+#endif /* CONFIG_MYRI10GE_DCA */
/* reset mcp/driver shared state back to 0 */
@@ -1121,7 +1121,7 @@ static int myri10ge_notify_dca_device(struct device *dev, void *data)
myri10ge_teardown_dca(mgp);
return 0;
}
-#endif /* CONFIG_DCA */
+#endif /* CONFIG_MYRI10GE_DCA */
static inline void
myri10ge_submit_8rx(struct mcp_kreq_ether_recv __iomem * dst,
@@ -1309,7 +1309,7 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, struct myri10ge_rx_buf *rx,
skb = netdev_alloc_skb(dev, MYRI10GE_HLEN + 16);
if (unlikely(skb == NULL)) {
- mgp->stats.rx_dropped++;
+ ss->stats.rx_dropped++;
do {
i--;
put_page(rx_frags[i].page);
@@ -1334,7 +1334,6 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, struct myri10ge_rx_buf *rx,
myri10ge_vlan_ip_csum(skb, csum);
}
netif_receive_skb(skb);
- dev->last_rx = jiffies;
return 1;
}
@@ -1504,7 +1503,6 @@ static int myri10ge_poll(struct napi_struct *napi, int budget)
{
struct myri10ge_slice_state *ss =
container_of(napi, struct myri10ge_slice_state, napi);
- struct net_device *netdev = ss->mgp->dev;
int work_done;
#ifdef CONFIG_MYRI10GE_DCA
@@ -1516,7 +1514,7 @@ static int myri10ge_poll(struct napi_struct *napi, int budget)
work_done = myri10ge_clean_rx_done(ss, budget);
if (work_done < budget) {
- netif_rx_complete(netdev, napi);
+ netif_rx_complete(napi);
put_be32(htonl(3), ss->irq_claim);
}
return work_done;
@@ -1534,7 +1532,7 @@ static irqreturn_t myri10ge_intr(int irq, void *arg)
/* an interrupt on a non-zero receive-only slice is implicitly
* valid since MSI-X irqs are not shared */
if ((mgp->dev->real_num_tx_queues == 1) && (ss != mgp->ss)) {
- netif_rx_schedule(ss->dev, &ss->napi);
+ netif_rx_schedule(&ss->napi);
return (IRQ_HANDLED);
}
@@ -1545,7 +1543,7 @@ static irqreturn_t myri10ge_intr(int irq, void *arg)
/* low bit indicates receives are present, so schedule
* napi poll handler */
if (stats->valid & 1)
- netif_rx_schedule(ss->dev, &ss->napi);
+ netif_rx_schedule(&ss->napi);
if (!mgp->msi_enabled && !mgp->msix_enabled) {
put_be32(0, mgp->irq_deassert);
@@ -2230,6 +2228,8 @@ myri10ge_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr,
*ip_hdr = iph;
if (iph->protocol != IPPROTO_TCP)
return -1;
+ if (iph->frag_off & htons(IP_MF | IP_OFFSET))
+ return -1;
*hdr_flags |= LRO_TCP;
*tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2);
@@ -2927,6 +2927,7 @@ static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev)
{
struct sk_buff *segs, *curr;
struct myri10ge_priv *mgp = netdev_priv(dev);
+ struct myri10ge_slice_state *ss;
int status;
segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO6);
@@ -2953,8 +2954,9 @@ static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev)
return 0;
drop:
+ ss = &mgp->ss[skb_get_queue_mapping(skb)];
dev_kfree_skb_any(skb);
- mgp->stats.tx_dropped += 1;
+ ss->stats.tx_dropped += 1;
return 0;
}
@@ -2985,7 +2987,6 @@ static void myri10ge_set_multicast_list(struct net_device *dev)
struct dev_mc_list *mc_list;
__be32 data[2] = { 0, 0 };
int err;
- DECLARE_MAC_BUF(mac);
/* can be called from atomic contexts,
* pass 1 to force atomicity in myri10ge_send_cmd() */
@@ -3032,8 +3033,7 @@ static void myri10ge_set_multicast_list(struct net_device *dev)
printk(KERN_ERR "myri10ge: %s: Failed "
"MXGEFW_JOIN_MULTICAST_GROUP, error status:"
"%d\t", dev->name, err);
- printk(KERN_ERR "MAC %s\n",
- print_mac(mac, mc_list->dmi_addr));
+ printk(KERN_ERR "MAC %pM\n", mc_list->dmi_addr);
goto abort;
}
}
@@ -3732,6 +3732,17 @@ abort_with_fw:
myri10ge_load_firmware(mgp, 0);
}
+static const struct net_device_ops myri10ge_netdev_ops = {
+ .ndo_open = myri10ge_open,
+ .ndo_stop = myri10ge_close,
+ .ndo_start_xmit = myri10ge_xmit,
+ .ndo_get_stats = myri10ge_get_stats,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = myri10ge_change_mtu,
+ .ndo_set_multicast_list = myri10ge_set_multicast_list,
+ .ndo_set_mac_address = myri10ge_set_mac_address,
+};
+
static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
struct net_device *netdev;
@@ -3740,6 +3751,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
int i;
int status = -ENXIO;
int dac_enabled;
+ unsigned hdr_offset, ss_offset;
netdev = alloc_etherdev_mq(sizeof(*mgp), MYRI10GE_MAX_SLICES);
if (netdev == NULL) {
@@ -3807,14 +3819,6 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (mgp->mtrr >= 0)
mgp->wc_enabled = 1;
#endif
- /* Hack. need to get rid of these magic numbers */
- mgp->sram_size =
- 2 * 1024 * 1024 - (2 * (48 * 1024) + (32 * 1024)) - 0x100;
- if (mgp->sram_size > mgp->board_span) {
- dev_err(&pdev->dev, "board span %ld bytes too small\n",
- mgp->board_span);
- goto abort_with_mtrr;
- }
mgp->sram = ioremap_wc(mgp->iomem_base, mgp->board_span);
if (mgp->sram == NULL) {
dev_err(&pdev->dev, "ioremap failed for %ld bytes at 0x%lx\n",
@@ -3822,9 +3826,19 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
status = -ENXIO;
goto abort_with_mtrr;
}
+ hdr_offset =
+ ntohl(__raw_readl(mgp->sram + MCP_HEADER_PTR_OFFSET)) & 0xffffc;
+ ss_offset = hdr_offset + offsetof(struct mcp_gen_header, string_specs);
+ mgp->sram_size = ntohl(__raw_readl(mgp->sram + ss_offset));
+ if (mgp->sram_size > mgp->board_span ||
+ mgp->sram_size <= MYRI10GE_FW_OFFSET) {
+ dev_err(&pdev->dev,
+ "invalid sram_size %dB or board span %ldB\n",
+ mgp->sram_size, mgp->board_span);
+ goto abort_with_ioremap;
+ }
memcpy_fromio(mgp->eeprom_strings,
- mgp->sram + mgp->sram_size - MYRI10GE_EEPROM_STRINGS_SIZE,
- MYRI10GE_EEPROM_STRINGS_SIZE);
+ mgp->sram + mgp->sram_size, MYRI10GE_EEPROM_STRINGS_SIZE);
memset(mgp->eeprom_strings + MYRI10GE_EEPROM_STRINGS_SIZE - 2, 0, 2);
status = myri10ge_read_mac_addr(mgp);
if (status)
@@ -3860,15 +3874,10 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN;
if ((myri10ge_initial_mtu + ETH_HLEN) < 68)
myri10ge_initial_mtu = 68;
+
+ netdev->netdev_ops = &myri10ge_netdev_ops;
netdev->mtu = myri10ge_initial_mtu;
- netdev->open = myri10ge_open;
- netdev->stop = myri10ge_close;
- netdev->hard_start_xmit = myri10ge_xmit;
- netdev->get_stats = myri10ge_get_stats;
netdev->base_addr = mgp->iomem_base;
- netdev->change_mtu = myri10ge_change_mtu;
- netdev->set_multicast_list = myri10ge_set_multicast_list;
- netdev->set_mac_address = myri10ge_set_mac_address;
netdev->features = mgp->features;
if (dac_enabled)
@@ -4019,7 +4028,7 @@ static struct notifier_block myri10ge_dca_notifier = {
.next = NULL,
.priority = 0,
};
-#endif /* CONFIG_DCA */
+#endif /* CONFIG_MYRI10GE_DCA */
static __init int myri10ge_init_module(void)
{
diff --git a/drivers/net/myri10ge/myri10ge_mcp.h b/drivers/net/myri10ge/myri10ge_mcp.h
index 993721090777..11be150e4d67 100644
--- a/drivers/net/myri10ge/myri10ge_mcp.h
+++ b/drivers/net/myri10ge/myri10ge_mcp.h
@@ -111,61 +111,61 @@ enum myri10ge_mcp_cmd_type {
MXGEFW_CMD_NONE = 0,
/* Reset the mcp, it is left in a safe state, waiting
* for the driver to set all its parameters */
- MXGEFW_CMD_RESET,
+ MXGEFW_CMD_RESET = 1,
/* get the version number of the current firmware..
* (may be available in the eeprom strings..? */
- MXGEFW_GET_MCP_VERSION,
+ MXGEFW_GET_MCP_VERSION = 2,
/* Parameters which must be set by the driver before it can
* issue MXGEFW_CMD_ETHERNET_UP. They persist until the next
* MXGEFW_CMD_RESET is issued */
- MXGEFW_CMD_SET_INTRQ_DMA,
+ MXGEFW_CMD_SET_INTRQ_DMA = 3,
/* data0 = LSW of the host address
* data1 = MSW of the host address
* data2 = slice number if multiple slices are used
*/
- MXGEFW_CMD_SET_BIG_BUFFER_SIZE, /* in bytes, power of 2 */
- MXGEFW_CMD_SET_SMALL_BUFFER_SIZE, /* in bytes */
+ MXGEFW_CMD_SET_BIG_BUFFER_SIZE = 4, /* in bytes, power of 2 */
+ MXGEFW_CMD_SET_SMALL_BUFFER_SIZE = 5, /* in bytes */
/* Parameters which refer to lanai SRAM addresses where the
* driver must issue PIO writes for various things */
- MXGEFW_CMD_GET_SEND_OFFSET,
- MXGEFW_CMD_GET_SMALL_RX_OFFSET,
- MXGEFW_CMD_GET_BIG_RX_OFFSET,
+ MXGEFW_CMD_GET_SEND_OFFSET = 6,
+ MXGEFW_CMD_GET_SMALL_RX_OFFSET = 7,
+ MXGEFW_CMD_GET_BIG_RX_OFFSET = 8,
/* data0 = slice number if multiple slices are used */
- MXGEFW_CMD_GET_IRQ_ACK_OFFSET,
- MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET,
+ MXGEFW_CMD_GET_IRQ_ACK_OFFSET = 9,
+ MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET = 10,
/* Parameters which refer to rings stored on the MCP,
* and whose size is controlled by the mcp */
- MXGEFW_CMD_GET_SEND_RING_SIZE, /* in bytes */
- MXGEFW_CMD_GET_RX_RING_SIZE, /* in bytes */
+ MXGEFW_CMD_GET_SEND_RING_SIZE = 11, /* in bytes */
+ MXGEFW_CMD_GET_RX_RING_SIZE = 12, /* in bytes */
/* Parameters which refer to rings stored in the host,
* and whose size is controlled by the host. Note that
* all must be physically contiguous and must contain
* a power of 2 number of entries. */
- MXGEFW_CMD_SET_INTRQ_SIZE, /* in bytes */
+ MXGEFW_CMD_SET_INTRQ_SIZE = 13, /* in bytes */
#define MXGEFW_CMD_SET_INTRQ_SIZE_FLAG_NO_STRICT_SIZE_CHECK (1 << 31)
/* command to bring ethernet interface up. Above parameters
* (plus mtu & mac address) must have been exchanged prior
* to issuing this command */
- MXGEFW_CMD_ETHERNET_UP,
+ MXGEFW_CMD_ETHERNET_UP = 14,
/* command to bring ethernet interface down. No further sends
* or receives may be processed until an MXGEFW_CMD_ETHERNET_UP
* is issued, and all interrupt queues must be flushed prior
* to ack'ing this command */
- MXGEFW_CMD_ETHERNET_DOWN,
+ MXGEFW_CMD_ETHERNET_DOWN = 15,
/* commands the driver may issue live, without resetting
* the nic. Note that increasing the mtu "live" should
@@ -173,40 +173,40 @@ enum myri10ge_mcp_cmd_type {
* sufficiently large to handle the new mtu. Decreasing
* the mtu live is safe */
- MXGEFW_CMD_SET_MTU,
- MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET, /* in microseconds */
- MXGEFW_CMD_SET_STATS_INTERVAL, /* in microseconds */
- MXGEFW_CMD_SET_STATS_DMA_OBSOLETE, /* replaced by SET_STATS_DMA_V2 */
+ MXGEFW_CMD_SET_MTU = 16,
+ MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET = 17, /* in microseconds */
+ MXGEFW_CMD_SET_STATS_INTERVAL = 18, /* in microseconds */
+ MXGEFW_CMD_SET_STATS_DMA_OBSOLETE = 19, /* replaced by SET_STATS_DMA_V2 */
- MXGEFW_ENABLE_PROMISC,
- MXGEFW_DISABLE_PROMISC,
- MXGEFW_SET_MAC_ADDRESS,
+ MXGEFW_ENABLE_PROMISC = 20,
+ MXGEFW_DISABLE_PROMISC = 21,
+ MXGEFW_SET_MAC_ADDRESS = 22,
- MXGEFW_ENABLE_FLOW_CONTROL,
- MXGEFW_DISABLE_FLOW_CONTROL,
+ MXGEFW_ENABLE_FLOW_CONTROL = 23,
+ MXGEFW_DISABLE_FLOW_CONTROL = 24,
/* do a DMA test
* data0,data1 = DMA address
* data2 = RDMA length (MSH), WDMA length (LSH)
* command return data = repetitions (MSH), 0.5-ms ticks (LSH)
*/
- MXGEFW_DMA_TEST,
+ MXGEFW_DMA_TEST = 25,
- MXGEFW_ENABLE_ALLMULTI,
- MXGEFW_DISABLE_ALLMULTI,
+ MXGEFW_ENABLE_ALLMULTI = 26,
+ MXGEFW_DISABLE_ALLMULTI = 27,
/* returns MXGEFW_CMD_ERROR_MULTICAST
* if there is no room in the cache
* data0,MSH(data1) = multicast group address */
- MXGEFW_JOIN_MULTICAST_GROUP,
+ MXGEFW_JOIN_MULTICAST_GROUP = 28,
/* returns MXGEFW_CMD_ERROR_MULTICAST
* if the address is not in the cache,
* or is equal to FF-FF-FF-FF-FF-FF
* data0,MSH(data1) = multicast group address */
- MXGEFW_LEAVE_MULTICAST_GROUP,
- MXGEFW_LEAVE_ALL_MULTICAST_GROUPS,
+ MXGEFW_LEAVE_MULTICAST_GROUP = 29,
+ MXGEFW_LEAVE_ALL_MULTICAST_GROUPS = 30,
- MXGEFW_CMD_SET_STATS_DMA_V2,
+ MXGEFW_CMD_SET_STATS_DMA_V2 = 31,
/* data0, data1 = bus addr,
* data2 = sizeof(struct mcp_irq_data) from driver point of view, allows
* adding new stuff to mcp_irq_data without changing the ABI
@@ -216,14 +216,14 @@ enum myri10ge_mcp_cmd_type {
* (in the upper 16 bits).
*/
- MXGEFW_CMD_UNALIGNED_TEST,
+ MXGEFW_CMD_UNALIGNED_TEST = 32,
/* same than DMA_TEST (same args) but abort with UNALIGNED on unaligned
* chipset */
- MXGEFW_CMD_UNALIGNED_STATUS,
+ MXGEFW_CMD_UNALIGNED_STATUS = 33,
/* return data = boolean, true if the chipset is known to be unaligned */
- MXGEFW_CMD_ALWAYS_USE_N_BIG_BUFFERS,
+ MXGEFW_CMD_ALWAYS_USE_N_BIG_BUFFERS = 34,
/* data0 = number of big buffers to use. It must be 0 or a power of 2.
* 0 indicates that the NIC consumes as many buffers as they are required
* for packet. This is the default behavior.
@@ -233,8 +233,8 @@ enum myri10ge_mcp_cmd_type {
* the NIC to be able to receive maximum-sized packets.
*/
- MXGEFW_CMD_GET_MAX_RSS_QUEUES,
- MXGEFW_CMD_ENABLE_RSS_QUEUES,
+ MXGEFW_CMD_GET_MAX_RSS_QUEUES = 35,
+ MXGEFW_CMD_ENABLE_RSS_QUEUES = 36,
/* data0 = number of slices n (0, 1, ..., n-1) to enable
* data1 = interrupt mode | use of multiple transmit queues.
* 0=share one INTx/MSI.
@@ -249,18 +249,18 @@ enum myri10ge_mcp_cmd_type {
#define MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE 0x1
#define MXGEFW_SLICE_ENABLE_MULTIPLE_TX_QUEUES 0x2
- MXGEFW_CMD_GET_RSS_SHARED_INTERRUPT_MASK_OFFSET,
- MXGEFW_CMD_SET_RSS_SHARED_INTERRUPT_DMA,
+ MXGEFW_CMD_GET_RSS_SHARED_INTERRUPT_MASK_OFFSET = 37,
+ MXGEFW_CMD_SET_RSS_SHARED_INTERRUPT_DMA = 38,
/* data0, data1 = bus address lsw, msw */
- MXGEFW_CMD_GET_RSS_TABLE_OFFSET,
+ MXGEFW_CMD_GET_RSS_TABLE_OFFSET = 39,
/* get the offset of the indirection table */
- MXGEFW_CMD_SET_RSS_TABLE_SIZE,
+ MXGEFW_CMD_SET_RSS_TABLE_SIZE = 40,
/* set the size of the indirection table */
- MXGEFW_CMD_GET_RSS_KEY_OFFSET,
+ MXGEFW_CMD_GET_RSS_KEY_OFFSET = 41,
/* get the offset of the secret key */
- MXGEFW_CMD_RSS_KEY_UPDATED,
+ MXGEFW_CMD_RSS_KEY_UPDATED = 42,
/* tell nic that the secret key's been updated */
- MXGEFW_CMD_SET_RSS_ENABLE,
+ MXGEFW_CMD_SET_RSS_ENABLE = 43,
/* data0 = enable/disable rss
* 0: disable rss. nic does not distribute receive packets.
* 1: enable rss. nic distributes receive packets among queues.
@@ -277,7 +277,7 @@ enum myri10ge_mcp_cmd_type {
#define MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT 0x5
#define MXGEFW_RSS_HASH_TYPE_MAX 0x5
- MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE,
+ MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE = 44,
/* Return data = the max. size of the entire headers of a IPv6 TSO packet.
* If the header size of a IPv6 TSO packet is larger than the specified
* value, then the driver must not use TSO.
@@ -286,7 +286,7 @@ enum myri10ge_mcp_cmd_type {
* always has enough header buffer to store maximum-sized headers.
*/
- MXGEFW_CMD_SET_TSO_MODE,
+ MXGEFW_CMD_SET_TSO_MODE = 45,
/* data0 = TSO mode.
* 0: Linux/FreeBSD style (NIC default)
* 1: NDIS/NetBSD style
@@ -294,33 +294,37 @@ enum myri10ge_mcp_cmd_type {
#define MXGEFW_TSO_MODE_LINUX 0
#define MXGEFW_TSO_MODE_NDIS 1
- MXGEFW_CMD_MDIO_READ,
+ MXGEFW_CMD_MDIO_READ = 46,
/* data0 = dev_addr (PMA/PMD or PCS ...), data1 = register/addr */
- MXGEFW_CMD_MDIO_WRITE,
+ MXGEFW_CMD_MDIO_WRITE = 47,
/* data0 = dev_addr, data1 = register/addr, data2 = value */
- MXGEFW_CMD_XFP_I2C_READ,
- /* Starts to get a fresh copy of one byte or of the whole xfp i2c table, the
+ MXGEFW_CMD_I2C_READ = 48,
+ /* Starts to get a fresh copy of one byte or of the module i2c table, the
* obtained data is cached inside the xaui-xfi chip :
- * data0 : "all" flag : 0 => get one byte, 1=> get 256 bytes,
- * data1 : if (data0 == 0): index of byte to refresh [ not used otherwise ]
+ * data0 : 0 => get one byte, 1=> get 256 bytes
+ * data1 : If data0 == 0: location to refresh
+ * bit 7:0 register location
+ * bit 8:15 is the i2c slave addr (0 is interpreted as 0xA1)
+ * bit 23:16 is the i2c bus number (for multi-port NICs)
+ * If data0 == 1: unused
* The operation might take ~1ms for a single byte or ~65ms when refreshing all 256 bytes
- * During the i2c operation, MXGEFW_CMD_XFP_I2C_READ or MXGEFW_CMD_XFP_BYTE attempts
+ * During the i2c operation, MXGEFW_CMD_I2C_READ or MXGEFW_CMD_I2C_BYTE attempts
* will return MXGEFW_CMD_ERROR_BUSY
*/
- MXGEFW_CMD_XFP_BYTE,
+ MXGEFW_CMD_I2C_BYTE = 49,
/* Return the last obtained copy of a given byte in the xfp i2c table
- * (copy cached during the last relevant MXGEFW_CMD_XFP_I2C_READ)
+ * (copy cached during the last relevant MXGEFW_CMD_I2C_READ)
* data0 : index of the desired table entry
* Return data = the byte stored at the requested index in the table
*/
- MXGEFW_CMD_GET_VPUMP_OFFSET,
+ MXGEFW_CMD_GET_VPUMP_OFFSET = 50,
/* Return data = NIC memory offset of mcp_vpump_public_global */
- MXGEFW_CMD_RESET_VPUMP,
+ MXGEFW_CMD_RESET_VPUMP = 51,
/* Resets the VPUMP state */
- MXGEFW_CMD_SET_RSS_MCP_SLOT_TYPE,
+ MXGEFW_CMD_SET_RSS_MCP_SLOT_TYPE = 52,
/* data0 = mcp_slot type to use.
* 0 = the default 4B mcp_slot
* 1 = 8B mcp_slot_8
@@ -328,7 +332,7 @@ enum myri10ge_mcp_cmd_type {
#define MXGEFW_RSS_MCP_SLOT_TYPE_MIN 0
#define MXGEFW_RSS_MCP_SLOT_TYPE_WITH_HASH 1
- MXGEFW_CMD_SET_THROTTLE_FACTOR,
+ MXGEFW_CMD_SET_THROTTLE_FACTOR = 53,
/* set the throttle factor for ethp_z8e
* data0 = throttle_factor
* throttle_factor = 256 * pcie-raw-speed / tx_speed
@@ -344,45 +348,50 @@ enum myri10ge_mcp_cmd_type {
* with tx_boundary == 4096, max-throttle-factor == 4095 => min-speed == 1Gb/s
*/
- MXGEFW_CMD_VPUMP_UP,
+ MXGEFW_CMD_VPUMP_UP = 54,
/* Allocates VPump Connection, Send Request and Zero copy buffer address tables */
- MXGEFW_CMD_GET_VPUMP_CLK,
+ MXGEFW_CMD_GET_VPUMP_CLK = 55,
/* Get the lanai clock */
- MXGEFW_CMD_GET_DCA_OFFSET,
+ MXGEFW_CMD_GET_DCA_OFFSET = 56,
/* offset of dca control for WDMAs */
/* VMWare NetQueue commands */
- MXGEFW_CMD_NETQ_GET_FILTERS_PER_QUEUE,
- MXGEFW_CMD_NETQ_ADD_FILTER,
+ MXGEFW_CMD_NETQ_GET_FILTERS_PER_QUEUE = 57,
+ MXGEFW_CMD_NETQ_ADD_FILTER = 58,
/* data0 = filter_id << 16 | queue << 8 | type */
/* data1 = MS4 of MAC Addr */
/* data2 = LS2_MAC << 16 | VLAN_tag */
- MXGEFW_CMD_NETQ_DEL_FILTER,
+ MXGEFW_CMD_NETQ_DEL_FILTER = 59,
/* data0 = filter_id */
- MXGEFW_CMD_NETQ_QUERY1,
- MXGEFW_CMD_NETQ_QUERY2,
- MXGEFW_CMD_NETQ_QUERY3,
- MXGEFW_CMD_NETQ_QUERY4,
-
+ MXGEFW_CMD_NETQ_QUERY1 = 60,
+ MXGEFW_CMD_NETQ_QUERY2 = 61,
+ MXGEFW_CMD_NETQ_QUERY3 = 62,
+ MXGEFW_CMD_NETQ_QUERY4 = 63,
+
+ MXGEFW_CMD_RELAX_RXBUFFER_ALIGNMENT = 64,
+ /* When set, small receive buffers can cross page boundaries.
+ * Both small and big receive buffers may start at any address.
+ * This option has performance implications, so use with caution.
+ */
};
enum myri10ge_mcp_cmd_status {
MXGEFW_CMD_OK = 0,
- MXGEFW_CMD_UNKNOWN,
- MXGEFW_CMD_ERROR_RANGE,
- MXGEFW_CMD_ERROR_BUSY,
- MXGEFW_CMD_ERROR_EMPTY,
- MXGEFW_CMD_ERROR_CLOSED,
- MXGEFW_CMD_ERROR_HASH_ERROR,
- MXGEFW_CMD_ERROR_BAD_PORT,
- MXGEFW_CMD_ERROR_RESOURCES,
- MXGEFW_CMD_ERROR_MULTICAST,
- MXGEFW_CMD_ERROR_UNALIGNED,
- MXGEFW_CMD_ERROR_NO_MDIO,
- MXGEFW_CMD_ERROR_XFP_FAILURE,
- MXGEFW_CMD_ERROR_XFP_ABSENT,
- MXGEFW_CMD_ERROR_BAD_PCIE_LINK
+ MXGEFW_CMD_UNKNOWN = 1,
+ MXGEFW_CMD_ERROR_RANGE = 2,
+ MXGEFW_CMD_ERROR_BUSY = 3,
+ MXGEFW_CMD_ERROR_EMPTY = 4,
+ MXGEFW_CMD_ERROR_CLOSED = 5,
+ MXGEFW_CMD_ERROR_HASH_ERROR = 6,
+ MXGEFW_CMD_ERROR_BAD_PORT = 7,
+ MXGEFW_CMD_ERROR_RESOURCES = 8,
+ MXGEFW_CMD_ERROR_MULTICAST = 9,
+ MXGEFW_CMD_ERROR_UNALIGNED = 10,
+ MXGEFW_CMD_ERROR_NO_MDIO = 11,
+ MXGEFW_CMD_ERROR_I2C_FAILURE = 12,
+ MXGEFW_CMD_ERROR_I2C_ABSENT = 13,
+ MXGEFW_CMD_ERROR_BAD_PCIE_LINK = 14
};
#define MXGEFW_OLD_IRQ_DATA_LEN 40
diff --git a/drivers/net/myri10ge/myri10ge_mcp_gen_header.h b/drivers/net/myri10ge/myri10ge_mcp_gen_header.h
index a8662ea8079a..caa6cbbb631e 100644
--- a/drivers/net/myri10ge/myri10ge_mcp_gen_header.h
+++ b/drivers/net/myri10ge/myri10ge_mcp_gen_header.h
@@ -41,6 +41,8 @@ struct mcp_gen_header {
unsigned short handoff_id_major; /* must be equal */
unsigned short handoff_id_caps; /* bitfield: new mcp must have superset */
unsigned msix_table_addr; /* start address of msix table in firmware */
+ unsigned bss_addr; /* start of bss */
+ unsigned features;
/* 8 */
};
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c
index 3ad7589d6a1c..899ed065a147 100644
--- a/drivers/net/myri_sbus.c
+++ b/drivers/net/myri_sbus.c
@@ -318,13 +318,10 @@ static void myri_is_not_so_happy(struct myri_eth *mp)
#ifdef DEBUG_HEADER
static void dump_ehdr(struct ethhdr *ehdr)
{
- DECLARE_MAC_BUF(mac);
- DECLARE_MAC_BUF(mac2);
- printk("ehdr[h_dst(%s)"
- "h_source(%s)"
+ printk("ehdr[h_dst(%pM)"
+ "h_source(%pM)"
"h_proto(%04x)]\n",
- print_mac(mac, ehdr->h_dest), print_mac(mac2, ehdr->h_source),
- ehdr->h_proto);
+ ehdr->h_dest, ehdr->h_source, ehdr->h_proto);
}
static void dump_ehdr_and_myripad(unsigned char *stuff)
@@ -528,7 +525,6 @@ static void myri_rx(struct myri_eth *mp, struct net_device *dev)
DRX(("prot[%04x] netif_rx ", skb->protocol));
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
next:
@@ -540,7 +536,7 @@ static void myri_rx(struct myri_eth *mp, struct net_device *dev)
static irqreturn_t myri_interrupt(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *) dev_id;
- struct myri_eth *mp = (struct myri_eth *) dev->priv;
+ struct myri_eth *mp = netdev_priv(dev);
void __iomem *lregs = mp->lregs;
struct myri_channel __iomem *chan = &mp->shmem->channel;
unsigned long flags;
@@ -579,14 +575,14 @@ static irqreturn_t myri_interrupt(int irq, void *dev_id)
static int myri_open(struct net_device *dev)
{
- struct myri_eth *mp = (struct myri_eth *) dev->priv;
+ struct myri_eth *mp = netdev_priv(dev);
return myri_init(mp, in_interrupt());
}
static int myri_close(struct net_device *dev)
{
- struct myri_eth *mp = (struct myri_eth *) dev->priv;
+ struct myri_eth *mp = netdev_priv(dev);
myri_clean_rings(mp);
return 0;
@@ -594,7 +590,7 @@ static int myri_close(struct net_device *dev)
static void myri_tx_timeout(struct net_device *dev)
{
- struct myri_eth *mp = (struct myri_eth *) dev->priv;
+ struct myri_eth *mp = netdev_priv(dev);
printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
@@ -605,7 +601,7 @@ static void myri_tx_timeout(struct net_device *dev)
static int myri_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct myri_eth *mp = (struct myri_eth *) dev->priv;
+ struct myri_eth *mp = netdev_priv(dev);
struct sendq __iomem *sq = mp->sq;
struct myri_txd __iomem *txd;
unsigned long flags;
@@ -905,7 +901,6 @@ static int __devinit myri_sbus_probe(struct of_device *op, const struct of_devic
struct device_node *dp = op->node;
static unsigned version_printed;
struct net_device *dev;
- DECLARE_MAC_BUF(mac);
struct myri_eth *mp;
const void *prop;
static int num;
@@ -1088,15 +1083,15 @@ static int __devinit myri_sbus_probe(struct of_device *op, const struct of_devic
num++;
- printk("%s: MyriCOM MyriNET Ethernet %s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ printk("%s: MyriCOM MyriNET Ethernet %pM\n",
+ dev->name, dev->dev_addr);
return 0;
err_free_irq:
free_irq(dev->irq, dev);
err:
- /* This will also free the co-allocated 'dev->priv' */
+ /* This will also free the co-allocated private data*/
free_netdev(dev);
return -ENODEV;
}
diff --git a/drivers/net/natsemi.c b/drivers/net/natsemi.c
index f7fa3944659b..478edb92bca3 100644
--- a/drivers/net/natsemi.c
+++ b/drivers/net/natsemi.c
@@ -792,7 +792,6 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
const int pcibar = 1; /* PCI base address register */
int prev_eedata;
u32 tmp;
- DECLARE_MAC_BUF(mac);
/* when built into the kernel, we only print version if device is found */
#ifndef MODULE
@@ -948,10 +947,10 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
if (netif_msg_drv(np)) {
printk(KERN_INFO "natsemi %s: %s at %#08llx "
- "(%s), %s, IRQ %d",
+ "(%s), %pM, IRQ %d",
dev->name, natsemi_pci_info[chip_idx].name,
(unsigned long long)iostart, pci_name(np->pci_dev),
- print_mac(mac, dev->dev_addr), irq);
+ dev->dev_addr, irq);
if (dev->if_port == PORT_TP)
printk(", port TP.\n");
else if (np->ignore_phy)
@@ -2194,10 +2193,10 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
prefetch(&np->rx_skbuff[np->cur_rx % RX_RING_SIZE]);
- if (netif_rx_schedule_prep(dev, &np->napi)) {
+ if (netif_rx_schedule_prep(&np->napi)) {
/* Disable interrupts and register for poll */
natsemi_irq_disable(dev);
- __netif_rx_schedule(dev, &np->napi);
+ __netif_rx_schedule(&np->napi);
} else
printk(KERN_WARNING
"%s: Ignoring interrupt, status %#08x, mask %#08x.\n",
@@ -2249,7 +2248,7 @@ static int natsemi_poll(struct napi_struct *napi, int budget)
np->intr_status = readl(ioaddr + IntrStatus);
} while (np->intr_status);
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
/* Reenable interrupts providing nothing is trying to shut
* the chip down. */
@@ -2362,7 +2361,6 @@ static void netdev_rx(struct net_device *dev, int *work_done, int work_to_do)
}
skb->protocol = eth_type_trans(skb, dev);
netif_receive_skb(skb);
- dev->last_rx = jiffies;
np->stats.rx_packets++;
np->stats.rx_bytes += pkt_len;
}
diff --git a/drivers/net/ne-h8300.c b/drivers/net/ne-h8300.c
index fbc7531d3c7d..b57239171046 100644
--- a/drivers/net/ne-h8300.c
+++ b/drivers/net/ne-h8300.c
@@ -167,7 +167,7 @@ static void cleanup_card(struct net_device *dev)
#ifndef MODULE
struct net_device * __init ne_probe(int unit)
{
- struct net_device *dev = ____alloc_ei_netdev(0);
+ struct net_device *dev = alloc_ei_netdev();
int err;
if (!dev)
@@ -193,6 +193,21 @@ out:
}
#endif
+static const struct net_device_ops ne_netdev_ops = {
+ .ndo_open = ne_open,
+ .ndo_stop = ne_close,
+
+ .ndo_start_xmit = ei_start_xmit,
+ .ndo_tx_timeout = ei_tx_timeout,
+ .ndo_get_stats = ei_get_stats,
+ .ndo_set_multicast_list = ei_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = ei_poll,
+#endif
+};
+
static int __init ne_probe1(struct net_device *dev, int ioaddr)
{
int i;
@@ -204,7 +219,6 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
static unsigned version_printed;
struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
unsigned char bus_width;
- DECLARE_MAC_BUF(mac);
if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
return -EBUSY;
@@ -299,7 +313,7 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
for(i = 0; i < ETHER_ADDR_LEN; i++)
dev->dev_addr[i] = SA_prom[i];
- printk(" %s\n", print_mac(mac, dev->dev_addr));
+ printk(" %pM\n", dev->dev_addr);
printk("%s: %s found at %#x, using IRQ %d.\n",
dev->name, name, ioaddr, dev->irq);
@@ -320,11 +334,9 @@ static int __init ne_probe1(struct net_device *dev, int ioaddr)
ei_status.block_output = &ne_block_output;
ei_status.get_8390_hdr = &ne_get_8390_hdr;
ei_status.priv = 0;
- dev->open = &ne_open;
- dev->stop = &ne_close;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = __ei_poll;
-#endif
+
+ dev->netdev_ops = &ne_netdev_ops;
+
__NS8390_init(dev, 0);
ret = register_netdev(dev);
@@ -625,7 +637,7 @@ int init_module(void)
int err;
for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
- struct net_device *dev = ____alloc_ei_netdev(0);
+ struct net_device *dev = alloc_ei_netdev();
if (!dev)
break;
if (io[this_dev]) {
diff --git a/drivers/net/ne.c b/drivers/net/ne.c
index eb681c0d51ba..5c3e242428f1 100644
--- a/drivers/net/ne.c
+++ b/drivers/net/ne.c
@@ -174,9 +174,6 @@ bad_clone_list[] __initdata = {
static int ne_probe1(struct net_device *dev, unsigned long ioaddr);
static int ne_probe_isapnp(struct net_device *dev);
-static int ne_open(struct net_device *dev);
-static int ne_close(struct net_device *dev);
-
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);
@@ -297,7 +294,6 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
int neX000, ctron, copam, bad_card;
int reg0, ret;
static unsigned version_printed;
- DECLARE_MAC_BUF(mac);
if (!request_region(ioaddr, NE_IO_EXTENT, DRV_NAME))
return -EBUSY;
@@ -517,7 +513,7 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
}
#endif
- printk("%s\n", print_mac(mac, dev->dev_addr));
+ printk("%pM\n", dev->dev_addr);
ei_status.name = name;
ei_status.tx_start_page = start_page;
@@ -537,11 +533,8 @@ static int __init ne_probe1(struct net_device *dev, unsigned long ioaddr)
ei_status.block_output = &ne_block_output;
ei_status.get_8390_hdr = &ne_get_8390_hdr;
ei_status.priv = 0;
- dev->open = &ne_open;
- dev->stop = &ne_close;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = eip_poll;
-#endif
+
+ dev->netdev_ops = &eip_netdev_ops;
NS8390p_init(dev, 0);
ret = register_netdev(dev);
@@ -558,20 +551,6 @@ err_out:
return ret;
}
-static int ne_open(struct net_device *dev)
-{
- eip_open(dev);
- return 0;
-}
-
-static int ne_close(struct net_device *dev)
-{
- if (ei_debug > 1)
- printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
- eip_close(dev);
- return 0;
-}
-
/* Hard reset the card. This used to pause for the same period that a
8390 reset command required, but that shouldn't be necessary. */
@@ -950,7 +929,7 @@ static void __init ne_add_devices(void)
}
#ifdef MODULE
-int __init init_module()
+int __init init_module(void)
{
int retval;
ne_add_devices();
diff --git a/drivers/net/ne2.c b/drivers/net/ne2.c
index 332df75a9ab6..a53bb201d3c7 100644
--- a/drivers/net/ne2.c
+++ b/drivers/net/ne2.c
@@ -137,9 +137,6 @@ extern int netcard_probe(struct net_device *dev);
static int ne2_probe1(struct net_device *dev, int slot);
-static int ne_open(struct net_device *dev);
-static int ne_close(struct net_device *dev);
-
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);
@@ -302,7 +299,6 @@ out:
static int ne2_procinfo(char *buf, int slot, struct net_device *dev)
{
int len=0;
- DECLARE_MAC_BUF(mac);
len += sprintf(buf+len, "The NE/2 Ethernet Adapter\n" );
len += sprintf(buf+len, "Driver written by Wim Dumon ");
@@ -313,7 +309,7 @@ static int ne2_procinfo(char *buf, int slot, struct net_device *dev)
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 : %s\n", print_mac(mac, dev->dev_addr));
+ len += sprintf(buf+len, "HW addr : %pM\n", dev->dev_addr);
return len;
}
@@ -326,7 +322,6 @@ static int __init ne2_probe1(struct net_device *dev, int slot)
const char *name = "NE/2";
int start_page, stop_page;
static unsigned version_printed;
- DECLARE_MAC_BUF(mac);
if (ei_debug && version_printed++ == 0)
printk(version);
@@ -469,7 +464,7 @@ static int __init ne2_probe1(struct net_device *dev, int slot)
for(i = 0; i < ETHER_ADDR_LEN; i++)
dev->dev_addr[i] = SA_prom[i];
- printk(" %s\n", print_mac(mac, dev->dev_addr));
+ printk(" %pM\n", dev->dev_addr);
printk("%s: %s found at %#x, using IRQ %d.\n",
dev->name, name, base_addr, dev->irq);
@@ -494,11 +489,7 @@ static int __init ne2_probe1(struct net_device *dev, int slot)
ei_status.priv = slot;
- dev->open = &ne_open;
- dev->stop = &ne_close;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = eip_poll;
-#endif
+ dev->netdev_ops = &eip_netdev_ops;
NS8390p_init(dev, 0);
retval = register_netdev(dev);
@@ -513,20 +504,6 @@ out:
return retval;
}
-static int ne_open(struct net_device *dev)
-{
- eip_open(dev);
- return 0;
-}
-
-static int ne_close(struct net_device *dev)
-{
- if (ei_debug > 1)
- printk("%s: Shutting down ethercard.\n", dev->name);
- eip_close(dev);
- return 0;
-}
-
/* 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)
diff --git a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
index de0de744a8fa..62f20ba211cb 100644
--- a/drivers/net/ne2k-pci.c
+++ b/drivers/net/ne2k-pci.c
@@ -200,6 +200,19 @@ struct ne2k_pci_card {
in the 'dev' and 'ei_status' structures.
*/
+static const struct net_device_ops ne2k_netdev_ops = {
+ .ndo_open = ne2k_pci_open,
+ .ndo_stop = ne2k_pci_close,
+ .ndo_start_xmit = ei_start_xmit,
+ .ndo_tx_timeout = ei_tx_timeout,
+ .ndo_get_stats = ei_get_stats,
+ .ndo_set_multicast_list = ei_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = ei_poll,
+#endif
+};
static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent)
@@ -212,7 +225,6 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
static unsigned int fnd_cnt;
long ioaddr;
int flags = pci_clone_list[chip_idx].flags;
- DECLARE_MAC_BUF(mac);
/* when built into the kernel, we only print version if device is found */
#ifndef MODULE
@@ -266,6 +278,8 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
dev_err(&pdev->dev, "cannot allocate ethernet device\n");
goto err_out_free_res;
}
+ dev->netdev_ops = &ne2k_netdev_ops;
+
SET_NETDEV_DEV(dev, &pdev->dev);
/* Reset card. Who knows what dain-bramaged state it was left in. */
@@ -354,12 +368,8 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
ei_status.block_output = &ne2k_pci_block_output;
ei_status.get_8390_hdr = &ne2k_pci_get_8390_hdr;
ei_status.priv = (unsigned long) pdev;
- dev->open = &ne2k_pci_open;
- dev->stop = &ne2k_pci_close;
+
dev->ethtool_ops = &ne2k_pci_ethtool_ops;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = ei_poll;
-#endif
NS8390_init(dev, 0);
i = register_netdev(dev);
@@ -368,9 +378,9 @@ static int __devinit ne2k_pci_init_one (struct pci_dev *pdev,
for(i = 0; i < 6; i++)
dev->dev_addr[i] = SA_prom[i];
- printk("%s: %s found at %#lx, IRQ %d, %s.\n",
+ printk("%s: %s found at %#lx, IRQ %d, %pM.\n",
dev->name, pci_clone_list[chip_idx].name, ioaddr, dev->irq,
- print_mac(mac, dev->dev_addr));
+ dev->dev_addr);
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
@@ -626,7 +636,7 @@ static void ne2k_pci_block_output(struct net_device *dev, int count,
static void ne2k_pci_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
- struct ei_device *ei = dev->priv;
+ struct ei_device *ei = netdev_priv(dev);
struct pci_dev *pci_dev = (struct pci_dev *) ei->priv;
strcpy(info->driver, DRV_NAME);
diff --git a/drivers/net/ne3210.c b/drivers/net/ne3210.c
index 425043a88db9..fac43fd6fc87 100644
--- a/drivers/net/ne3210.c
+++ b/drivers/net/ne3210.c
@@ -45,9 +45,6 @@
#define DRV_NAME "ne3210"
-static int ne3210_open(struct net_device *dev);
-static int ne3210_close(struct net_device *dev);
-
static void ne3210_reset_8390(struct net_device *dev);
static void ne3210_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page);
@@ -99,7 +96,6 @@ static int __init ne3210_eisa_probe (struct device *device)
int i, retval, port_index;
struct eisa_device *edev = to_eisa_device (device);
struct net_device *dev;
- DECLARE_MAC_BUF(mac);
/* Allocate dev->priv and fill in 8390 specific dev fields. */
if (!(dev = alloc_ei_netdev ())) {
@@ -131,8 +127,8 @@ static int __init ne3210_eisa_probe (struct device *device)
port_index = inb(ioaddr + NE3210_CFG2) >> 6;
for(i = 0; i < ETHER_ADDR_LEN; i++)
dev->dev_addr[i] = inb(ioaddr + NE3210_SA_PROM + i);
- printk("ne3210.c: NE3210 in EISA slot %d, media: %s, addr: %s.\n",
- edev->slot, ifmap[port_index], print_mac(mac, dev->dev_addr));
+ printk("ne3210.c: NE3210 in EISA slot %d, media: %s, addr: %pM.\n",
+ edev->slot, ifmap[port_index], dev->dev_addr);
/* Snarf the interrupt now. CFG file has them all listed as `edge' with share=NO */
dev->irq = irq_map[(inb(ioaddr + NE3210_CFG2) >> 3) & 0x07];
@@ -200,11 +196,8 @@ static int __init ne3210_eisa_probe (struct device *device)
ei_status.block_output = &ne3210_block_output;
ei_status.get_8390_hdr = &ne3210_get_8390_hdr;
- dev->open = &ne3210_open;
- dev->stop = &ne3210_close;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = ei_poll;
-#endif
+ dev->netdev_ops = &ei_netdev_ops;
+
dev->if_port = ifmap_val[port_index];
if ((retval = register_netdev (dev)))
@@ -321,22 +314,6 @@ static void ne3210_block_output(struct net_device *dev, int count,
memcpy_toio(shmem, buf, count);
}
-static int ne3210_open(struct net_device *dev)
-{
- ei_open(dev);
- return 0;
-}
-
-static int ne3210_close(struct net_device *dev)
-{
-
- if (ei_debug > 1)
- printk("%s: Shutting down ethercard.\n", dev->name);
-
- ei_close(dev);
- return 0;
-}
-
static struct eisa_device_id ne3210_ids[] = {
{ "EGL0101" },
{ "NVL1801" },
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 9681618c3232..d304d38cd5d1 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -307,17 +307,14 @@ static ssize_t show_remote_ip(struct netconsole_target *nt, char *buf)
static ssize_t show_local_mac(struct netconsole_target *nt, char *buf)
{
struct net_device *dev = nt->np.dev;
+ static const u8 bcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
- DECLARE_MAC_BUF(mac);
- return snprintf(buf, PAGE_SIZE, "%s\n", dev ?
- print_mac(mac, dev->dev_addr) : "ff:ff:ff:ff:ff:ff");
+ return snprintf(buf, PAGE_SIZE, "%pM\n", dev ? dev->dev_addr : bcast);
}
static ssize_t show_remote_mac(struct netconsole_target *nt, char *buf)
{
- DECLARE_MAC_BUF(mac);
- return snprintf(buf, PAGE_SIZE, "%s\n",
- print_mac(mac, nt->np.remote_mac));
+ return snprintf(buf, PAGE_SIZE, "%pM\n", nt->np.remote_mac);
}
/*
diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c
index b289a0a2b945..1861d5bbd96b 100644
--- a/drivers/net/netx-eth.c
+++ b/drivers/net/netx-eth.c
@@ -165,7 +165,6 @@ static void netx_eth_receive(struct net_device *ndev)
pfifo_push(EMPTY_PTR_FIFO(priv->id),
FIFO_PTR_SEGMENT(seg) | FIFO_PTR_FRAMENO(frameno));
- ndev->last_rx = jiffies;
skb->protocol = eth_type_trans(skb, ndev);
netif_rx(skb);
ndev->stats.rx_packets++;
diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
index b974ca0fc530..e45ce2951729 100644
--- a/drivers/net/netxen/netxen_nic_ethtool.c
+++ b/drivers/net/netxen/netxen_nic_ethtool.c
@@ -275,11 +275,11 @@ netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
} else
return -EOPNOTSUPP;
- if (netif_running(dev)) {
- dev->stop(dev);
- dev->open(dev);
- }
- return 0;
+ if (!netif_running(dev))
+ return 0;
+
+ dev->netdev_ops->ndo_stop(dev);
+ return dev->netdev_ops->ndo_open(dev);
}
static int netxen_nic_get_regs_len(struct net_device *dev)
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index 84978f80f396..aa6e603bfcbf 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -537,7 +537,7 @@ netxen_send_cmd_descs(struct netxen_adapter *adapter,
static int nx_p3_sre_macaddr_change(struct net_device *dev,
u8 *addr, unsigned op)
{
- struct netxen_adapter *adapter = (struct netxen_adapter *)dev->priv;
+ struct netxen_adapter *adapter = netdev_priv(dev);
nx_nic_req_t req;
nx_mac_req_t mac_req;
int rv;
@@ -1459,7 +1459,7 @@ static int netxen_nic_pci_mem_read_direct(struct netxen_adapter *adapter,
mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE * 2);
else
mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
- if (mem_ptr == 0UL) {
+ if (mem_ptr == NULL) {
*(uint8_t *)data = 0;
return -1;
}
@@ -1533,7 +1533,7 @@ netxen_nic_pci_mem_write_direct(struct netxen_adapter *adapter, u64 off,
mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE*2);
else
mem_ptr = ioremap(mem_base + mem_page, PAGE_SIZE);
- if (mem_ptr == 0UL)
+ if (mem_ptr == NULL)
return -1;
addr = mem_ptr;
addr += start & (PAGE_SIZE - 1);
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 5bba675d0504..d924468e506e 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -1285,9 +1285,7 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
}
adapter->stats.rxdropped++;
} else {
-
netif_receive_skb(skb);
- netdev->last_rx = jiffies;
adapter->stats.no_rcv++;
adapter->stats.rxbytes += length;
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 6ef3f0d84bcf..ba01524b5531 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -439,7 +439,6 @@ netxen_read_mac_addr(struct netxen_adapter *adapter)
int i;
unsigned char *p;
__le64 mac_addr;
- DECLARE_MAC_BUF(mac);
struct net_device *netdev = adapter->netdev;
struct pci_dev *pdev = adapter->pdev;
@@ -462,15 +461,39 @@ netxen_read_mac_addr(struct netxen_adapter *adapter)
/* set station address */
- if (!is_valid_ether_addr(netdev->perm_addr)) {
- dev_warn(&pdev->dev, "Bad MAC address %s.\n",
- print_mac(mac, netdev->dev_addr));
- } else
+ if (!is_valid_ether_addr(netdev->perm_addr))
+ dev_warn(&pdev->dev, "Bad MAC address %pM.\n", netdev->dev_addr);
+ else
adapter->macaddr_set(adapter, netdev->dev_addr);
return 0;
}
+static void netxen_set_multicast_list(struct net_device *dev)
+{
+ struct netxen_adapter *adapter = netdev_priv(dev);
+
+ if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
+ netxen_p3_nic_set_multi(dev);
+ else
+ netxen_p2_nic_set_multi(dev);
+}
+
+static const struct net_device_ops netxen_netdev_ops = {
+ .ndo_open = netxen_nic_open,
+ .ndo_stop = netxen_nic_close,
+ .ndo_start_xmit = netxen_nic_xmit_frame,
+ .ndo_get_stats = netxen_nic_get_stats,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_multicast_list = netxen_set_multicast_list,
+ .ndo_set_mac_address = netxen_nic_set_mac,
+ .ndo_change_mtu = netxen_nic_change_mtu,
+ .ndo_tx_timeout = netxen_tx_timeout,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = netxen_nic_poll_controller,
+#endif
+};
+
/*
* netxen_nic_probe()
*
@@ -543,7 +566,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
SET_NETDEV_DEV(netdev, &pdev->dev);
- adapter = netdev->priv;
+ adapter = netdev_priv(netdev);
adapter->netdev = netdev;
adapter->pdev = pdev;
adapter->ahw.pci_func = pci_func_id;
@@ -682,25 +705,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
else
adapter->max_mc_count = 16;
- netdev->open = netxen_nic_open;
- netdev->stop = netxen_nic_close;
- netdev->hard_start_xmit = netxen_nic_xmit_frame;
- netdev->get_stats = netxen_nic_get_stats;
- if (NX_IS_REVISION_P3(revision_id))
- netdev->set_multicast_list = netxen_p3_nic_set_multi;
- else
- netdev->set_multicast_list = netxen_p2_nic_set_multi;
- netdev->set_mac_address = netxen_nic_set_mac;
- netdev->change_mtu = netxen_nic_change_mtu;
- netdev->tx_timeout = netxen_tx_timeout;
+ netdev->netdev_ops = &netxen_netdev_ops;
netdev->watchdog_timeo = 2*HZ;
netxen_nic_change_mtu(netdev, netdev->mtu);
SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops);
-#ifdef CONFIG_NET_POLL_CONTROLLER
- netdev->poll_controller = netxen_nic_poll_controller;
-#endif
+
/* ScatterGather support */
netdev->features = NETIF_F_SG;
netdev->features |= NETIF_F_IP_CSUM;
@@ -988,7 +999,7 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
*/
static int netxen_nic_open(struct net_device *netdev)
{
- struct netxen_adapter *adapter = (struct netxen_adapter *)netdev->priv;
+ struct netxen_adapter *adapter = netdev_priv(netdev);
int err = 0;
int ctx, ring;
irq_handler_t handler;
@@ -1077,7 +1088,7 @@ static int netxen_nic_open(struct net_device *netdev)
netxen_nic_set_link_parameters(adapter);
- netdev->set_multicast_list(netdev);
+ netxen_set_multicast_list(netdev);
if (adapter->set_mtu)
adapter->set_mtu(adapter, netdev->mtu);
@@ -1572,7 +1583,7 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget)
}
if ((work_done < budget) && tx_complete) {
- netif_rx_complete(adapter->netdev, &adapter->napi);
+ netif_rx_complete(&adapter->napi);
netxen_nic_enable_int(adapter);
}
diff --git a/drivers/net/netxen/netxen_nic_niu.c b/drivers/net/netxen/netxen_nic_niu.c
index 27f07f6a45b1..c3b9c83b32fe 100644
--- a/drivers/net/netxen/netxen_nic_niu.c
+++ b/drivers/net/netxen/netxen_nic_niu.c
@@ -608,7 +608,6 @@ int netxen_niu_macaddr_set(struct netxen_adapter *adapter,
int phy = adapter->physical_port;
unsigned char mac_addr[6];
int i;
- DECLARE_MAC_BUF(mac);
if (NX_IS_REVISION_P3(adapter->ahw.revision_id))
return 0;
@@ -636,10 +635,8 @@ int netxen_niu_macaddr_set(struct netxen_adapter *adapter,
if (i == 10) {
printk(KERN_ERR "%s: cannot set Mac addr for %s\n",
netxen_nic_driver_name, adapter->netdev->name);
- printk(KERN_ERR "MAC address set: %s.\n",
- print_mac(mac, addr));
- printk(KERN_ERR "MAC address get: %s.\n",
- print_mac(mac, mac_addr));
+ printk(KERN_ERR "MAC address set: %pM.\n", addr);
+ printk(KERN_ERR "MAC address get: %pM.\n", mac_addr);
}
return 0;
}
diff --git a/drivers/net/ni5010.c b/drivers/net/ni5010.c
index 8e0ca9f4e404..539e18ab485c 100644
--- a/drivers/net/ni5010.c
+++ b/drivers/net/ni5010.c
@@ -203,7 +203,6 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
unsigned int data = 0;
int boguscount = 40;
int err = -ENODEV;
- DECLARE_MAC_BUF(mac);
dev->base_addr = ioaddr;
dev->irq = irq;
@@ -271,7 +270,7 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
outw(i, IE_GP);
dev->dev_addr[i] = inb(IE_SAPROM);
}
- printk("%s ", print_mac(mac, dev->dev_addr));
+ printk("%pM ", dev->dev_addr);
PRINTK2((KERN_DEBUG "%s: I/O #4 passed!\n", dev->name));
@@ -329,7 +328,7 @@ static int __init ni5010_probe1(struct net_device *dev, int ioaddr)
outb(0, IE_RBUF); /* set buffer byte 0 to 0 again */
}
printk("-> bufsize rcv/xmt=%d/%d\n", bufsize_rcv, NI5010_BUFSIZE);
- memset(dev->priv, 0, sizeof(struct ni5010_local));
+ memset(netdev_priv(dev), 0, sizeof(struct ni5010_local));
dev->open = ni5010_open;
dev->stop = ni5010_close;
@@ -570,7 +569,6 @@ static void ni5010_rx(struct net_device *dev)
skb->protocol = eth_type_trans(skb,dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += i_pkt_size;
@@ -768,12 +766,3 @@ module_init(ni5010_init_module);
module_exit(ni5010_cleanup_module);
#endif /* MODULE */
MODULE_LICENSE("GPL");
-
-/*
- * Local variables:
- * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c ni5010.c"
- * version-control: t
- * kept-new-versions: 5
- * tab-width: 4
- * End:
- */
diff --git a/drivers/net/ni52.c b/drivers/net/ni52.c
index b9a882d362da..a8bcc00c3302 100644
--- a/drivers/net/ni52.c
+++ b/drivers/net/ni52.c
@@ -9,8 +9,6 @@
* [feel free to mail ....]
*
* when using as module: (no autoprobing!)
- * compile with:
- * gcc -O2 -fomit-frame-pointer -m486 -D__KERNEL__ -DMODULE -c ni52.c
* run with e.g:
* insmod ni52.o io=0x360 irq=9 memstart=0xd0000 memend=0xd4000
*
@@ -214,7 +212,7 @@ struct priv {
/* wait for command with timeout: */
static void wait_for_scb_cmd(struct net_device *dev)
{
- struct priv *p = dev->priv;
+ struct priv *p = netdev_priv(dev);
int i;
for (i = 0; i < 16384; i++) {
if (readb(&p->scb->cmd_cuc) == 0)
@@ -233,7 +231,7 @@ static void wait_for_scb_cmd(struct net_device *dev)
static void wait_for_scb_cmd_ruc(struct net_device *dev)
{
- struct priv *p = dev->priv;
+ struct priv *p = netdev_priv(dev);
int i;
for (i = 0; i < 16384; i++) {
if (readb(&p->scb->cmd_ruc) == 0)
@@ -298,7 +296,7 @@ static int ni52_open(struct net_device *dev)
static int check_iscp(struct net_device *dev, void __iomem *addr)
{
struct iscp_struct __iomem *iscp = addr;
- struct priv *p = dev->priv;
+ struct priv *p = netdev_priv(dev);
memset_io(iscp, 0, sizeof(struct iscp_struct));
writel(make24(iscp), &p->scp->iscp);
@@ -318,7 +316,7 @@ static int check_iscp(struct net_device *dev, void __iomem *addr)
*/
static int check586(struct net_device *dev, unsigned size)
{
- struct priv *p = dev->priv;
+ struct priv *p = netdev_priv(dev);
int i;
p->mapped = ioremap(dev->mem_start, size);
@@ -354,7 +352,7 @@ Enodev:
*/
static void alloc586(struct net_device *dev)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
ni_reset586();
mdelay(32);
@@ -400,7 +398,7 @@ struct net_device * __init ni52_probe(int unit)
if (!dev)
return ERR_PTR(-ENOMEM);
- p = dev->priv;
+ p = netdev_priv(dev);
if (unit >= 0) {
sprintf(dev->name, "eth%d", unit);
@@ -446,7 +444,7 @@ out:
static int __init ni52_probe1(struct net_device *dev, int ioaddr)
{
int i, size, retval;
- struct priv *priv = dev->priv;
+ struct priv *priv = netdev_priv(dev);
dev->base_addr = ioaddr;
dev->irq = irq;
@@ -588,7 +586,7 @@ static int init586(struct net_device *dev)
{
void __iomem *ptr;
int i, result = 0;
- struct priv *p = (struct priv *)dev->priv;
+ struct priv *p = netdev_priv(dev);
struct configure_cmd_struct __iomem *cfg_cmd;
struct iasetup_cmd_struct __iomem *ias_cmd;
struct tdr_cmd_struct __iomem *tdr_cmd;
@@ -829,7 +827,7 @@ static void __iomem *alloc_rfa(struct net_device *dev, void __iomem *ptr)
struct rfd_struct __iomem *rfd = ptr;
struct rbd_struct __iomem *rbd;
int i;
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
memset_io(rfd, 0,
sizeof(struct rfd_struct) * (p->num_recv_buffs + rfdadd));
@@ -878,7 +876,7 @@ static irqreturn_t ni52_interrupt(int irq, void *dev_id)
int cnt = 0;
struct priv *p;
- p = (struct priv *) dev->priv;
+ p = netdev_priv(dev);
if (debuglevel > 1)
printk("I");
@@ -950,7 +948,7 @@ static void ni52_rcv_int(struct net_device *dev)
unsigned short totlen;
struct sk_buff *skb;
struct rbd_struct __iomem *rbd;
- struct priv *p = (struct priv *)dev->priv;
+ struct priv *p = netdev_priv(dev);
if (debuglevel > 0)
printk("R");
@@ -970,7 +968,6 @@ static void ni52_rcv_int(struct net_device *dev)
memcpy_fromio(skb->data, p->base + readl(&rbd->buffer), totlen);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
p->stats.rx_packets++;
p->stats.rx_bytes += totlen;
} else
@@ -1040,7 +1037,7 @@ static void ni52_rcv_int(struct net_device *dev)
static void ni52_rnr_int(struct net_device *dev)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
p->stats.rx_errors++;
@@ -1065,7 +1062,7 @@ static void ni52_rnr_int(struct net_device *dev)
static void ni52_xmt_int(struct net_device *dev)
{
int status;
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
if (debuglevel > 0)
printk("X");
@@ -1113,7 +1110,7 @@ static void ni52_xmt_int(struct net_device *dev)
static void startrecv586(struct net_device *dev)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
wait_for_scb_cmd(dev);
wait_for_scb_cmd_ruc(dev);
@@ -1126,7 +1123,7 @@ static void startrecv586(struct net_device *dev)
static void ni52_timeout(struct net_device *dev)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
#ifndef NO_NOPCOMMANDS
if (readb(&p->scb->cus) & CU_ACTIVE) { /* COMMAND-UNIT active? */
netif_wake_queue(dev);
@@ -1177,7 +1174,7 @@ static int ni52_send_packet(struct sk_buff *skb, struct net_device *dev)
#ifndef NO_NOPCOMMANDS
int next_nop;
#endif
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
if (skb->len > XMIT_BUFF_SIZE) {
printk(KERN_ERR "%s: Sorry, max. framelength is %d bytes. The length of your frame is %d bytes.\n", dev->name, XMIT_BUFF_SIZE, skb->len);
@@ -1274,7 +1271,7 @@ static int ni52_send_packet(struct sk_buff *skb, struct net_device *dev)
static struct net_device_stats *ni52_get_stats(struct net_device *dev)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
unsigned short crc, aln, rsc, ovrn;
/* Get error-statistics from the ni82586 */
@@ -1337,7 +1334,7 @@ int __init init_module(void)
void __exit cleanup_module(void)
{
- struct priv *p = dev_ni52->priv;
+ struct priv *p = netdev_priv(dev_ni52);
unregister_netdev(dev_ni52);
iounmap(p->mapped);
release_region(dev_ni52->base_addr, NI52_TOTAL_SIZE);
@@ -1346,7 +1343,3 @@ void __exit cleanup_module(void)
#endif /* MODULE */
MODULE_LICENSE("GPL");
-
-/*
- * END: linux/drivers/net/ni52.c
- */
diff --git a/drivers/net/ni65.c b/drivers/net/ni65.c
index 3edc971d0eca..254057275e0e 100644
--- a/drivers/net/ni65.c
+++ b/drivers/net/ni65.c
@@ -7,8 +7,6 @@
* EtherBlaster. (probably it also works with every full NE2100
* compatible card)
*
- * To compile as module, type:
- * gcc -O2 -fomit-frame-pointer -m486 -D__KERNEL__ -DMODULE -c ni65.c
* driver probes: io: 0x360,0x300,0x320,0x340 / dma: 3,5,6,7
*
* This is an extension to the Linux operating system, and is covered by the
@@ -295,7 +293,7 @@ static void ni65_set_performance(struct priv *p)
*/
static int ni65_open(struct net_device *dev)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = dev->ml_priv;
int irqval = request_irq(dev->irq, &ni65_interrupt,0,
cards[p->cardno].cardname,dev);
if (irqval) {
@@ -321,7 +319,7 @@ static int ni65_open(struct net_device *dev)
*/
static int ni65_close(struct net_device *dev)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = dev->ml_priv;
netif_stop_queue(dev);
@@ -345,7 +343,7 @@ static int ni65_close(struct net_device *dev)
static void cleanup_card(struct net_device *dev)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = dev->ml_priv;
disable_dma(dev->dma);
free_dma(dev->dma);
release_region(dev->base_addr, cards[p->cardno].total_size);
@@ -444,7 +442,7 @@ static int __init ni65_probe1(struct net_device *dev,int ioaddr)
release_region(ioaddr, cards[i].total_size);
return j;
}
- p = (struct priv *) dev->priv;
+ p = dev->ml_priv;
p->cmdr_addr = ioaddr + cards[i].cmd_offset;
p->cardno = i;
spin_lock_init(&p->ring_lock);
@@ -647,8 +645,8 @@ static int ni65_alloc_buffer(struct net_device *dev)
if(!ptr)
return -ENOMEM;
- p = dev->priv = (struct priv *) (((unsigned long) ptr + 7) & ~0x7);
- memset((char *) dev->priv,0,sizeof(struct priv));
+ p = dev->ml_priv = (struct priv *) (((unsigned long) ptr + 7) & ~0x7);
+ memset((char *)p, 0, sizeof(struct priv));
p->self = ptr;
for(i=0;i<TMDNUM;i++)
@@ -790,7 +788,7 @@ static void ni65_stop_start(struct net_device *dev,struct priv *p)
static int ni65_lance_reinit(struct net_device *dev)
{
int i;
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = dev->ml_priv;
unsigned long flags;
p->lock = 0;
@@ -876,7 +874,7 @@ static irqreturn_t ni65_interrupt(int irq, void * dev_id)
struct priv *p;
int bcnt = 32;
- p = (struct priv *) dev->priv;
+ p = dev->ml_priv;
spin_lock(&p->ring_lock);
@@ -899,7 +897,7 @@ static irqreturn_t ni65_interrupt(int irq, void * dev_id)
if(csr0 & CSR0_ERR)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = dev->ml_priv;
if(debuglevel > 1)
printk(KERN_ERR "%s: general error: %04x.\n",dev->name,csr0);
if(csr0 & CSR0_BABL)
@@ -924,7 +922,7 @@ static irqreturn_t ni65_interrupt(int irq, void * dev_id)
int j;
for(j=0;j<RMDNUM;j++)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = dev->ml_priv;
int i,k,num1,num2;
for(i=RMDNUM-1;i>0;i--) {
num2 = (p->rmdnum + i) & (RMDNUM-1);
@@ -982,7 +980,7 @@ static irqreturn_t ni65_interrupt(int irq, void * dev_id)
*/
static void ni65_xmit_intr(struct net_device *dev,int csr0)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = dev->ml_priv;
while(p->xmit_queued)
{
@@ -1049,7 +1047,7 @@ static void ni65_recv_intr(struct net_device *dev,int csr0)
struct rmd *rmdp;
int rmdstat,len;
int cnt=0;
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = dev->ml_priv;
rmdp = p->rmdhead + p->rmdnum;
while(!( (rmdstat = rmdp->u.s.status) & RCV_OWN))
@@ -1113,7 +1111,6 @@ static void ni65_recv_intr(struct net_device *dev,int csr0)
p->stats.rx_bytes += len;
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
- dev->last_rx = jiffies;
}
else
{
@@ -1140,7 +1137,7 @@ static void ni65_recv_intr(struct net_device *dev,int csr0)
static void ni65_timeout(struct net_device *dev)
{
int i;
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = dev->ml_priv;
printk(KERN_ERR "%s: xmitter timed out, try to restart!\n",dev->name);
for(i=0;i<TMDNUM;i++)
@@ -1157,7 +1154,7 @@ static void ni65_timeout(struct net_device *dev)
static int ni65_send_packet(struct sk_buff *skb, struct net_device *dev)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = dev->ml_priv;
netif_stop_queue(dev);
@@ -1222,7 +1219,7 @@ static struct net_device_stats *ni65_get_stats(struct net_device *dev)
#if 0
int i;
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = dev->ml_priv;
for(i=0;i<RMDNUM;i++)
{
struct rmd *rmdp = p->rmdhead + ((p->rmdnum + i) & (RMDNUM-1));
@@ -1231,7 +1228,7 @@ static struct net_device_stats *ni65_get_stats(struct net_device *dev)
printk("\n");
#endif
- return &((struct priv *) dev->priv)->stats;
+ return &((struct priv *)dev->ml_priv)->stats;
}
static void set_multicast_list(struct net_device *dev)
@@ -1266,7 +1263,3 @@ void __exit cleanup_module(void)
#endif /* MODULE */
MODULE_LICENSE("GPL");
-
-/*
- * END of ni65.c
- */
diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index 1b6f548c4411..0c0b752315ca 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -448,7 +448,7 @@ static int serdes_init_niu_1g_serdes(struct niu *np)
struct niu_link_config *lp = &np->link_config;
u16 pll_cfg, pll_sts;
int max_retry = 100;
- u64 sig, mask, val;
+ u64 uninitialized_var(sig), mask, val;
u32 tx_cfg, rx_cfg;
unsigned long i;
int err;
@@ -547,7 +547,7 @@ static int serdes_init_niu_10g_serdes(struct niu *np)
struct niu_link_config *lp = &np->link_config;
u32 tx_cfg, rx_cfg, pll_cfg, pll_sts;
int max_retry = 100;
- u64 sig, mask, val;
+ u64 uninitialized_var(sig), mask, val;
unsigned long i;
int err;
@@ -738,7 +738,7 @@ static int esr_write_glue0(struct niu *np, unsigned long chan, u32 val)
static int esr_reset(struct niu *np)
{
- u32 reset;
+ u32 uninitialized_var(reset);
int err;
err = mdio_write(np, np->port, NIU_ESR_DEV_ADDR,
@@ -3392,8 +3392,6 @@ static int niu_process_rx_pkt(struct niu *np, struct rx_ring_info *rp)
skb->protocol = eth_type_trans(skb, np->dev);
netif_receive_skb(skb);
- np->dev->last_rx = jiffies;
-
return num_rcr;
}
@@ -3529,6 +3527,57 @@ out:
}
}
+static inline void niu_sync_rx_discard_stats(struct niu *np,
+ struct rx_ring_info *rp,
+ const int limit)
+{
+ /* This elaborate scheme is needed for reading the RX discard
+ * counters, as they are only 16-bit and can overflow quickly,
+ * and because the overflow indication bit is not usable as
+ * the counter value does not wrap, but remains at max value
+ * 0xFFFF.
+ *
+ * In theory and in practice counters can be lost in between
+ * reading nr64() and clearing the counter nw64(). For this
+ * reason, the number of counter clearings nw64() is
+ * limited/reduced though the limit parameter.
+ */
+ int rx_channel = rp->rx_channel;
+ u32 misc, wred;
+
+ /* RXMISC (Receive Miscellaneous Discard Count), covers the
+ * following discard events: IPP (Input Port Process),
+ * FFLP/TCAM, Full RCR (Receive Completion Ring) RBR (Receive
+ * Block Ring) prefetch buffer is empty.
+ */
+ misc = nr64(RXMISC(rx_channel));
+ if (unlikely((misc & RXMISC_COUNT) > limit)) {
+ nw64(RXMISC(rx_channel), 0);
+ rp->rx_errors += misc & RXMISC_COUNT;
+
+ if (unlikely(misc & RXMISC_OFLOW))
+ dev_err(np->device, "rx-%d: Counter overflow "
+ "RXMISC discard\n", rx_channel);
+
+ niudbg(RX_ERR, "%s-rx-%d: MISC drop=%u over=%u\n",
+ np->dev->name, rx_channel, misc, misc-limit);
+ }
+
+ /* WRED (Weighted Random Early Discard) by hardware */
+ wred = nr64(RED_DIS_CNT(rx_channel));
+ if (unlikely((wred & RED_DIS_CNT_COUNT) > limit)) {
+ nw64(RED_DIS_CNT(rx_channel), 0);
+ rp->rx_dropped += wred & RED_DIS_CNT_COUNT;
+
+ if (unlikely(wred & RED_DIS_CNT_OFLOW))
+ dev_err(np->device, "rx-%d: Counter overflow "
+ "WRED discard\n", rx_channel);
+
+ niudbg(RX_ERR, "%s-rx-%d: WRED drop=%u over=%u\n",
+ np->dev->name, rx_channel, wred, wred-limit);
+ }
+}
+
static int niu_rx_work(struct niu *np, struct rx_ring_info *rp, int budget)
{
int qlen, rcr_done = 0, work_done = 0;
@@ -3569,6 +3618,10 @@ static int niu_rx_work(struct niu *np, struct rx_ring_info *rp, int budget)
nw64(RX_DMA_CTL_STAT(rp->rx_channel), stat);
+ /* Only sync discards stats when qlen indicate potential for drops */
+ if (qlen > 10)
+ niu_sync_rx_discard_stats(np, rp, 0x7FFF);
+
return work_done;
}
@@ -3616,7 +3669,7 @@ static int niu_poll(struct napi_struct *napi, int budget)
work_done = niu_poll_core(np, lp, budget);
if (work_done < budget) {
- netif_rx_complete(np->dev, napi);
+ netif_rx_complete(napi);
niu_ldg_rearm(np, lp, 1);
}
return work_done;
@@ -4035,12 +4088,12 @@ static void __niu_fastpath_interrupt(struct niu *np, int ldg, u64 v0)
static void niu_schedule_napi(struct niu *np, struct niu_ldg *lp,
u64 v0, u64 v1, u64 v2)
{
- if (likely(netif_rx_schedule_prep(np->dev, &lp->napi))) {
+ if (likely(netif_rx_schedule_prep(&lp->napi))) {
lp->v0 = v0;
lp->v1 = v1;
lp->v2 = v2;
__niu_fastpath_interrupt(np, lp->ldg_num, v0);
- __netif_rx_schedule(np->dev, &lp->napi);
+ __netif_rx_schedule(&lp->napi);
}
}
@@ -5849,17 +5902,42 @@ static void niu_stop_hw(struct niu *np)
niu_reset_rx_channels(np);
}
+static void niu_set_irq_name(struct niu *np)
+{
+ int port = np->port;
+ int i, j = 1;
+
+ sprintf(np->irq_name[0], "%s:MAC", np->dev->name);
+
+ if (port == 0) {
+ sprintf(np->irq_name[1], "%s:MIF", np->dev->name);
+ sprintf(np->irq_name[2], "%s:SYSERR", np->dev->name);
+ j = 3;
+ }
+
+ for (i = 0; i < np->num_ldg - j; i++) {
+ if (i < np->num_rx_rings)
+ sprintf(np->irq_name[i+j], "%s-rx-%d",
+ np->dev->name, i);
+ else if (i < np->num_tx_rings + np->num_rx_rings)
+ sprintf(np->irq_name[i+j], "%s-tx-%d", np->dev->name,
+ i - np->num_rx_rings);
+ }
+}
+
static int niu_request_irq(struct niu *np)
{
int i, j, err;
+ niu_set_irq_name(np);
+
err = 0;
for (i = 0; i < np->num_ldg; i++) {
struct niu_ldg *lp = &np->ldg[i];
err = request_irq(lp->irq, niu_interrupt,
IRQF_SHARED | IRQF_SAMPLE_RANDOM,
- np->dev->name, lp);
+ np->irq_name[i], lp);
if (err)
goto out_free_irqs;
@@ -6050,15 +6128,17 @@ static void niu_get_rx_stats(struct niu *np)
for (i = 0; i < np->num_rx_rings; i++) {
struct rx_ring_info *rp = &np->rx_rings[i];
+ niu_sync_rx_discard_stats(np, rp, 0);
+
pkts += rp->rx_packets;
bytes += rp->rx_bytes;
dropped += rp->rx_dropped;
errors += rp->rx_errors;
}
- np->net_stats.rx_packets = pkts;
- np->net_stats.rx_bytes = bytes;
- np->net_stats.rx_dropped = dropped;
- np->net_stats.rx_errors = errors;
+ np->dev->stats.rx_packets = pkts;
+ np->dev->stats.rx_bytes = bytes;
+ np->dev->stats.rx_dropped = dropped;
+ np->dev->stats.rx_errors = errors;
}
static void niu_get_tx_stats(struct niu *np)
@@ -6074,9 +6154,9 @@ static void niu_get_tx_stats(struct niu *np)
bytes += rp->tx_bytes;
errors += rp->tx_errors;
}
- np->net_stats.tx_packets = pkts;
- np->net_stats.tx_bytes = bytes;
- np->net_stats.tx_errors = errors;
+ np->dev->stats.tx_packets = pkts;
+ np->dev->stats.tx_bytes = bytes;
+ np->dev->stats.tx_errors = errors;
}
static struct net_device_stats *niu_get_stats(struct net_device *dev)
@@ -6086,7 +6166,7 @@ static struct net_device_stats *niu_get_stats(struct net_device *dev)
niu_get_rx_stats(np);
niu_get_tx_stats(np);
- return &np->net_stats;
+ return &dev->stats;
}
static void niu_load_hash_xmac(struct niu *np, u16 *hash)
@@ -6991,6 +7071,8 @@ static void niu_get_ethtool_stats(struct net_device *dev,
for (i = 0; i < np->num_rx_rings; i++) {
struct rx_ring_info *rp = &np->rx_rings[i];
+ niu_sync_rx_discard_stats(np, rp, 0);
+
data[0] = rp->rx_channel;
data[1] = rp->rx_packets;
data[2] = rp->rx_bytes;
@@ -8824,7 +8906,7 @@ static u64 niu_pci_map_page(struct device *dev, struct page *page,
static void niu_pci_unmap_page(struct device *dev, u64 dma_address,
size_t size, enum dma_data_direction direction)
{
- return dma_unmap_page(dev, dma_address, size, direction);
+ dma_unmap_page(dev, dma_address, size, direction);
}
static u64 niu_pci_map_single(struct device *dev, void *cpu_addr,
@@ -8891,28 +8973,31 @@ static struct net_device * __devinit niu_alloc_and_init(
return dev;
}
+static const struct net_device_ops niu_netdev_ops = {
+ .ndo_open = niu_open,
+ .ndo_stop = niu_close,
+ .ndo_start_xmit = niu_start_xmit,
+ .ndo_get_stats = niu_get_stats,
+ .ndo_set_multicast_list = niu_set_rx_mode,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = niu_set_mac_addr,
+ .ndo_do_ioctl = niu_ioctl,
+ .ndo_tx_timeout = niu_tx_timeout,
+ .ndo_change_mtu = niu_change_mtu,
+};
+
static void __devinit niu_assign_netdev_ops(struct net_device *dev)
{
- dev->open = niu_open;
- dev->stop = niu_close;
- dev->get_stats = niu_get_stats;
- dev->set_multicast_list = niu_set_rx_mode;
- dev->set_mac_address = niu_set_mac_addr;
- dev->do_ioctl = niu_ioctl;
- dev->tx_timeout = niu_tx_timeout;
- dev->hard_start_xmit = niu_start_xmit;
+ dev->netdev_ops = &niu_netdev_ops;
dev->ethtool_ops = &niu_ethtool_ops;
dev->watchdog_timeo = NIU_TX_TIMEOUT;
- dev->change_mtu = niu_change_mtu;
}
static void __devinit niu_device_announce(struct niu *np)
{
struct net_device *dev = np->dev;
- DECLARE_MAC_BUF(mac);
- pr_info("%s: NIU Ethernet %s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ pr_info("%s: NIU Ethernet %pM\n", dev->name, dev->dev_addr);
if (np->parent->plat_type == PLAT_TYPE_ATCA_CP3220) {
pr_info("%s: Port type[%s] mode[%s:%s] XCVR[%s] phy[%s]\n",
diff --git a/drivers/net/niu.h b/drivers/net/niu.h
index 180ca8ae93de..e1a7392e8d70 100644
--- a/drivers/net/niu.h
+++ b/drivers/net/niu.h
@@ -3243,12 +3243,12 @@ struct niu {
#define NIU_FLAGS_XMAC 0x00010000 /* 0=BMAC 1=XMAC */
u32 msg_enable;
+ char irq_name[NIU_NUM_RXCHAN+NIU_NUM_TXCHAN+3][IFNAMSIZ + 6];
/* Protects hw programming, and ring state. */
spinlock_t lock;
const struct niu_ops *ops;
- struct net_device_stats net_stats;
union niu_mac_stats mac_stats;
struct rx_ring_info *rx_rings;
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c
index ff449619f047..46b0772489e4 100644
--- a/drivers/net/ns83820.c
+++ b/drivers/net/ns83820.c
@@ -1948,14 +1948,25 @@ static void ns83820_probe_phy(struct net_device *ndev)
}
#endif
-static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_device_id *id)
+static const struct net_device_ops netdev_ops = {
+ .ndo_open = ns83820_open,
+ .ndo_stop = ns83820_stop,
+ .ndo_start_xmit = ns83820_hard_start_xmit,
+ .ndo_get_stats = ns83820_get_stats,
+ .ndo_change_mtu = ns83820_change_mtu,
+ .ndo_set_multicast_list = ns83820_set_multicast,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_tx_timeout = ns83820_tx_timeout,
+};
+
+static int __devinit ns83820_init_one(struct pci_dev *pci_dev,
+ const struct pci_device_id *id)
{
struct net_device *ndev;
struct ns83820 *dev;
long addr;
int err;
int using_dac = 0;
- DECLARE_MAC_BUF(mac);
/* See if we can set the dma mask early on; failure is fatal. */
if (sizeof(dma_addr_t) == 8 &&
@@ -2041,14 +2052,8 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
ndev->name, le32_to_cpu(readl(dev->base + 0x22c)),
pci_dev->subsystem_vendor, pci_dev->subsystem_device);
- ndev->open = ns83820_open;
- ndev->stop = ns83820_stop;
- ndev->hard_start_xmit = ns83820_hard_start_xmit;
- ndev->get_stats = ns83820_get_stats;
- ndev->change_mtu = ns83820_change_mtu;
- ndev->set_multicast_list = ns83820_set_multicast;
+ ndev->netdev_ops = &netdev_ops;
SET_ETHTOOL_OPS(ndev, &ops);
- ndev->tx_timeout = ns83820_tx_timeout;
ndev->watchdog_timeo = 5 * HZ;
pci_set_drvdata(pci_dev, ndev);
@@ -2220,12 +2225,11 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_
ndev->features |= NETIF_F_HIGHDMA;
}
- printk(KERN_INFO "%s: ns83820 v" VERSION ": DP83820 v%u.%u: %s io=0x%08lx irq=%d f=%s\n",
+ printk(KERN_INFO "%s: ns83820 v" VERSION ": DP83820 v%u.%u: %pM io=0x%08lx irq=%d f=%s\n",
ndev->name,
(unsigned)readl(dev->base + SRR) >> 8,
(unsigned)readl(dev->base + SRR) & 0xff,
- print_mac(mac, ndev->dev_addr),
- addr, pci_dev->irq,
+ ndev->dev_addr, addr, pci_dev->irq,
(ndev->features & NETIF_F_HIGHDMA) ? "h,sg" : "sg"
);
diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
index edc0fd588985..dcd199045613 100644
--- a/drivers/net/pasemi_mac.c
+++ b/drivers/net/pasemi_mac.c
@@ -971,7 +971,7 @@ static irqreturn_t pasemi_mac_rx_intr(int irq, void *data)
if (*chan->status & PAS_STATUS_ERROR)
reg |= PAS_IOB_DMA_RXCH_RESET_DINTC;
- netif_rx_schedule(dev, &mac->napi);
+ netif_rx_schedule(&mac->napi);
write_iob_reg(PAS_IOB_DMA_RXCH_RESET(chan->chno), reg);
@@ -1011,7 +1011,7 @@ static irqreturn_t pasemi_mac_tx_intr(int irq, void *data)
mod_timer(&txring->clean_timer, jiffies + (TX_CLEAN_INTERVAL)*2);
- netif_rx_schedule(mac->netdev, &mac->napi);
+ netif_rx_schedule(&mac->napi);
if (reg)
write_iob_reg(PAS_IOB_DMA_TXCH_RESET(chan->chno), reg);
@@ -1105,7 +1105,8 @@ static int pasemi_mac_phy_init(struct net_device *dev)
goto err;
phy_id = *prop;
- snprintf(mac->phy_id, BUS_ID_SIZE, "%x:%02x", (int)r.start, phy_id);
+ snprintf(mac->phy_id, sizeof(mac->phy_id), "%x:%02x",
+ (int)r.start, phy_id);
of_node_put(phy_dn);
@@ -1640,7 +1641,7 @@ static int pasemi_mac_poll(struct napi_struct *napi, int budget)
pkts = pasemi_mac_clean_rx(rx_ring(mac), budget);
if (pkts < budget) {
/* all done, no more packets present */
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
pasemi_mac_restart_rx_intr(mac);
pasemi_mac_restart_tx_intr(mac);
@@ -1742,7 +1743,6 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
struct net_device *dev;
struct pasemi_mac *mac;
int err;
- DECLARE_MAC_BUF(mac_buf);
err = pci_enable_device(pdev);
if (err)
@@ -1849,9 +1849,9 @@ pasemi_mac_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err);
goto out;
} else if netif_msg_probe(mac)
- printk(KERN_INFO "%s: PA Semi %s: intf %d, hw addr %s\n",
+ printk(KERN_INFO "%s: PA Semi %s: intf %d, hw addr %pM\n",
dev->name, mac->type == MAC_TYPE_GMAC ? "GMAC" : "XAUI",
- mac->dma_if, print_mac(mac_buf, dev->dev_addr));
+ mac->dma_if, dev->dev_addr);
return err;
diff --git a/drivers/net/pasemi_mac_ethtool.c b/drivers/net/pasemi_mac_ethtool.c
index 5e8df3afea64..064a4fe1dd90 100644
--- a/drivers/net/pasemi_mac_ethtool.c
+++ b/drivers/net/pasemi_mac_ethtool.c
@@ -109,7 +109,7 @@ static void
pasemi_mac_ethtool_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ering)
{
- struct pasemi_mac *mac = netdev->priv;
+ struct pasemi_mac *mac = netdev_priv(netdev);
ering->tx_max_pending = TX_RING_SIZE/2;
ering->tx_pending = RING_USED(mac->tx)/2;
@@ -130,7 +130,7 @@ static int pasemi_mac_get_sset_count(struct net_device *netdev, int sset)
static void pasemi_mac_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, u64 *data)
{
- struct pasemi_mac *mac = netdev->priv;
+ struct pasemi_mac *mac = netdev_priv(netdev);
int i;
data[0] = pasemi_read_dma_reg(PAS_DMA_RXINT_RCMDSTA(mac->dma_if))
diff --git a/drivers/net/pci-skeleton.c b/drivers/net/pci-skeleton.c
index 0a575fef29e6..c95fd72c3bb9 100644
--- a/drivers/net/pci-skeleton.c
+++ b/drivers/net/pci-skeleton.c
@@ -737,7 +737,6 @@ static int __devinit netdrv_init_one (struct pci_dev *pdev,
int i, addr_len, option;
void *ioaddr = NULL;
static int board_idx = -1;
- DECLARE_MAC_BUF(mac);
/* when built into the kernel, we only print version if device is found */
#ifndef MODULE
@@ -782,7 +781,7 @@ static int __devinit netdrv_init_one (struct pci_dev *pdev,
dev->irq = pdev->irq;
dev->base_addr = (unsigned long) ioaddr;
- /* dev->priv/tp zeroed and aligned in alloc_etherdev */
+ /* netdev_priv()/tp zeroed and aligned in alloc_etherdev */
tp = netdev_priv(dev);
/* note: tp->chipset set in netdrv_init_board */
@@ -797,11 +796,11 @@ static int __devinit netdrv_init_one (struct pci_dev *pdev,
tp->phys[0] = 32;
- printk (KERN_INFO "%s: %s at 0x%lx, %sIRQ %d\n",
+ printk (KERN_INFO "%s: %s at 0x%lx, %pM IRQ %d\n",
dev->name,
board_info[ent->driver_data].name,
dev->base_addr,
- print_mac(mac, dev->dev_addr),
+ dev->dev_addr,
dev->irq);
printk (KERN_DEBUG "%s: Identified 8139 chip type '%s'\n",
@@ -1566,7 +1565,6 @@ static void netdrv_rx_interrupt (struct net_device *dev,
skb->protocol = eth_type_trans (skb, dev);
netif_rx (skb);
- dev->last_rx = jiffies;
dev->stats.rx_bytes += pkt_size;
dev->stats.rx_packets++;
} else {
diff --git a/drivers/net/pcmcia/3c574_cs.c b/drivers/net/pcmcia/3c574_cs.c
index 08c4dd896077..e5cb6b1f0ebd 100644
--- a/drivers/net/pcmcia/3c574_cs.c
+++ b/drivers/net/pcmcia/3c574_cs.c
@@ -345,7 +345,6 @@ static int tc574_config(struct pcmcia_device *link)
__be16 *phys_addr;
char *cardname;
__u32 config;
- DECLARE_MAC_BUF(mac);
phys_addr = (__be16 *)dev->dev_addr;
@@ -463,9 +462,9 @@ static int tc574_config(struct pcmcia_device *link)
strcpy(lp->node.dev_name, dev->name);
printk(KERN_INFO "%s: %s at io %#3lx, irq %d, "
- "hw_addr %s.\n",
+ "hw_addr %pM.\n",
dev->name, cardname, dev->base_addr, dev->irq,
- print_mac(mac, dev->dev_addr));
+ dev->dev_addr);
printk(" %dK FIFO split %s Rx:Tx, %sMII interface.\n",
8 << config & Ram_size,
ram_split[(config & Ram_split) >> Ram_split_shift],
@@ -1062,7 +1061,6 @@ static int el3_rx(struct net_device *dev, int worklimit)
((pkt_len+3)>>2));
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
} else {
diff --git a/drivers/net/pcmcia/3c589_cs.c b/drivers/net/pcmcia/3c589_cs.c
index c235cdba69c6..73ecc657999d 100644
--- a/drivers/net/pcmcia/3c589_cs.c
+++ b/drivers/net/pcmcia/3c589_cs.c
@@ -255,7 +255,6 @@ static int tc589_config(struct pcmcia_device *link)
int last_fn, last_ret, i, j, multi = 0, fifo;
unsigned int ioaddr;
char *ram_split[] = {"5:3", "3:1", "1:1", "3:5"};
- DECLARE_MAC_BUF(mac);
DEBUG(0, "3c589_config(0x%p)\n", link);
@@ -333,9 +332,9 @@ static int tc589_config(struct pcmcia_device *link)
strcpy(lp->node.dev_name, dev->name);
printk(KERN_INFO "%s: 3Com 3c%s, io %#3lx, irq %d, "
- "hw_addr %s\n",
+ "hw_addr %pM\n",
dev->name, (multi ? "562" : "589"), dev->base_addr, dev->irq,
- print_mac(mac, dev->dev_addr));
+ dev->dev_addr);
printk(KERN_INFO " %dK FIFO split %s Rx:Tx, %s xcvr\n",
(fifo & 7) ? 32 : 8, ram_split[(fifo >> 16) & 3],
if_names[dev->if_port]);
@@ -884,7 +883,6 @@ static int el3_rx(struct net_device *dev)
(pkt_len+3)>>2);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
} else {
diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c
index 0418045166c3..0afa72095810 100644
--- a/drivers/net/pcmcia/axnet_cs.c
+++ b/drivers/net/pcmcia/axnet_cs.c
@@ -321,7 +321,6 @@ static int axnet_config(struct pcmcia_device *link)
struct net_device *dev = link->priv;
axnet_dev_t *info = PRIV(dev);
int i, j, last_ret, last_fn;
- DECLARE_MAC_BUF(mac);
DEBUG(0, "axnet_config(0x%p)\n", link);
@@ -397,10 +396,10 @@ static int axnet_config(struct pcmcia_device *link)
strcpy(info->node.dev_name, dev->name);
printk(KERN_INFO "%s: Asix AX88%d90: io %#3lx, irq %d, "
- "hw_addr %s\n",
+ "hw_addr %pM\n",
dev->name, ((info->flags & IS_AX88790) ? 7 : 1),
dev->base_addr, dev->irq,
- print_mac(mac, dev->dev_addr));
+ dev->dev_addr);
if (info->phy_id != -1) {
DEBUG(0, " MII transceiver at index %d, status %x.\n", info->phy_id, j);
} else {
@@ -906,7 +905,7 @@ int ei_debug = 1;
/* Index to functions. */
static void ei_tx_intr(struct net_device *dev);
static void ei_tx_err(struct net_device *dev);
-static void ei_tx_timeout(struct net_device *dev);
+static void axnet_tx_timeout(struct net_device *dev);
static void ei_receive(struct net_device *dev);
static void ei_rx_overrun(struct net_device *dev);
@@ -957,9 +956,9 @@ static int ax_open(struct net_device *dev)
#ifdef HAVE_TX_TIMEOUT
/* The card I/O part of the driver (e.g. 3c503) can hook a Tx timeout
- wrapper that does e.g. media check & then calls ei_tx_timeout. */
+ wrapper that does e.g. media check & then calls axnet_tx_timeout. */
if (dev->tx_timeout == NULL)
- dev->tx_timeout = ei_tx_timeout;
+ dev->tx_timeout = axnet_tx_timeout;
if (dev->watchdog_timeo <= 0)
dev->watchdog_timeo = TX_TIMEOUT;
#endif
@@ -1003,14 +1002,14 @@ static int ax_close(struct net_device *dev)
}
/**
- * ei_tx_timeout - handle transmit time out condition
+ * axnet_tx_timeout - handle transmit time out condition
* @dev: network device which has apparently fallen asleep
*
* Called by kernel when device never acknowledges a transmit has
* completed (or failed) - i.e. never posted a Tx related interrupt.
*/
-static void ei_tx_timeout(struct net_device *dev)
+static void axnet_tx_timeout(struct net_device *dev)
{
long e8390_base = dev->base_addr;
struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
@@ -1047,14 +1046,14 @@ static void ei_tx_timeout(struct net_device *dev)
}
/**
- * ei_start_xmit - begin packet transmission
+ * axnet_start_xmit - begin packet transmission
* @skb: packet to be sent
* @dev: network device to which packet is sent
*
* Sends a packet to an 8390 network device.
*/
-static int ei_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static int axnet_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
long e8390_base = dev->base_addr;
struct ei_device *ei_local = (struct ei_device *) netdev_priv(dev);
@@ -1493,7 +1492,6 @@ static void ei_receive(struct net_device *dev)
ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
if (pkt_stat & ENRSR_PHY)
@@ -1720,7 +1718,7 @@ static void axdev_setup(struct net_device *dev)
ei_local = (struct ei_device *)netdev_priv(dev);
spin_lock_init(&ei_local->page_lock);
- dev->hard_start_xmit = &ei_start_xmit;
+ dev->hard_start_xmit = &axnet_start_xmit;
dev->get_stats = get_stats;
dev->set_multicast_list = &set_multicast_list;
diff --git a/drivers/net/pcmcia/com20020_cs.c b/drivers/net/pcmcia/com20020_cs.c
index 831090c75622..7b5c77b7bd27 100644
--- a/drivers/net/pcmcia/com20020_cs.c
+++ b/drivers/net/pcmcia/com20020_cs.c
@@ -155,7 +155,7 @@ static int com20020_probe(struct pcmcia_device *p_dev)
if (!dev)
goto fail_alloc_dev;
- lp = dev->priv;
+ lp = netdev_priv(dev);
lp->timeout = timeout;
lp->backplane = backplane;
lp->clockp = clockp;
@@ -303,7 +303,7 @@ static int com20020_config(struct pcmcia_device *link)
goto failed;
}
- lp = dev->priv;
+ lp = netdev_priv(dev);
lp->card_name = "PCMCIA COM20020";
lp->card_flags = ARC_CAN_10MBIT; /* pretend all of them can 10Mbit */
@@ -364,7 +364,7 @@ static int com20020_resume(struct pcmcia_device *link)
if (link->open) {
int ioaddr = dev->base_addr;
- struct arcnet_local *lp = dev->priv;
+ struct arcnet_local *lp = netdev_priv(dev);
ARCRESET;
}
diff --git a/drivers/net/pcmcia/fmvj18x_cs.c b/drivers/net/pcmcia/fmvj18x_cs.c
index 69d916daa7bb..69dcfbbabe82 100644
--- a/drivers/net/pcmcia/fmvj18x_cs.c
+++ b/drivers/net/pcmcia/fmvj18x_cs.c
@@ -125,6 +125,7 @@ typedef struct local_info_t {
u_short tx_queue_len;
cardtype_t cardtype;
u_short sent;
+ u_char __iomem *base;
} local_info_t;
#define MC_FILTERBREAK 64
@@ -242,6 +243,7 @@ static int fmvj18x_probe(struct pcmcia_device *link)
lp = netdev_priv(dev);
link->priv = dev;
lp->p_dev = link;
+ lp->base = NULL;
/* The io structure describes IO port mapping */
link->io.NumPorts1 = 32;
@@ -348,7 +350,6 @@ static int fmvj18x_config(struct pcmcia_device *link)
cardtype_t cardtype;
char *card_name = "unknown";
u_char *node_id;
- DECLARE_MAC_BUF(mac);
DEBUG(0, "fmvj18x_config(0x%p)\n", link);
@@ -443,8 +444,10 @@ static int fmvj18x_config(struct pcmcia_device *link)
dev->irq = link->irq.AssignedIRQ;
dev->base_addr = link->io.BasePort1;
- if (link->io.BasePort2 != 0)
- fmvj18x_setup_mfc(link);
+ if (link->io.BasePort2 != 0) {
+ ret = fmvj18x_setup_mfc(link);
+ if (ret != 0) goto failed;
+ }
ioaddr = dev->base_addr;
@@ -539,9 +542,9 @@ static int fmvj18x_config(struct pcmcia_device *link)
/* print current configuration */
printk(KERN_INFO "%s: %s, sram %s, port %#3lx, irq %d, "
- "hw_addr %s\n",
+ "hw_addr %pM\n",
dev->name, card_name, sram_config == 0 ? "4K TX*2" : "8K TX*2",
- dev->base_addr, dev->irq, print_mac(mac, dev->dev_addr));
+ dev->base_addr, dev->irq, dev->dev_addr);
return 0;
@@ -611,10 +614,10 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)
{
win_req_t req;
memreq_t mem;
- u_char __iomem *base;
- int i, j;
+ int i;
struct net_device *dev = link->priv;
unsigned int ioaddr;
+ local_info_t *lp = netdev_priv(dev);
/* Allocate a small memory window */
req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;
@@ -626,25 +629,32 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)
return -1;
}
- base = ioremap(req.Base, req.Size);
+ lp->base = ioremap(req.Base, req.Size);
+ if (lp->base == NULL) {
+ printk(KERN_NOTICE "fmvj18x_cs: ioremap failed\n");
+ return -1;
+ }
+
mem.Page = 0;
mem.CardOffset = 0;
- pcmcia_map_mem_page(link->win, &mem);
-
+ i = pcmcia_map_mem_page(link->win, &mem);
+ if (i != 0) {
+ iounmap(lp->base);
+ lp->base = NULL;
+ cs_error(link, MapMemPage, i);
+ return -1;
+ }
+
ioaddr = dev->base_addr;
- writeb(0x47, base+0x800); /* Config Option Register of LAN */
- writeb(0x0, base+0x802); /* Config and Status Register */
+ writeb(0x47, lp->base+0x800); /* Config Option Register of LAN */
+ writeb(0x0, lp->base+0x802); /* Config and Status Register */
- writeb(ioaddr & 0xff, base+0x80a); /* I/O Base(Low) of LAN */
- writeb((ioaddr >> 8) & 0xff, base+0x80c); /* I/O Base(High) of LAN */
+ writeb(ioaddr & 0xff, lp->base+0x80a); /* I/O Base(Low) of LAN */
+ writeb((ioaddr >> 8) & 0xff, lp->base+0x80c); /* I/O Base(High) of LAN */
- writeb(0x45, base+0x820); /* Config Option Register of Modem */
- writeb(0x8, base+0x822); /* Config and Status Register */
+ writeb(0x45, lp->base+0x820); /* Config Option Register of Modem */
+ writeb(0x8, lp->base+0x822); /* Config and Status Register */
- iounmap(base);
- j = pcmcia_release_window(link->win);
- if (j != 0)
- cs_error(link, ReleaseWindow, j);
return 0;
}
@@ -652,8 +662,25 @@ static int fmvj18x_setup_mfc(struct pcmcia_device *link)
static void fmvj18x_release(struct pcmcia_device *link)
{
- DEBUG(0, "fmvj18x_release(0x%p)\n", link);
- pcmcia_disable_device(link);
+
+ struct net_device *dev = link->priv;
+ local_info_t *lp = netdev_priv(dev);
+ u_char __iomem *tmp;
+ int j;
+
+ DEBUG(0, "fmvj18x_release(0x%p)\n", link);
+
+ if (lp->base != NULL) {
+ tmp = lp->base;
+ lp->base = NULL; /* set NULL before iounmap */
+ iounmap(tmp);
+ j = pcmcia_release_window(link->win);
+ if (j != 0)
+ cs_error(link, ReleaseWindow, j);
+ }
+
+ pcmcia_disable_device(link);
+
}
static int fmvj18x_suspend(struct pcmcia_device *link)
@@ -784,6 +811,13 @@ static irqreturn_t fjn_interrupt(int dummy, void *dev_id)
outb(D_TX_INTR, ioaddr + TX_INTR);
outb(D_RX_INTR, ioaddr + RX_INTR);
+
+ if (lp->base != NULL) {
+ /* Ack interrupt for multifunction card */
+ writeb(0x01, lp->base+0x802);
+ writeb(0x09, lp->base+0x822);
+ }
+
return IRQ_HANDLED;
} /* fjn_interrupt */
@@ -1036,7 +1070,6 @@ static void fjn_rx(struct net_device *dev)
#endif
netif_rx(skb);
- dev->last_rx = jiffies;
lp->stats.rx_packets++;
lp->stats.rx_bytes += pkt_len;
}
diff --git a/drivers/net/pcmcia/nmclan_cs.c b/drivers/net/pcmcia/nmclan_cs.c
index 448cd40aeba5..ec7c588c9ae5 100644
--- a/drivers/net/pcmcia/nmclan_cs.c
+++ b/drivers/net/pcmcia/nmclan_cs.c
@@ -659,7 +659,6 @@ static int nmclan_config(struct pcmcia_device *link)
u_char buf[64];
int i, last_ret, last_fn;
unsigned int ioaddr;
- DECLARE_MAC_BUF(mac);
DEBUG(0, "nmclan_config(0x%p)\n", link);
@@ -719,9 +718,9 @@ static int nmclan_config(struct pcmcia_device *link)
strcpy(lp->node.dev_name, dev->name);
printk(KERN_INFO "%s: nmclan: port %#3lx, irq %d, %s port,"
- " hw_addr %s\n",
+ " hw_addr %pM\n",
dev->name, dev->base_addr, dev->irq, if_names[dev->if_port],
- print_mac(mac, dev->dev_addr));
+ dev->dev_addr);
return 0;
cs_failed:
@@ -1193,7 +1192,6 @@ static int mace_rx(struct net_device *dev, unsigned char RxCnt)
netif_rx(skb); /* Send the packet to the upper (protocol) layers. */
- dev->last_rx = jiffies;
lp->linux_stats.rx_packets++;
lp->linux_stats.rx_bytes += pkt_len;
outb(0xFF, ioaddr + AM2150_RCV_NEXT); /* skip to next frame */
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index ce486f094492..c38ed777f0a8 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -554,7 +554,6 @@ static int pcnet_config(struct pcmcia_device *link)
int last_ret, last_fn, start_pg, stop_pg, cm_offset;
int has_shmem = 0;
hw_info_t *local_hw_info;
- DECLARE_MAC_BUF(mac);
DEBUG(0, "pcnet_config(0x%p)\n", link);
@@ -675,7 +674,7 @@ static int pcnet_config(struct pcmcia_device *link)
printk (" mem %#5lx,", dev->mem_start);
if (info->flags & HAS_MISC_REG)
printk(" %s xcvr,", if_names[dev->if_port]);
- printk(" hw_addr %s\n", print_mac(mac, dev->dev_addr));
+ printk(" hw_addr %pM\n", dev->dev_addr);
return 0;
cs_failed:
diff --git a/drivers/net/pcmcia/smc91c92_cs.c b/drivers/net/pcmcia/smc91c92_cs.c
index c74d6656d266..fccd53ef3c64 100644
--- a/drivers/net/pcmcia/smc91c92_cs.c
+++ b/drivers/net/pcmcia/smc91c92_cs.c
@@ -949,7 +949,6 @@ static int smc91c92_config(struct pcmcia_device *link)
int i, j, rev;
unsigned int ioaddr;
u_long mir;
- DECLARE_MAC_BUF(mac);
DEBUG(0, "smc91c92_config(0x%p)\n", link);
@@ -1062,9 +1061,9 @@ static int smc91c92_config(struct pcmcia_device *link)
strcpy(smc->node.dev_name, dev->name);
printk(KERN_INFO "%s: smc91c%s rev %d: io %#3lx, irq %d, "
- "hw_addr %s\n",
+ "hw_addr %pM\n",
dev->name, name, (rev & 0x0f), dev->base_addr, dev->irq,
- print_mac(mac, dev->dev_addr));
+ dev->dev_addr);
if (rev > 0) {
if (mir & 0x3ff)
diff --git a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
index e1fd585e7131..fef7e1861d6a 100644
--- a/drivers/net/pcmcia/xirc2ps_cs.c
+++ b/drivers/net/pcmcia/xirc2ps_cs.c
@@ -772,7 +772,6 @@ xirc2ps_config(struct pcmcia_device * link)
int err, i;
u_char buf[64];
cistpl_lan_node_id_t *node_id = (cistpl_lan_node_id_t*)parse.funce.data;
- DECLARE_MAC_BUF(mac);
local->dingo_ccr = NULL;
@@ -1051,9 +1050,9 @@ xirc2ps_config(struct pcmcia_device * link)
strcpy(local->node.dev_name, dev->name);
/* give some infos about the hardware */
- printk(KERN_INFO "%s: %s: port %#3lx, irq %d, hwaddr %s\n",
+ printk(KERN_INFO "%s: %s: port %#3lx, irq %d, hwaddr %pM\n",
dev->name, local->manf_str,(u_long)dev->base_addr, (int)dev->irq,
- print_mac(mac, dev->dev_addr));
+ dev->dev_addr);
return 0;
@@ -1243,7 +1242,6 @@ xirc2ps_interrupt(int irq, void *dev_id)
}
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
lp->stats.rx_packets++;
lp->stats.rx_bytes += pktlen;
if (!(rsr & PhyPkt))
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
index ca8c0e037400..044b7b07f5f4 100644
--- a/drivers/net/pcnet32.c
+++ b/drivers/net/pcnet32.c
@@ -1246,7 +1246,6 @@ static void pcnet32_rx_entry(struct net_device *dev,
dev->stats.rx_bytes += skb->len;
skb->protocol = eth_type_trans(skb, dev);
netif_receive_skb(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
return;
}
@@ -1398,7 +1397,7 @@ static int pcnet32_poll(struct napi_struct *napi, int budget)
if (work_done < budget) {
spin_lock_irqsave(&lp->lock, flags);
- __netif_rx_complete(dev, napi);
+ __netif_rx_complete(napi);
/* clear interrupt masks */
val = lp->a.read_csr(ioaddr, CSR3);
@@ -1747,8 +1746,7 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev)
memset(dev->dev_addr, 0, sizeof(dev->dev_addr));
if (pcnet32_debug & NETIF_MSG_PROBE) {
- DECLARE_MAC_BUF(mac);
- printk(" %s", print_mac(mac, dev->dev_addr));
+ printk(" %pM", dev->dev_addr);
/* Version 0x2623 and 0x2624 */
if (((chip_version + 1) & 0xfffe) == 0x2624) {
@@ -2588,14 +2586,14 @@ pcnet32_interrupt(int irq, void *dev_id)
dev->name, csr0);
/* unlike for the lance, there is no restart needed */
}
- if (netif_rx_schedule_prep(dev, &lp->napi)) {
+ if (netif_rx_schedule_prep(&lp->napi)) {
u16 val;
/* set interrupt masks */
val = lp->a.read_csr(ioaddr, CSR3);
val |= 0x5f00;
lp->a.write_csr(ioaddr, CSR3, val);
mmiowb();
- __netif_rx_schedule(dev, &lp->napi);
+ __netif_rx_schedule(&lp->napi);
break;
}
csr0 = lp->a.read_csr(ioaddr, CSR0);
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index d55932acd887..de9cf5136fdc 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -66,6 +66,22 @@ config REALTEK_PHY
---help---
Supports the Realtek 821x PHY.
+config NATIONAL_PHY
+ tristate "Drivers for National Semiconductor PHYs"
+ ---help---
+ Currently supports the DP83865 PHY.
+
+config STE10XP
+ depends on PHYLIB
+ tristate "Driver for STMicroelectronics STe10Xp PHYs"
+ ---help---
+ This is the driver for the STe100p and STe101p PHYs.
+
+config LSI_ET1011C_PHY
+ tristate "Driver for LSI ET1011C PHY"
+ ---help---
+ Supports the LSI ET1011C PHY.
+
config FIXED_PHY
bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs"
depends on PHYLIB=y
@@ -84,10 +100,13 @@ config MDIO_BITBANG
If in doubt, say N.
-config MDIO_OF_GPIO
+config MDIO_GPIO
tristate "Support for GPIO lib-based bitbanged MDIO buses"
- depends on MDIO_BITBANG && OF_GPIO
+ depends on MDIO_BITBANG && GENERIC_GPIO
---help---
Supports GPIO lib-based MDIO busses.
+ To compile this driver as a module, choose M here: the module
+ will be called mdio-gpio.
+
endif # PHYLIB
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index eee329fa6f53..3a1bfefefbc3 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -13,6 +13,9 @@ obj-$(CONFIG_VITESSE_PHY) += vitesse.o
obj-$(CONFIG_BROADCOM_PHY) += broadcom.o
obj-$(CONFIG_ICPLUS_PHY) += icplus.o
obj-$(CONFIG_REALTEK_PHY) += realtek.o
+obj-$(CONFIG_LSI_ET1011C_PHY) += et1011c.o
obj-$(CONFIG_FIXED_PHY) += fixed.o
obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o
-obj-$(CONFIG_MDIO_OF_GPIO) += mdio-ofgpio.o
+obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o
+obj-$(CONFIG_NATIONAL_PHY) += national.o
+obj-$(CONFIG_STE10XP) += ste10Xp.o
diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c
index 4b4dc98ad165..190efc3301c6 100644
--- a/drivers/net/phy/broadcom.c
+++ b/drivers/net/phy/broadcom.c
@@ -17,6 +17,8 @@
#include <linux/module.h>
#include <linux/phy.h>
+#define PHY_ID_BCM50610 0x0143bd60
+
#define MII_BCM54XX_ECR 0x10 /* BCM54xx extended control register */
#define MII_BCM54XX_ECR_IM 0x1000 /* Interrupt mask */
#define MII_BCM54XX_ECR_IF 0x0800 /* Interrupt force */
@@ -54,6 +56,21 @@
#define MII_BCM54XX_SHD_DATA(x) ((x & 0x3ff) << 0)
/*
+ * AUXILIARY CONTROL SHADOW ACCESS REGISTERS. (PHY REG 0x18)
+ */
+#define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL 0x0000
+#define MII_BCM54XX_AUXCTL_ACTL_TX_6DB 0x0400
+#define MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA 0x0800
+
+#define MII_BCM54XX_AUXCTL_MISC_WREN 0x8000
+#define MII_BCM54XX_AUXCTL_MISC_FORCE_AMDIX 0x0200
+#define MII_BCM54XX_AUXCTL_MISC_RDSEL_MISC 0x7000
+#define MII_BCM54XX_AUXCTL_SHDWSEL_MISC 0x0007
+
+#define MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL 0x0000
+
+
+/*
* Broadcom LED source encodings. These are used in BCM5461, BCM5481,
* BCM5482, and possibly some others.
*/
@@ -88,6 +105,24 @@
#define BCM5482_SHD_MODE_1000BX 0x0001 /* Enable 1000BASE-X registers */
/*
+ * EXPANSION SHADOW ACCESS REGISTERS. (PHY REG 0x15, 0x16, and 0x17)
+ */
+#define MII_BCM54XX_EXP_AADJ1CH0 0x001f
+#define MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN 0x0200
+#define MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF 0x0100
+#define MII_BCM54XX_EXP_AADJ1CH3 0x601f
+#define MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ 0x0002
+#define MII_BCM54XX_EXP_EXP08 0x0F08
+#define MII_BCM54XX_EXP_EXP08_RJCT_2MHZ 0x0001
+#define MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE 0x0200
+#define MII_BCM54XX_EXP_EXP75 0x0f75
+#define MII_BCM54XX_EXP_EXP75_VDACCTRL 0x003c
+#define MII_BCM54XX_EXP_EXP96 0x0f96
+#define MII_BCM54XX_EXP_EXP96_MYST 0x0010
+#define MII_BCM54XX_EXP_EXP97 0x0f97
+#define MII_BCM54XX_EXP_EXP97_MYST 0x0c0c
+
+/*
* BCM5482: Secondary SerDes registers
*/
#define BCM5482_SSD_1000BX_CTL 0x00 /* 1000BASE-X Control */
@@ -128,40 +163,93 @@ static int bcm54xx_shadow_write(struct phy_device *phydev, u16 shadow, u16 val)
MII_BCM54XX_SHD_DATA(val));
}
-/*
- * Indirect register access functions for the Expansion Registers
- * and Secondary SerDes registers (when sec_serdes=1).
- */
-static int bcm54xx_exp_read(struct phy_device *phydev,
- int sec_serdes, u8 regnum)
+/* Indirect register access functions for the Expansion Registers */
+static int bcm54xx_exp_read(struct phy_device *phydev, u8 regnum)
{
int val;
- phy_write(phydev, MII_BCM54XX_EXP_SEL,
- (sec_serdes ? MII_BCM54XX_EXP_SEL_SSD :
- MII_BCM54XX_EXP_SEL_ER) |
- regnum);
+ val = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
+ if (val < 0)
+ return val;
+
val = phy_read(phydev, MII_BCM54XX_EXP_DATA);
- phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
+
+ /* Restore default value. It's O.K. if this write fails. */
+ phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
return val;
}
-static int bcm54xx_exp_write(struct phy_device *phydev,
- int sec_serdes, u8 regnum, u16 val)
+static int bcm54xx_exp_write(struct phy_device *phydev, u16 regnum, u16 val)
{
int ret;
- phy_write(phydev, MII_BCM54XX_EXP_SEL,
- (sec_serdes ? MII_BCM54XX_EXP_SEL_SSD :
- MII_BCM54XX_EXP_SEL_ER) |
- regnum);
+ ret = phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
+ if (ret < 0)
+ return ret;
+
ret = phy_write(phydev, MII_BCM54XX_EXP_DATA, val);
- phy_write(phydev, MII_BCM54XX_EXP_SEL, regnum);
+
+ /* Restore default value. It's O.K. if this write fails. */
+ phy_write(phydev, MII_BCM54XX_EXP_SEL, 0);
return ret;
}
+static int bcm54xx_auxctl_write(struct phy_device *phydev, u16 regnum, u16 val)
+{
+ return phy_write(phydev, MII_BCM54XX_AUX_CTL, regnum | val);
+}
+
+static int bcm50610_a0_workaround(struct phy_device *phydev)
+{
+ int err;
+
+ err = bcm54xx_auxctl_write(phydev,
+ MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
+ MII_BCM54XX_AUXCTL_ACTL_SMDSP_ENA |
+ MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
+ if (err < 0)
+ return err;
+
+ err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP08,
+ MII_BCM54XX_EXP_EXP08_RJCT_2MHZ |
+ MII_BCM54XX_EXP_EXP08_EARLY_DAC_WAKE);
+ if (err < 0)
+ goto error;
+
+ err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH0,
+ MII_BCM54XX_EXP_AADJ1CH0_SWP_ABCD_OEN |
+ MII_BCM54XX_EXP_AADJ1CH0_SWSEL_THPF);
+ if (err < 0)
+ goto error;
+
+ err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_AADJ1CH3,
+ MII_BCM54XX_EXP_AADJ1CH3_ADCCKADJ);
+ if (err < 0)
+ goto error;
+
+ err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP75,
+ MII_BCM54XX_EXP_EXP75_VDACCTRL);
+ if (err < 0)
+ goto error;
+
+ err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP96,
+ MII_BCM54XX_EXP_EXP96_MYST);
+ if (err < 0)
+ goto error;
+
+ err = bcm54xx_exp_write(phydev, MII_BCM54XX_EXP_EXP97,
+ MII_BCM54XX_EXP_EXP97_MYST);
+
+error:
+ bcm54xx_auxctl_write(phydev,
+ MII_BCM54XX_AUXCTL_SHDWSEL_AUXCTL,
+ MII_BCM54XX_AUXCTL_ACTL_TX_6DB);
+
+ return err;
+}
+
static int bcm54xx_config_init(struct phy_device *phydev)
{
int reg, err;
@@ -183,6 +271,13 @@ static int bcm54xx_config_init(struct phy_device *phydev)
err = phy_write(phydev, MII_BCM54XX_IMR, reg);
if (err < 0)
return err;
+
+ if (phydev->drv->phy_id == PHY_ID_BCM50610) {
+ err = bcm50610_a0_workaround(phydev);
+ if (err < 0)
+ return err;
+ }
+
return 0;
}
@@ -205,18 +300,27 @@ static int bcm5482_config_init(struct phy_device *phydev)
/*
* Enable SGMII slave mode and auto-detection
*/
- reg = bcm54xx_exp_read(phydev, 1, BCM5482_SSD_SGMII_SLAVE);
- bcm54xx_exp_write(phydev, 1, BCM5482_SSD_SGMII_SLAVE,
- reg |
- BCM5482_SSD_SGMII_SLAVE_EN |
- BCM5482_SSD_SGMII_SLAVE_AD);
+ reg = BCM5482_SSD_SGMII_SLAVE | MII_BCM54XX_EXP_SEL_SSD;
+ err = bcm54xx_exp_read(phydev, reg);
+ if (err < 0)
+ return err;
+ err = bcm54xx_exp_write(phydev, reg, err |
+ BCM5482_SSD_SGMII_SLAVE_EN |
+ BCM5482_SSD_SGMII_SLAVE_AD);
+ if (err < 0)
+ return err;
/*
* Disable secondary SerDes powerdown
*/
- reg = bcm54xx_exp_read(phydev, 1, BCM5482_SSD_1000BX_CTL);
- bcm54xx_exp_write(phydev, 1, BCM5482_SSD_1000BX_CTL,
- reg & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
+ reg = BCM5482_SSD_1000BX_CTL | MII_BCM54XX_EXP_SEL_SSD;
+ err = bcm54xx_exp_read(phydev, reg);
+ if (err < 0)
+ return err;
+ err = bcm54xx_exp_write(phydev, reg,
+ err & ~BCM5482_SSD_1000BX_CTL_PWRDOWN);
+ if (err < 0)
+ return err;
/*
* Select 1000BASE-X register set (primary SerDes)
@@ -335,7 +439,8 @@ static struct phy_driver bcm5411_driver = {
.phy_id = 0x00206070,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM5411",
- .features = PHY_GBIT_FEATURES,
+ .features = PHY_GBIT_FEATURES |
+ SUPPORTED_Pause | SUPPORTED_Asym_Pause,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
@@ -349,7 +454,8 @@ static struct phy_driver bcm5421_driver = {
.phy_id = 0x002060e0,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM5421",
- .features = PHY_GBIT_FEATURES,
+ .features = PHY_GBIT_FEATURES |
+ SUPPORTED_Pause | SUPPORTED_Asym_Pause,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
@@ -363,7 +469,8 @@ static struct phy_driver bcm5461_driver = {
.phy_id = 0x002060c0,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM5461",
- .features = PHY_GBIT_FEATURES,
+ .features = PHY_GBIT_FEATURES |
+ SUPPORTED_Pause | SUPPORTED_Asym_Pause,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
@@ -377,7 +484,8 @@ static struct phy_driver bcm5464_driver = {
.phy_id = 0x002060b0,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM5464",
- .features = PHY_GBIT_FEATURES,
+ .features = PHY_GBIT_FEATURES |
+ SUPPORTED_Pause | SUPPORTED_Asym_Pause,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = genphy_config_aneg,
@@ -391,7 +499,8 @@ static struct phy_driver bcm5481_driver = {
.phy_id = 0x0143bca0,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM5481",
- .features = PHY_GBIT_FEATURES,
+ .features = PHY_GBIT_FEATURES |
+ SUPPORTED_Pause | SUPPORTED_Asym_Pause,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm54xx_config_init,
.config_aneg = bcm5481_config_aneg,
@@ -405,7 +514,8 @@ static struct phy_driver bcm5482_driver = {
.phy_id = 0x0143bcb0,
.phy_id_mask = 0xfffffff0,
.name = "Broadcom BCM5482",
- .features = PHY_GBIT_FEATURES,
+ .features = PHY_GBIT_FEATURES |
+ SUPPORTED_Pause | SUPPORTED_Asym_Pause,
.flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
.config_init = bcm5482_config_init,
.config_aneg = genphy_config_aneg,
@@ -415,6 +525,36 @@ static struct phy_driver bcm5482_driver = {
.driver = { .owner = THIS_MODULE },
};
+static struct phy_driver bcm50610_driver = {
+ .phy_id = PHY_ID_BCM50610,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Broadcom BCM50610",
+ .features = PHY_GBIT_FEATURES |
+ SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+ .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+ .config_init = bcm54xx_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = bcm54xx_ack_interrupt,
+ .config_intr = bcm54xx_config_intr,
+ .driver = { .owner = THIS_MODULE },
+};
+
+static struct phy_driver bcm57780_driver = {
+ .phy_id = 0x03625d90,
+ .phy_id_mask = 0xfffffff0,
+ .name = "Broadcom BCM57780",
+ .features = PHY_GBIT_FEATURES |
+ SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+ .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+ .config_init = bcm54xx_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = bcm54xx_ack_interrupt,
+ .config_intr = bcm54xx_config_intr,
+ .driver = { .owner = THIS_MODULE },
+};
+
static int __init broadcom_init(void)
{
int ret;
@@ -437,8 +577,18 @@ static int __init broadcom_init(void)
ret = phy_driver_register(&bcm5482_driver);
if (ret)
goto out_5482;
+ ret = phy_driver_register(&bcm50610_driver);
+ if (ret)
+ goto out_50610;
+ ret = phy_driver_register(&bcm57780_driver);
+ if (ret)
+ goto out_57780;
return ret;
+out_57780:
+ phy_driver_unregister(&bcm50610_driver);
+out_50610:
+ phy_driver_unregister(&bcm5482_driver);
out_5482:
phy_driver_unregister(&bcm5481_driver);
out_5481:
@@ -455,6 +605,8 @@ out_5411:
static void __exit broadcom_exit(void)
{
+ phy_driver_unregister(&bcm57780_driver);
+ phy_driver_unregister(&bcm50610_driver);
phy_driver_unregister(&bcm5482_driver);
phy_driver_unregister(&bcm5481_driver);
phy_driver_unregister(&bcm5464_driver);
diff --git a/drivers/net/phy/et1011c.c b/drivers/net/phy/et1011c.c
new file mode 100644
index 000000000000..b031fa21f1aa
--- /dev/null
+++ b/drivers/net/phy/et1011c.c
@@ -0,0 +1,113 @@
+/*
+ * drivers/net/phy/et1011c.c
+ *
+ * Driver for LSI ET1011C PHYs
+ *
+ * Author: Chaithrika U S
+ *
+ * Copyright (c) 2008 Texas Instruments
+ *
+ * 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/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <asm/irq.h>
+
+#define ET1011C_STATUS_REG (0x1A)
+#define ET1011C_CONFIG_REG (0x16)
+#define ET1011C_SPEED_MASK (0x0300)
+#define ET1011C_GIGABIT_SPEED (0x0200)
+#define ET1011C_TX_FIFO_MASK (0x3000)
+#define ET1011C_TX_FIFO_DEPTH_8 (0x0000)
+#define ET1011C_TX_FIFO_DEPTH_16 (0x1000)
+#define ET1011C_INTERFACE_MASK (0x0007)
+#define ET1011C_GMII_INTERFACE (0x0002)
+#define ET1011C_SYS_CLK_EN (0x01 << 4)
+
+
+MODULE_DESCRIPTION("LSI ET1011C PHY driver");
+MODULE_AUTHOR("Chaithrika U S");
+MODULE_LICENSE("GPL");
+
+static int et1011c_config_aneg(struct phy_device *phydev)
+{
+ int ctl = 0;
+ ctl = phy_read(phydev, MII_BMCR);
+ if (ctl < 0)
+ return ctl;
+ ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_SPEED1000 |
+ BMCR_ANENABLE);
+ /* First clear the PHY */
+ phy_write(phydev, MII_BMCR, ctl | BMCR_RESET);
+
+ return genphy_config_aneg(phydev);
+}
+
+static int et1011c_read_status(struct phy_device *phydev)
+{
+ int ret;
+ u32 val;
+ static int speed;
+ ret = genphy_read_status(phydev);
+
+ if (speed != phydev->speed) {
+ speed = phydev->speed;
+ val = phy_read(phydev, ET1011C_STATUS_REG);
+ if ((val & ET1011C_SPEED_MASK) ==
+ ET1011C_GIGABIT_SPEED) {
+ val = phy_read(phydev, ET1011C_CONFIG_REG);
+ val &= ~ET1011C_TX_FIFO_MASK;
+ phy_write(phydev, ET1011C_CONFIG_REG, val\
+ | ET1011C_GMII_INTERFACE\
+ | ET1011C_SYS_CLK_EN\
+ | ET1011C_TX_FIFO_DEPTH_16);
+
+ }
+ }
+ return ret;
+}
+
+static struct phy_driver et1011c_driver = {
+ .phy_id = 0x0282f014,
+ .name = "ET1011C",
+ .phy_id_mask = 0xfffffff0,
+ .features = (PHY_BASIC_FEATURES | SUPPORTED_1000baseT_Full),
+ .flags = PHY_POLL,
+ .config_aneg = et1011c_config_aneg,
+ .read_status = et1011c_read_status,
+ .driver = { .owner = THIS_MODULE,},
+};
+
+static int __init et1011c_init(void)
+{
+ return phy_driver_register(&et1011c_driver);
+}
+
+static void __exit et1011c_exit(void)
+{
+ phy_driver_unregister(&et1011c_driver);
+}
+
+module_init(et1011c_init);
+module_exit(et1011c_exit);
diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c
new file mode 100644
index 000000000000..a439ebeb4319
--- /dev/null
+++ b/drivers/net/phy/mdio-gpio.c
@@ -0,0 +1,296 @@
+/*
+ * GPIO based MDIO bitbang driver.
+ * Supports OpenFirmware.
+ *
+ * Copyright (c) 2008 CSE Semaphore Belgium.
+ * by Laurent Pinchart <laurentp@cse-semaphore.com>
+ *
+ * Copyright (C) 2008, Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
+ *
+ * Based on earlier work by
+ *
+ * Copyright (c) 2003 Intracom S.A.
+ * by Pantelis Antoniou <panto@intracom.gr>
+ *
+ * 2005 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <vbordug@ru.mvista.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/mdio-gpio.h>
+
+#ifdef CONFIG_OF_GPIO
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+#endif
+
+struct mdio_gpio_info {
+ struct mdiobb_ctrl ctrl;
+ int mdc, mdio;
+};
+
+static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)
+{
+ struct mdio_gpio_info *bitbang =
+ container_of(ctrl, struct mdio_gpio_info, ctrl);
+
+ if (dir)
+ gpio_direction_output(bitbang->mdio, 1);
+ else
+ gpio_direction_input(bitbang->mdio);
+}
+
+static int mdio_get(struct mdiobb_ctrl *ctrl)
+{
+ struct mdio_gpio_info *bitbang =
+ container_of(ctrl, struct mdio_gpio_info, ctrl);
+
+ return gpio_get_value(bitbang->mdio);
+}
+
+static void mdio_set(struct mdiobb_ctrl *ctrl, int what)
+{
+ struct mdio_gpio_info *bitbang =
+ container_of(ctrl, struct mdio_gpio_info, ctrl);
+
+ gpio_set_value(bitbang->mdio, what);
+}
+
+static void mdc_set(struct mdiobb_ctrl *ctrl, int what)
+{
+ struct mdio_gpio_info *bitbang =
+ container_of(ctrl, struct mdio_gpio_info, ctrl);
+
+ gpio_set_value(bitbang->mdc, what);
+}
+
+static struct mdiobb_ops mdio_gpio_ops = {
+ .owner = THIS_MODULE,
+ .set_mdc = mdc_set,
+ .set_mdio_dir = mdio_dir,
+ .set_mdio_data = mdio_set,
+ .get_mdio_data = mdio_get,
+};
+
+static int __devinit mdio_gpio_bus_init(struct device *dev,
+ struct mdio_gpio_platform_data *pdata,
+ int bus_id)
+{
+ struct mii_bus *new_bus;
+ struct mdio_gpio_info *bitbang;
+ int ret = -ENOMEM;
+ int i;
+
+ bitbang = kzalloc(sizeof(*bitbang), GFP_KERNEL);
+ if (!bitbang)
+ goto out;
+
+ bitbang->ctrl.ops = &mdio_gpio_ops;
+ bitbang->mdc = pdata->mdc;
+ bitbang->mdio = pdata->mdio;
+
+ new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
+ if (!new_bus)
+ goto out_free_bitbang;
+
+ new_bus->name = "GPIO Bitbanged MDIO",
+
+ ret = -ENODEV;
+
+ new_bus->phy_mask = pdata->phy_mask;
+ new_bus->irq = pdata->irqs;
+ new_bus->parent = dev;
+
+ if (new_bus->phy_mask == ~0)
+ goto out_free_bus;
+
+ for (i = 0; i < PHY_MAX_ADDR; i++)
+ if (!new_bus->irq[i])
+ new_bus->irq[i] = PHY_POLL;
+
+ snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", bus_id);
+
+ if (gpio_request(bitbang->mdc, "mdc"))
+ goto out_free_bus;
+
+ if (gpio_request(bitbang->mdio, "mdio"))
+ goto out_free_mdc;
+
+ dev_set_drvdata(dev, new_bus);
+
+ ret = mdiobus_register(new_bus);
+ if (ret)
+ goto out_free_all;
+
+ return 0;
+
+out_free_all:
+ dev_set_drvdata(dev, NULL);
+ gpio_free(bitbang->mdio);
+out_free_mdc:
+ gpio_free(bitbang->mdc);
+out_free_bus:
+ free_mdio_bitbang(new_bus);
+out_free_bitbang:
+ kfree(bitbang);
+out:
+ return ret;
+}
+
+static void __devexit mdio_gpio_bus_destroy(struct device *dev)
+{
+ struct mii_bus *bus = dev_get_drvdata(dev);
+ struct mdio_gpio_info *bitbang = bus->priv;
+
+ mdiobus_unregister(bus);
+ free_mdio_bitbang(bus);
+ dev_set_drvdata(dev, NULL);
+ gpio_free(bitbang->mdc);
+ gpio_free(bitbang->mdio);
+ kfree(bitbang);
+}
+
+static int __devinit mdio_gpio_probe(struct platform_device *pdev)
+{
+ struct mdio_gpio_platform_data *pdata = pdev->dev.platform_data;
+
+ if (!pdata)
+ return -ENODEV;
+
+ return mdio_gpio_bus_init(&pdev->dev, pdata, pdev->id);
+}
+
+static int __devexit mdio_gpio_remove(struct platform_device *pdev)
+{
+ mdio_gpio_bus_destroy(&pdev->dev);
+
+ return 0;
+}
+
+#ifdef CONFIG_OF_GPIO
+static void __devinit add_phy(struct mdio_gpio_platform_data *pdata,
+ struct device_node *np)
+{
+ const u32 *data;
+ int len, id, irq;
+
+ data = of_get_property(np, "reg", &len);
+ if (!data || len != 4)
+ return;
+
+ id = *data;
+ pdata->phy_mask &= ~(1 << id);
+
+ irq = of_irq_to_resource(np, 0, NULL);
+ if (irq)
+ pdata->irqs[id] = irq;
+}
+
+static int __devinit mdio_ofgpio_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ struct device_node *np = NULL;
+ struct mdio_gpio_platform_data *pdata;
+
+ pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+
+ pdata->mdc = of_get_gpio(ofdev->node, 0);
+ pdata->mdio = of_get_gpio(ofdev->node, 1);
+
+ if (pdata->mdc < 0 || pdata->mdio < 0)
+ goto out_free;
+
+ while ((np = of_get_next_child(ofdev->node, np)))
+ if (!strcmp(np->type, "ethernet-phy"))
+ add_phy(pdata, np);
+
+ return mdio_gpio_bus_init(&ofdev->dev, pdata, pdata->mdc);
+
+out_free:
+ kfree(pdata);
+ return -ENODEV;
+}
+
+static int __devexit mdio_ofgpio_remove(struct of_device *ofdev)
+{
+ mdio_gpio_bus_destroy(&ofdev->dev);
+ kfree(ofdev->dev.platform_data);
+
+ return 0;
+}
+
+static struct of_device_id mdio_ofgpio_match[] = {
+ {
+ .compatible = "virtual,mdio-gpio",
+ },
+ {},
+};
+
+static struct of_platform_driver mdio_ofgpio_driver = {
+ .name = "mdio-gpio",
+ .match_table = mdio_ofgpio_match,
+ .probe = mdio_ofgpio_probe,
+ .remove = __devexit_p(mdio_ofgpio_remove),
+};
+
+static inline int __init mdio_ofgpio_init(void)
+{
+ return of_register_platform_driver(&mdio_ofgpio_driver);
+}
+
+static inline void __exit mdio_ofgpio_exit(void)
+{
+ of_unregister_platform_driver(&mdio_ofgpio_driver);
+}
+#else
+static inline int __init mdio_ofgpio_init(void) { return 0; }
+static inline void __exit mdio_ofgpio_exit(void) { }
+#endif /* CONFIG_OF_GPIO */
+
+static struct platform_driver mdio_gpio_driver = {
+ .probe = mdio_gpio_probe,
+ .remove = __devexit_p(mdio_gpio_remove),
+ .driver = {
+ .name = "mdio-gpio",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init mdio_gpio_init(void)
+{
+ int ret;
+
+ ret = mdio_ofgpio_init();
+ if (ret)
+ return ret;
+
+ ret = platform_driver_register(&mdio_gpio_driver);
+ if (ret)
+ mdio_ofgpio_exit();
+
+ return ret;
+}
+module_init(mdio_gpio_init);
+
+static void __exit mdio_gpio_exit(void)
+{
+ platform_driver_unregister(&mdio_gpio_driver);
+ mdio_ofgpio_exit();
+}
+module_exit(mdio_gpio_exit);
+
+MODULE_ALIAS("platform:mdio-gpio");
+MODULE_AUTHOR("Laurent Pinchart, Paulius Zaleckas");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Generic driver for MDIO bus emulation using GPIO");
diff --git a/drivers/net/phy/mdio-ofgpio.c b/drivers/net/phy/mdio-ofgpio.c
deleted file mode 100644
index 2ff97754e574..000000000000
--- a/drivers/net/phy/mdio-ofgpio.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * OpenFirmware GPIO based MDIO bitbang driver.
- *
- * Copyright (c) 2008 CSE Semaphore Belgium.
- * by Laurent Pinchart <laurentp@cse-semaphore.com>
- *
- * Based on earlier work by
- *
- * Copyright (c) 2003 Intracom S.A.
- * by Pantelis Antoniou <panto@intracom.gr>
- *
- * 2005 (c) MontaVista Software, Inc.
- * Vitaly Bordug <vbordug@ru.mvista.com>
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/mdio-bitbang.h>
-#include <linux/of_gpio.h>
-#include <linux/of_platform.h>
-
-struct mdio_gpio_info {
- struct mdiobb_ctrl ctrl;
- int mdc, mdio;
-};
-
-static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)
-{
- struct mdio_gpio_info *bitbang =
- container_of(ctrl, struct mdio_gpio_info, ctrl);
-
- if (dir)
- gpio_direction_output(bitbang->mdio, 1);
- else
- gpio_direction_input(bitbang->mdio);
-}
-
-static int mdio_read(struct mdiobb_ctrl *ctrl)
-{
- struct mdio_gpio_info *bitbang =
- container_of(ctrl, struct mdio_gpio_info, ctrl);
-
- return gpio_get_value(bitbang->mdio);
-}
-
-static void mdio(struct mdiobb_ctrl *ctrl, int what)
-{
- struct mdio_gpio_info *bitbang =
- container_of(ctrl, struct mdio_gpio_info, ctrl);
-
- gpio_set_value(bitbang->mdio, what);
-}
-
-static void mdc(struct mdiobb_ctrl *ctrl, int what)
-{
- struct mdio_gpio_info *bitbang =
- container_of(ctrl, struct mdio_gpio_info, ctrl);
-
- gpio_set_value(bitbang->mdc, what);
-}
-
-static struct mdiobb_ops mdio_gpio_ops = {
- .owner = THIS_MODULE,
- .set_mdc = mdc,
- .set_mdio_dir = mdio_dir,
- .set_mdio_data = mdio,
- .get_mdio_data = mdio_read,
-};
-
-static int __devinit mdio_ofgpio_bitbang_init(struct mii_bus *bus,
- struct device_node *np)
-{
- struct mdio_gpio_info *bitbang = bus->priv;
-
- bitbang->mdc = of_get_gpio(np, 0);
- bitbang->mdio = of_get_gpio(np, 1);
-
- if (bitbang->mdc < 0 || bitbang->mdio < 0)
- return -ENODEV;
-
- snprintf(bus->id, MII_BUS_ID_SIZE, "%x", bitbang->mdc);
- return 0;
-}
-
-static void __devinit add_phy(struct mii_bus *bus, struct device_node *np)
-{
- const u32 *data;
- int len, id, irq;
-
- data = of_get_property(np, "reg", &len);
- if (!data || len != 4)
- return;
-
- id = *data;
- bus->phy_mask &= ~(1 << id);
-
- irq = of_irq_to_resource(np, 0, NULL);
- if (irq != NO_IRQ)
- bus->irq[id] = irq;
-}
-
-static int __devinit mdio_ofgpio_probe(struct of_device *ofdev,
- const struct of_device_id *match)
-{
- struct device_node *np = NULL;
- struct mii_bus *new_bus;
- struct mdio_gpio_info *bitbang;
- int ret = -ENOMEM;
- int i;
-
- bitbang = kzalloc(sizeof(struct mdio_gpio_info), GFP_KERNEL);
- if (!bitbang)
- goto out;
-
- bitbang->ctrl.ops = &mdio_gpio_ops;
-
- new_bus = alloc_mdio_bitbang(&bitbang->ctrl);
- if (!new_bus)
- goto out_free_bitbang;
-
- new_bus->name = "GPIO Bitbanged MII",
-
- ret = mdio_ofgpio_bitbang_init(new_bus, ofdev->node);
- if (ret)
- goto out_free_bus;
-
- new_bus->phy_mask = ~0;
- new_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
- if (!new_bus->irq)
- goto out_free_bus;
-
- for (i = 0; i < PHY_MAX_ADDR; i++)
- new_bus->irq[i] = -1;
-
- while ((np = of_get_next_child(ofdev->node, np)))
- if (!strcmp(np->type, "ethernet-phy"))
- add_phy(new_bus, np);
-
- new_bus->parent = &ofdev->dev;
- dev_set_drvdata(&ofdev->dev, new_bus);
-
- ret = mdiobus_register(new_bus);
- if (ret)
- goto out_free_irqs;
-
- return 0;
-
-out_free_irqs:
- dev_set_drvdata(&ofdev->dev, NULL);
- kfree(new_bus->irq);
-out_free_bus:
- free_mdio_bitbang(new_bus);
-out_free_bitbang:
- kfree(bitbang);
-out:
- return ret;
-}
-
-static int mdio_ofgpio_remove(struct of_device *ofdev)
-{
- struct mii_bus *bus = dev_get_drvdata(&ofdev->dev);
- struct mdio_gpio_info *bitbang = bus->priv;
-
- mdiobus_unregister(bus);
- kfree(bus->irq);
- free_mdio_bitbang(bus);
- dev_set_drvdata(&ofdev->dev, NULL);
- kfree(bitbang);
-
- return 0;
-}
-
-static struct of_device_id mdio_ofgpio_match[] = {
- {
- .compatible = "virtual,mdio-gpio",
- },
- {},
-};
-
-static struct of_platform_driver mdio_ofgpio_driver = {
- .name = "mdio-gpio",
- .match_table = mdio_ofgpio_match,
- .probe = mdio_ofgpio_probe,
- .remove = mdio_ofgpio_remove,
-};
-
-static int mdio_ofgpio_init(void)
-{
- return of_register_platform_driver(&mdio_ofgpio_driver);
-}
-
-static void mdio_ofgpio_exit(void)
-{
- of_unregister_platform_driver(&mdio_ofgpio_driver);
-}
-
-module_init(mdio_ofgpio_init);
-module_exit(mdio_ofgpio_exit);
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 536bda1f428b..11adf6ed4628 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -63,7 +63,9 @@ EXPORT_SYMBOL(mdiobus_alloc);
static void mdiobus_release(struct device *d)
{
struct mii_bus *bus = to_mii_bus(d);
- BUG_ON(bus->state != MDIOBUS_RELEASED);
+ BUG_ON(bus->state != MDIOBUS_RELEASED &&
+ /* for compatibility with error handling in drivers */
+ bus->state != MDIOBUS_ALLOCATED);
kfree(bus);
}
@@ -83,8 +85,7 @@ static struct class mdio_bus_class = {
*/
int mdiobus_register(struct mii_bus *bus)
{
- int i;
- int err = 0;
+ int i, err;
if (NULL == bus || NULL == bus->name ||
NULL == bus->read ||
@@ -97,7 +98,7 @@ int mdiobus_register(struct mii_bus *bus)
bus->dev.parent = bus->parent;
bus->dev.class = &mdio_bus_class;
bus->dev.groups = NULL;
- memcpy(bus->dev.bus_id, bus->id, MII_BUS_ID_SIZE);
+ dev_set_name(&bus->dev, bus->id);
err = device_register(&bus->dev);
if (err) {
@@ -105,8 +106,6 @@ int mdiobus_register(struct mii_bus *bus)
return -EINVAL;
}
- bus->state = MDIOBUS_REGISTERED;
-
mutex_init(&bus->mdio_lock);
if (bus->reset)
@@ -118,13 +117,23 @@ int mdiobus_register(struct mii_bus *bus)
struct phy_device *phydev;
phydev = mdiobus_scan(bus, i);
- if (IS_ERR(phydev))
+ if (IS_ERR(phydev)) {
err = PTR_ERR(phydev);
+ goto error;
+ }
}
}
+ bus->state = MDIOBUS_REGISTERED;
pr_info("%s: probed\n", bus->name);
+ return 0;
+error:
+ while (--i >= 0) {
+ if (bus->phy_map[i])
+ device_unregister(&bus->phy_map[i]->dev);
+ }
+ device_del(&bus->dev);
return err;
}
EXPORT_SYMBOL(mdiobus_register);
@@ -191,7 +200,7 @@ struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr)
phydev->dev.parent = bus->parent;
phydev->dev.bus = &mdio_bus_type;
- snprintf(phydev->dev.bus_id, BUS_ID_SIZE, PHY_ID_FMT, bus->id, addr);
+ dev_set_name(&phydev->dev, PHY_ID_FMT, bus->id, addr);
phydev->bus = bus;
@@ -284,9 +293,12 @@ static int mdio_bus_suspend(struct device * dev, pm_message_t state)
{
int ret = 0;
struct device_driver *drv = dev->driver;
+ struct phy_driver *phydrv = to_phy_driver(drv);
+ struct phy_device *phydev = to_phy_device(dev);
- if (drv && drv->suspend)
- ret = drv->suspend(dev, state);
+ if ((!device_may_wakeup(phydev->dev.parent)) &&
+ (phydrv && phydrv->suspend))
+ ret = phydrv->suspend(phydev);
return ret;
}
@@ -295,9 +307,12 @@ static int mdio_bus_resume(struct device * dev)
{
int ret = 0;
struct device_driver *drv = dev->driver;
+ struct phy_driver *phydrv = to_phy_driver(drv);
+ struct phy_device *phydev = to_phy_device(dev);
- if (drv && drv->resume)
- ret = drv->resume(dev);
+ if ((!device_may_wakeup(phydev->dev.parent)) &&
+ (phydrv && phydrv->resume))
+ ret = phydrv->resume(phydev);
return ret;
}
diff --git a/drivers/net/phy/national.c b/drivers/net/phy/national.c
new file mode 100644
index 000000000000..6c636eb72089
--- /dev/null
+++ b/drivers/net/phy/national.c
@@ -0,0 +1,155 @@
+/*
+ * drivers/net/phy/national.c
+ *
+ * Driver for National Semiconductor PHYs
+ *
+ * Author: Stuart Menefy <stuart.menefy@st.com>
+ * Maintainer: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+ *
+ * Copyright (c) 2008 STMicroelectronics Limited
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/mii.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+#include <linux/netdevice.h>
+
+/* DP83865 phy identifier values */
+#define DP83865_PHY_ID 0x20005c7a
+
+#define DP83865_INT_MASK_REG 0x15
+#define DP83865_INT_MASK_STATUS 0x14
+
+#define DP83865_INT_REMOTE_FAULT 0x0008
+#define DP83865_INT_ANE_COMPLETED 0x0010
+#define DP83865_INT_LINK_CHANGE 0xe000
+#define DP83865_INT_MASK_DEFAULT (DP83865_INT_REMOTE_FAULT | \
+ DP83865_INT_ANE_COMPLETED | \
+ DP83865_INT_LINK_CHANGE)
+
+/* Advanced proprietary configuration */
+#define NS_EXP_MEM_CTL 0x16
+#define NS_EXP_MEM_DATA 0x1d
+#define NS_EXP_MEM_ADD 0x1e
+
+#define LED_CTRL_REG 0x13
+#define AN_FALLBACK_AN 0x0001
+#define AN_FALLBACK_CRC 0x0002
+#define AN_FALLBACK_IE 0x0004
+#define ALL_FALLBACK_ON (AN_FALLBACK_AN | AN_FALLBACK_CRC | AN_FALLBACK_IE)
+
+enum hdx_loopback {
+ hdx_loopback_on = 0,
+ hdx_loopback_off = 1,
+};
+
+static u8 ns_exp_read(struct phy_device *phydev, u16 reg)
+{
+ phy_write(phydev, NS_EXP_MEM_ADD, reg);
+ return phy_read(phydev, NS_EXP_MEM_DATA);
+}
+
+static void ns_exp_write(struct phy_device *phydev, u16 reg, u8 data)
+{
+ phy_write(phydev, NS_EXP_MEM_ADD, reg);
+ phy_write(phydev, NS_EXP_MEM_DATA, data);
+}
+
+static int ns_config_intr(struct phy_device *phydev)
+{
+ int err;
+
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
+ err = phy_write(phydev, DP83865_INT_MASK_REG,
+ DP83865_INT_MASK_DEFAULT);
+ else
+ err = phy_write(phydev, DP83865_INT_MASK_REG, 0);
+
+ return err;
+}
+
+static int ns_ack_interrupt(struct phy_device *phydev)
+{
+ int ret = phy_read(phydev, DP83865_INT_MASK_STATUS);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static void ns_giga_speed_fallback(struct phy_device *phydev, int mode)
+{
+ int bmcr = phy_read(phydev, MII_BMCR);
+
+ phy_write(phydev, MII_BMCR, (bmcr | BMCR_PDOWN));
+
+ /* Enable 8 bit expended memory read/write (no auto increment) */
+ phy_write(phydev, NS_EXP_MEM_CTL, 0);
+ phy_write(phydev, NS_EXP_MEM_ADD, 0x1C0);
+ phy_write(phydev, NS_EXP_MEM_DATA, 0x0008);
+ phy_write(phydev, MII_BMCR, (bmcr & ~BMCR_PDOWN));
+ phy_write(phydev, LED_CTRL_REG, mode);
+ return;
+}
+
+static void ns_10_base_t_hdx_loopack(struct phy_device *phydev, int disable)
+{
+ if (disable)
+ ns_exp_write(phydev, 0x1c0, ns_exp_read(phydev, 0x1c0) | 1);
+ else
+ ns_exp_write(phydev, 0x1c0,
+ ns_exp_read(phydev, 0x1c0) & 0xfffe);
+
+ printk(KERN_DEBUG "DP83865 PHY: 10BASE-T HDX loopback %s\n",
+ (ns_exp_read(phydev, 0x1c0) & 0x0001) ? "off" : "on");
+
+ return;
+}
+
+static int ns_config_init(struct phy_device *phydev)
+{
+ ns_giga_speed_fallback(phydev, ALL_FALLBACK_ON);
+ /* In the latest MAC or switches design, the 10 Mbps loopback
+ is desired to be turned off. */
+ ns_10_base_t_hdx_loopack(phydev, hdx_loopback_off);
+ return ns_ack_interrupt(phydev);
+}
+
+static struct phy_driver dp83865_driver = {
+ .phy_id = DP83865_PHY_ID,
+ .phy_id_mask = 0xfffffff0,
+ .name = "NatSemi DP83865",
+ .features = PHY_GBIT_FEATURES | SUPPORTED_Pause | SUPPORTED_Asym_Pause,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = ns_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = ns_ack_interrupt,
+ .config_intr = ns_config_intr,
+ .driver = {.owner = THIS_MODULE,}
+};
+
+static int __init ns_init(void)
+{
+ return phy_driver_register(&dp83865_driver);
+}
+
+static void __exit ns_exit(void)
+{
+ phy_driver_unregister(&dp83865_driver);
+}
+
+MODULE_DESCRIPTION("NatSemi PHY driver");
+MODULE_AUTHOR("Stuart Menefy");
+MODULE_LICENSE("GPL");
+
+module_init(ns_init);
+module_exit(ns_exit);
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index df4e6257d4a7..e4ede6080c9d 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -45,7 +45,7 @@
*/
void phy_print_status(struct phy_device *phydev)
{
- pr_info("PHY: %s - Link is %s", phydev->dev.bus_id,
+ pr_info("PHY: %s - Link is %s", dev_name(&phydev->dev),
phydev->link ? "Up" : "Down");
if (phydev->link)
printk(" - %d/%s", phydev->speed,
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 25acbbde4a60..e35460165bf7 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -74,7 +74,7 @@ int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
if (!fixup)
return -ENOMEM;
- strncpy(fixup->bus_id, bus_id, BUS_ID_SIZE);
+ strlcpy(fixup->bus_id, bus_id, sizeof(fixup->bus_id));
fixup->phy_uid = phy_uid;
fixup->phy_uid_mask = phy_uid_mask;
fixup->run = run;
@@ -109,7 +109,7 @@ EXPORT_SYMBOL(phy_register_fixup_for_id);
*/
static int phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup)
{
- if (strcmp(fixup->bus_id, phydev->dev.bus_id) != 0)
+ if (strcmp(fixup->bus_id, dev_name(&phydev->dev)) != 0)
if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0)
return 0;
@@ -232,7 +232,7 @@ struct phy_device * get_phy_device(struct mii_bus *bus, int addr)
return NULL;
/*
- * Broken hardware is sometimes missing the pull down resistor on the
+ * Broken hardware is sometimes missing the pull-up resistor on the
* MDIO line, which results in reads to non-existent devices returning
* 0 rather than 0xffff. Catch this here and treat 0 as a non-existent
* device as well.
@@ -517,23 +517,6 @@ int genphy_setup_forced(struct phy_device *phydev)
err = phy_write(phydev, MII_BMCR, ctl);
- if (err < 0)
- return err;
-
- /*
- * Run the fixups on this PHY, just in case the
- * board code needs to change something after a reset
- */
- err = phy_scan_fixups(phydev);
-
- if (err < 0)
- return err;
-
- /* We just reset the device, so we'd better configure any
- * settings the PHY requires to operate */
- if (phydev->drv->config_init)
- err = phydev->drv->config_init(phydev);
-
return err;
}
@@ -779,7 +762,35 @@ static int genphy_config_init(struct phy_device *phydev)
return 0;
}
+int genphy_suspend(struct phy_device *phydev)
+{
+ int value;
+ mutex_lock(&phydev->lock);
+
+ value = phy_read(phydev, MII_BMCR);
+ phy_write(phydev, MII_BMCR, (value | BMCR_PDOWN));
+
+ mutex_unlock(&phydev->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(genphy_suspend);
+
+int genphy_resume(struct phy_device *phydev)
+{
+ int value;
+
+ mutex_lock(&phydev->lock);
+
+ value = phy_read(phydev, MII_BMCR);
+ phy_write(phydev, MII_BMCR, (value & ~BMCR_PDOWN));
+
+ mutex_unlock(&phydev->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(genphy_resume);
/**
* phy_probe - probe and init a PHY device
@@ -855,7 +866,6 @@ int phy_driver_register(struct phy_driver *new_driver)
{
int retval;
- memset(&new_driver->driver, 0, sizeof(new_driver->driver));
new_driver->driver.name = new_driver->name;
new_driver->driver.bus = &mdio_bus_type;
new_driver->driver.probe = phy_probe;
@@ -890,6 +900,8 @@ static struct phy_driver genphy_driver = {
.features = 0,
.config_aneg = genphy_config_aneg,
.read_status = genphy_read_status,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
.driver = {.owner= THIS_MODULE, },
};
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 73baa7a3bb0e..c05d38d46350 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -126,6 +126,27 @@ static struct phy_driver lan8700_driver = {
.driver = { .owner = THIS_MODULE, }
};
+static struct phy_driver lan911x_int_driver = {
+ .phy_id = 0x0007c0d0, /* OUI=0x00800f, Model#=0x0d */
+ .phy_id_mask = 0xfffffff0,
+ .name = "SMSC LAN911x Internal PHY",
+
+ .features = (PHY_BASIC_FEATURES | SUPPORTED_Pause
+ | SUPPORTED_Asym_Pause),
+ .flags = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
+
+ /* basic functions */
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .config_init = smsc_phy_config_init,
+
+ /* IRQ related */
+ .ack_interrupt = smsc_phy_ack_interrupt,
+ .config_intr = smsc_phy_config_intr,
+
+ .driver = { .owner = THIS_MODULE, }
+};
+
static int __init smsc_init(void)
{
int ret;
@@ -142,8 +163,14 @@ static int __init smsc_init(void)
if (ret)
goto err3;
+ ret = phy_driver_register (&lan911x_int_driver);
+ if (ret)
+ goto err4;
+
return 0;
+err4:
+ phy_driver_unregister (&lan8700_driver);
err3:
phy_driver_unregister (&lan8187_driver);
err2:
@@ -154,6 +181,7 @@ err1:
static void __exit smsc_exit(void)
{
+ phy_driver_unregister (&lan911x_int_driver);
phy_driver_unregister (&lan8700_driver);
phy_driver_unregister (&lan8187_driver);
phy_driver_unregister (&lan83c185_driver);
diff --git a/drivers/net/phy/ste10Xp.c b/drivers/net/phy/ste10Xp.c
new file mode 100644
index 000000000000..6bdb0d53aaf9
--- /dev/null
+++ b/drivers/net/phy/ste10Xp.c
@@ -0,0 +1,137 @@
+/*
+ * drivers/net/phy/ste10Xp.c
+ *
+ * Driver for STMicroelectronics STe10Xp PHYs
+ *
+ * Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
+ *
+ * Copyright (c) 2008 STMicroelectronics Limited
+ *
+ * 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/init.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+
+#define MII_XCIIS 0x11 /* Configuration Info IRQ & Status Reg */
+#define MII_XIE 0x12 /* Interrupt Enable Register */
+#define MII_XIE_DEFAULT_MASK 0x0070 /* ANE complete, Remote Fault, Link Down */
+
+#define STE101P_PHY_ID 0x00061c50
+#define STE100P_PHY_ID 0x1c040011
+
+static int ste10Xp_config_init(struct phy_device *phydev)
+{
+ int value, err;
+
+ /* Software Reset PHY */
+ value = phy_read(phydev, MII_BMCR);
+ if (value < 0)
+ return value;
+
+ value |= BMCR_RESET;
+ err = phy_write(phydev, MII_BMCR, value);
+ if (err < 0)
+ return err;
+
+ do {
+ value = phy_read(phydev, MII_BMCR);
+ } while (value & BMCR_RESET);
+
+ return 0;
+}
+
+static int ste10Xp_config_intr(struct phy_device *phydev)
+{
+ int err, value;
+
+ if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
+ /* Enable all STe101P interrupts (PR12) */
+ err = phy_write(phydev, MII_XIE, MII_XIE_DEFAULT_MASK);
+ /* clear any pending interrupts */
+ if (err == 0) {
+ value = phy_read(phydev, MII_XCIIS);
+ if (value < 0)
+ err = value;
+ }
+ } else
+ err = phy_write(phydev, MII_XIE, 0);
+
+ return err;
+}
+
+static int ste10Xp_ack_interrupt(struct phy_device *phydev)
+{
+ int err = phy_read(phydev, MII_XCIIS);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static struct phy_driver ste101p_pdriver = {
+ .phy_id = STE101P_PHY_ID,
+ .phy_id_mask = 0xfffffff0,
+ .name = "STe101p",
+ .features = PHY_BASIC_FEATURES | SUPPORTED_Pause,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = ste10Xp_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = ste10Xp_ack_interrupt,
+ .config_intr = ste10Xp_config_intr,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .driver = {.owner = THIS_MODULE,}
+};
+
+static struct phy_driver ste100p_pdriver = {
+ .phy_id = STE100P_PHY_ID,
+ .phy_id_mask = 0xffffffff,
+ .name = "STe100p",
+ .features = PHY_BASIC_FEATURES | SUPPORTED_Pause,
+ .flags = PHY_HAS_INTERRUPT,
+ .config_init = ste10Xp_config_init,
+ .config_aneg = genphy_config_aneg,
+ .read_status = genphy_read_status,
+ .ack_interrupt = ste10Xp_ack_interrupt,
+ .config_intr = ste10Xp_config_intr,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .driver = {.owner = THIS_MODULE,}
+};
+
+static int __init ste10Xp_init(void)
+{
+ int retval;
+
+ retval = phy_driver_register(&ste100p_pdriver);
+ if (retval < 0)
+ return retval;
+ return phy_driver_register(&ste101p_pdriver);
+}
+
+static void __exit ste10Xp_exit(void)
+{
+ phy_driver_unregister(&ste100p_pdriver);
+ phy_driver_unregister(&ste101p_pdriver);
+}
+
+module_init(ste10Xp_init);
+module_exit(ste10Xp_exit);
+
+MODULE_DESCRIPTION("STMicroelectronics STe10Xp PHY driver");
+MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/plip.c b/drivers/net/plip.c
index 1e965427b0e9..0c46d603b8fe 100644
--- a/drivers/net/plip.c
+++ b/drivers/net/plip.c
@@ -229,7 +229,7 @@ static inline void enable_parport_interrupts (struct net_device *dev)
if (dev->irq != -1)
{
struct parport *port =
- ((struct net_local *)dev->priv)->pardev->port;
+ ((struct net_local *)netdev_priv(dev))->pardev->port;
port->ops->enable_irq (port);
}
}
@@ -239,7 +239,7 @@ static inline void disable_parport_interrupts (struct net_device *dev)
if (dev->irq != -1)
{
struct parport *port =
- ((struct net_local *)dev->priv)->pardev->port;
+ ((struct net_local *)netdev_priv(dev))->pardev->port;
port->ops->disable_irq (port);
}
}
@@ -247,7 +247,7 @@ static inline void disable_parport_interrupts (struct net_device *dev)
static inline void write_data (struct net_device *dev, unsigned char data)
{
struct parport *port =
- ((struct net_local *)dev->priv)->pardev->port;
+ ((struct net_local *)netdev_priv(dev))->pardev->port;
port->ops->write_data (port, data);
}
@@ -255,7 +255,7 @@ static inline void write_data (struct net_device *dev, unsigned char data)
static inline unsigned char read_status (struct net_device *dev)
{
struct parport *port =
- ((struct net_local *)dev->priv)->pardev->port;
+ ((struct net_local *)netdev_priv(dev))->pardev->port;
return port->ops->read_status (port);
}
@@ -638,14 +638,14 @@ plip_receive_packet(struct net_device *dev, struct net_local *nl,
case PLIP_PK_DATA:
lbuf = rcv->skb->data;
- do
+ do {
if (plip_receive(nibble_timeout, dev,
&rcv->nibble, &lbuf[rcv->byte]))
return TIMEOUT;
- while (++rcv->byte < rcv->length.h);
- do
+ } while (++rcv->byte < rcv->length.h);
+ do {
rcv->checksum += lbuf[--rcv->byte];
- while (rcv->byte);
+ } while (rcv->byte);
rcv->state = PLIP_PK_CHECKSUM;
case PLIP_PK_CHECKSUM:
@@ -664,7 +664,6 @@ plip_receive_packet(struct net_device *dev, struct net_local *nl,
/* Inform the upper layer for the arrival of a packet. */
rcv->skb->protocol=plip_type_trans(rcv->skb, dev);
netif_rx_ni(rcv->skb);
- dev->last_rx = jiffies;
dev->stats.rx_bytes += rcv->length.h;
dev->stats.rx_packets++;
rcv->skb = NULL;
@@ -817,14 +816,14 @@ plip_send_packet(struct net_device *dev, struct net_local *nl,
snd->checksum = 0;
case PLIP_PK_DATA:
- do
+ do {
if (plip_send(nibble_timeout, dev,
&snd->nibble, lbuf[snd->byte]))
return TIMEOUT;
- while (++snd->byte < snd->length.h);
- do
+ } while (++snd->byte < snd->length.h);
+ do {
snd->checksum += lbuf[--snd->byte];
- while (snd->byte);
+ } while (snd->byte);
snd->state = PLIP_PK_CHECKSUM;
case PLIP_PK_CHECKSUM:
@@ -1018,8 +1017,8 @@ plip_hard_header(struct sk_buff *skb, struct net_device *dev,
return ret;
}
-int plip_hard_header_cache(const struct neighbour *neigh,
- struct hh_cache *hh)
+static int plip_hard_header_cache(const struct neighbour *neigh,
+ struct hh_cache *hh)
{
int ret;
@@ -1397,9 +1396,3 @@ static int __init plip_init (void)
module_init(plip_init);
module_exit(plip_cleanup_module);
MODULE_LICENSE("GPL");
-
-/*
- * Local variables:
- * compile-command: "gcc -DMODULE -DMODVERSIONS -D__KERNEL__ -Wall -Wstrict-prototypes -O2 -g -fomit-frame-pointer -pipe -c plip.c"
- * End:
- */
diff --git a/drivers/net/ppp_async.c b/drivers/net/ppp_async.c
index 451bdb57d6fc..6567fabd2e13 100644
--- a/drivers/net/ppp_async.c
+++ b/drivers/net/ppp_async.c
@@ -293,9 +293,6 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
err = -EFAULT;
switch (cmd) {
case PPPIOCGCHAN:
- err = -ENXIO;
- if (!ap)
- break;
err = -EFAULT;
if (put_user(ppp_channel_index(&ap->chan), p))
break;
@@ -303,9 +300,6 @@ ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
break;
case PPPIOCGUNIT:
- err = -ENXIO;
- if (!ap)
- break;
err = -EFAULT;
if (put_user(ppp_unit_number(&ap->chan), p))
break;
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
index 7e857e938adb..06b448285eb5 100644
--- a/drivers/net/ppp_generic.c
+++ b/drivers/net/ppp_generic.c
@@ -27,6 +27,7 @@
#include <linux/kmod.h>
#include <linux/init.h>
#include <linux/list.h>
+#include <linux/idr.h>
#include <linux/netdevice.h>
#include <linux/poll.h>
#include <linux/ppp_defs.h>
@@ -116,6 +117,7 @@ struct ppp {
unsigned long last_xmit; /* jiffies when last pkt sent 9c */
unsigned long last_recv; /* jiffies when last pkt rcvd a0 */
struct net_device *dev; /* network interface device a4 */
+ int closing; /* is device closing down? a8 */
#ifdef CONFIG_PPP_MULTILINK
int nxchan; /* next channel to send something on */
u32 nxseq; /* next sequence number to send */
@@ -172,35 +174,13 @@ struct channel {
*/
/*
- * A cardmap represents a mapping from unsigned integers to pointers,
- * and provides a fast "find lowest unused number" operation.
- * It uses a broad (32-way) tree with a bitmap at each level.
- * It is designed to be space-efficient for small numbers of entries
- * and time-efficient for large numbers of entries.
- */
-#define CARDMAP_ORDER 5
-#define CARDMAP_WIDTH (1U << CARDMAP_ORDER)
-#define CARDMAP_MASK (CARDMAP_WIDTH - 1)
-
-struct cardmap {
- int shift;
- unsigned long inuse;
- struct cardmap *parent;
- void *ptr[CARDMAP_WIDTH];
-};
-static void *cardmap_get(struct cardmap *map, unsigned int nr);
-static int cardmap_set(struct cardmap **map, unsigned int nr, void *ptr);
-static unsigned int cardmap_find_first_free(struct cardmap *map);
-static void cardmap_destroy(struct cardmap **map);
-
-/*
* all_ppp_mutex protects the all_ppp_units mapping.
* It also ensures that finding a ppp unit in the all_ppp_units map
* and updating its file.refcnt field is atomic.
*/
static DEFINE_MUTEX(all_ppp_mutex);
-static struct cardmap *all_ppp_units;
static atomic_t ppp_unit_count = ATOMIC_INIT(0);
+static DEFINE_IDR(ppp_units_idr);
/*
* all_channels_lock protects all_channels and last_channel_index,
@@ -269,6 +249,9 @@ static struct channel *ppp_find_channel(int unit);
static int ppp_connect_channel(struct channel *pch, int unit);
static int ppp_disconnect_channel(struct channel *pch);
static void ppp_destroy_channel(struct channel *pch);
+static int unit_get(struct idr *p, void *ptr);
+static void unit_put(struct idr *p, int n);
+static void *unit_find(struct idr *p, int n);
static struct class *ppp_class;
@@ -886,7 +869,7 @@ out_chrdev:
static int
ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct ppp *ppp = (struct ppp *) dev->priv;
+ struct ppp *ppp = netdev_priv(dev);
int npi, proto;
unsigned char *pp;
@@ -931,7 +914,7 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev)
static int
ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
- struct ppp *ppp = dev->priv;
+ struct ppp *ppp = netdev_priv(dev);
int err = -EFAULT;
void __user *addr = (void __user *) ifr->ifr_ifru.ifru_data;
struct ppp_stats stats;
@@ -971,8 +954,14 @@ ppp_net_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return err;
}
+static const struct net_device_ops ppp_netdev_ops = {
+ .ndo_start_xmit = ppp_start_xmit,
+ .ndo_do_ioctl = ppp_net_ioctl,
+};
+
static void ppp_setup(struct net_device *dev)
{
+ dev->netdev_ops = &ppp_netdev_ops;
dev->hard_header_len = PPP_HDRLEN;
dev->mtu = PPP_MTU;
dev->addr_len = 0;
@@ -995,7 +984,7 @@ ppp_xmit_process(struct ppp *ppp)
struct sk_buff *skb;
ppp_xmit_lock(ppp);
- if (ppp->dev) {
+ if (!ppp->closing) {
ppp_push(ppp);
while (!ppp->xmit_pending
&& (skb = skb_dequeue(&ppp->file.xq)))
@@ -1463,8 +1452,7 @@ static inline void
ppp_do_recv(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
{
ppp_recv_lock(ppp);
- /* ppp->dev == 0 means interface is closing down */
- if (ppp->dev)
+ if (!ppp->closing)
ppp_receive_frame(ppp, skb, pch);
else
kfree_skb(skb);
@@ -1684,7 +1672,6 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb)
skb->protocol = htons(npindex_to_ethertype[npi]);
skb_reset_mac_header(skb);
netif_rx(skb);
- ppp->dev->last_rx = jiffies;
}
}
return;
@@ -2414,13 +2401,12 @@ ppp_create_interface(int unit, int *retp)
int ret = -ENOMEM;
int i;
- ppp = kzalloc(sizeof(struct ppp), GFP_KERNEL);
- if (!ppp)
- goto out;
- dev = alloc_netdev(0, "", ppp_setup);
+ dev = alloc_netdev(sizeof(struct ppp), "", ppp_setup);
if (!dev)
goto out1;
+ ppp = netdev_priv(dev);
+ ppp->dev = dev;
ppp->mru = PPP_MRU;
init_ppp_file(&ppp->file, INTERFACE);
ppp->file.hdrlen = PPP_HDRLEN - 2; /* don't count proto bytes */
@@ -2433,18 +2419,25 @@ ppp_create_interface(int unit, int *retp)
ppp->minseq = -1;
skb_queue_head_init(&ppp->mrq);
#endif /* CONFIG_PPP_MULTILINK */
- ppp->dev = dev;
- dev->priv = ppp;
-
- dev->hard_start_xmit = ppp_start_xmit;
- dev->do_ioctl = ppp_net_ioctl;
ret = -EEXIST;
mutex_lock(&all_ppp_mutex);
- if (unit < 0)
- unit = cardmap_find_first_free(all_ppp_units);
- else if (cardmap_get(all_ppp_units, unit) != NULL)
- goto out2; /* unit already exists */
+
+ if (unit < 0) {
+ unit = unit_get(&ppp_units_idr, ppp);
+ if (unit < 0) {
+ *retp = unit;
+ goto out2;
+ }
+ } else {
+ if (unit_find(&ppp_units_idr, unit))
+ goto out2; /* unit already exists */
+ else {
+ /* darn, someone is cheating us? */
+ *retp = -EINVAL;
+ goto out2;
+ }
+ }
/* Initialize the new ppp unit */
ppp->file.index = unit;
@@ -2452,29 +2445,22 @@ ppp_create_interface(int unit, int *retp)
ret = register_netdev(dev);
if (ret != 0) {
+ unit_put(&ppp_units_idr, unit);
printk(KERN_ERR "PPP: couldn't register device %s (%d)\n",
dev->name, ret);
goto out2;
}
atomic_inc(&ppp_unit_count);
- ret = cardmap_set(&all_ppp_units, unit, ppp);
- if (ret != 0)
- goto out3;
-
mutex_unlock(&all_ppp_mutex);
+
*retp = 0;
return ppp;
-out3:
- atomic_dec(&ppp_unit_count);
- unregister_netdev(dev);
out2:
mutex_unlock(&all_ppp_mutex);
free_netdev(dev);
out1:
- kfree(ppp);
-out:
*retp = ret;
return NULL;
}
@@ -2498,19 +2484,17 @@ init_ppp_file(struct ppp_file *pf, int kind)
*/
static void ppp_shutdown_interface(struct ppp *ppp)
{
- struct net_device *dev;
-
mutex_lock(&all_ppp_mutex);
- ppp_lock(ppp);
- dev = ppp->dev;
- ppp->dev = NULL;
- ppp_unlock(ppp);
/* This will call dev_close() for us. */
- if (dev) {
- unregister_netdev(dev);
- free_netdev(dev);
- }
- cardmap_set(&all_ppp_units, ppp->file.index, NULL);
+ ppp_lock(ppp);
+ if (!ppp->closing) {
+ ppp->closing = 1;
+ ppp_unlock(ppp);
+ unregister_netdev(ppp->dev);
+ } else
+ ppp_unlock(ppp);
+
+ unit_put(&ppp_units_idr, ppp->file.index);
ppp->file.dead = 1;
ppp->owner = NULL;
wake_up_interruptible(&ppp->file.rwait);
@@ -2554,7 +2538,7 @@ static void ppp_destroy_interface(struct ppp *ppp)
if (ppp->xmit_pending)
kfree_skb(ppp->xmit_pending);
- kfree(ppp);
+ free_netdev(ppp->dev);
}
/*
@@ -2564,7 +2548,7 @@ static void ppp_destroy_interface(struct ppp *ppp)
static struct ppp *
ppp_find_unit(int unit)
{
- return cardmap_get(all_ppp_units, unit);
+ return unit_find(&ppp_units_idr, unit);
}
/*
@@ -2616,7 +2600,7 @@ ppp_connect_channel(struct channel *pch, int unit)
if (pch->file.hdrlen > ppp->file.hdrlen)
ppp->file.hdrlen = pch->file.hdrlen;
hdrlen = pch->file.hdrlen + 2; /* for protocol bytes */
- if (ppp->dev && hdrlen > ppp->dev->hard_header_len)
+ if (hdrlen > ppp->dev->hard_header_len)
ppp->dev->hard_header_len = hdrlen;
list_add_tail(&pch->clist, &ppp->channels);
++ppp->n_channels;
@@ -2682,123 +2666,45 @@ static void __exit ppp_cleanup(void)
/* should never happen */
if (atomic_read(&ppp_unit_count) || atomic_read(&channel_count))
printk(KERN_ERR "PPP: removing module but units remain!\n");
- cardmap_destroy(&all_ppp_units);
unregister_chrdev(PPP_MAJOR, "ppp");
device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0));
class_destroy(ppp_class);
+ idr_destroy(&ppp_units_idr);
}
/*
- * Cardmap implementation.
+ * Units handling. Caller must protect concurrent access
+ * by holding all_ppp_mutex
*/
-static void *cardmap_get(struct cardmap *map, unsigned int nr)
+
+/* get new free unit number and associate pointer with it */
+static int unit_get(struct idr *p, void *ptr)
{
- struct cardmap *p;
- int i;
+ int unit, err;
- for (p = map; p != NULL; ) {
- if ((i = nr >> p->shift) >= CARDMAP_WIDTH)
- return NULL;
- if (p->shift == 0)
- return p->ptr[i];
- nr &= ~(CARDMAP_MASK << p->shift);
- p = p->ptr[i];
+again:
+ if (idr_pre_get(p, GFP_KERNEL) == 0) {
+ printk(KERN_ERR "Out of memory expanding drawable idr\n");
+ return -ENOMEM;
}
- return NULL;
-}
-static int cardmap_set(struct cardmap **pmap, unsigned int nr, void *ptr)
-{
- struct cardmap *p;
- int i;
+ err = idr_get_new_above(p, ptr, 0, &unit);
+ if (err == -EAGAIN)
+ goto again;
- p = *pmap;
- if (p == NULL || (nr >> p->shift) >= CARDMAP_WIDTH) {
- do {
- /* need a new top level */
- struct cardmap *np = kzalloc(sizeof(*np), GFP_KERNEL);
- if (!np)
- goto enomem;
- np->ptr[0] = p;
- if (p != NULL) {
- np->shift = p->shift + CARDMAP_ORDER;
- p->parent = np;
- } else
- np->shift = 0;
- p = np;
- } while ((nr >> p->shift) >= CARDMAP_WIDTH);
- *pmap = p;
- }
- while (p->shift > 0) {
- i = (nr >> p->shift) & CARDMAP_MASK;
- if (p->ptr[i] == NULL) {
- struct cardmap *np = kzalloc(sizeof(*np), GFP_KERNEL);
- if (!np)
- goto enomem;
- np->shift = p->shift - CARDMAP_ORDER;
- np->parent = p;
- p->ptr[i] = np;
- }
- if (ptr == NULL)
- clear_bit(i, &p->inuse);
- p = p->ptr[i];
- }
- i = nr & CARDMAP_MASK;
- p->ptr[i] = ptr;
- if (ptr != NULL)
- set_bit(i, &p->inuse);
- else
- clear_bit(i, &p->inuse);
- return 0;
- enomem:
- return -ENOMEM;
+ return unit;
}
-static unsigned int cardmap_find_first_free(struct cardmap *map)
+/* put unit number back to a pool */
+static void unit_put(struct idr *p, int n)
{
- struct cardmap *p;
- unsigned int nr = 0;
- int i;
-
- if ((p = map) == NULL)
- return 0;
- for (;;) {
- i = find_first_zero_bit(&p->inuse, CARDMAP_WIDTH);
- if (i >= CARDMAP_WIDTH) {
- if (p->parent == NULL)
- return CARDMAP_WIDTH << p->shift;
- p = p->parent;
- i = (nr >> p->shift) & CARDMAP_MASK;
- set_bit(i, &p->inuse);
- continue;
- }
- nr = (nr & (~CARDMAP_MASK << p->shift)) | (i << p->shift);
- if (p->shift == 0 || p->ptr[i] == NULL)
- return nr;
- p = p->ptr[i];
- }
+ idr_remove(p, n);
}
-static void cardmap_destroy(struct cardmap **pmap)
+/* get pointer associated with the number */
+static void *unit_find(struct idr *p, int n)
{
- struct cardmap *p, *np;
- int i;
-
- for (p = *pmap; p != NULL; p = np) {
- if (p->shift != 0) {
- for (i = 0; i < CARDMAP_WIDTH; ++i)
- if (p->ptr[i] != NULL)
- break;
- if (i < CARDMAP_WIDTH) {
- np = p->ptr[i];
- p->ptr[i] = NULL;
- continue;
- }
- }
- np = p->parent;
- kfree(p);
- }
- *pmap = NULL;
+ return idr_find(p, n);
}
/* Module/initialization stuff */
diff --git a/drivers/net/ppp_synctty.c b/drivers/net/ppp_synctty.c
index 801d8f99d471..1e892b7b1f8c 100644
--- a/drivers/net/ppp_synctty.c
+++ b/drivers/net/ppp_synctty.c
@@ -333,9 +333,6 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file,
err = -EFAULT;
switch (cmd) {
case PPPIOCGCHAN:
- err = -ENXIO;
- if (!ap)
- break;
err = -EFAULT;
if (put_user(ppp_channel_index(&ap->chan), p))
break;
@@ -343,9 +340,6 @@ ppp_synctty_ioctl(struct tty_struct *tty, struct file *file,
break;
case PPPIOCGUNIT:
- err = -ENXIO;
- if (!ap)
- break;
err = -EFAULT;
if (put_user(ppp_unit_number(&ap->chan), p))
break;
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index b646e92134dc..c22b30533a14 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -958,7 +958,6 @@ static int pppoe_seq_show(struct seq_file *seq, void *v)
{
struct pppox_sock *po;
char *dev_name;
- DECLARE_MAC_BUF(mac);
if (v == SEQ_START_TOKEN) {
seq_puts(seq, "Id Address Device\n");
@@ -968,8 +967,8 @@ static int pppoe_seq_show(struct seq_file *seq, void *v)
po = v;
dev_name = po->pppoe_pa.dev;
- seq_printf(seq, "%08X %s %8s\n",
- po->pppoe_pa.sid, print_mac(mac, po->pppoe_pa.remote), dev_name);
+ seq_printf(seq, "%08X %pM %8s\n",
+ po->pppoe_pa.sid, po->pppoe_pa.remote, dev_name);
out:
return 0;
}
diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c
index e98d9773158d..f1a946785c6a 100644
--- a/drivers/net/pppol2tp.c
+++ b/drivers/net/pppol2tp.c
@@ -489,6 +489,30 @@ out:
spin_unlock_bh(&session->reorder_q.lock);
}
+static inline int pppol2tp_verify_udp_checksum(struct sock *sk,
+ struct sk_buff *skb)
+{
+ struct udphdr *uh = udp_hdr(skb);
+ u16 ulen = ntohs(uh->len);
+ struct inet_sock *inet;
+ __wsum psum;
+
+ if (sk->sk_no_check || skb_csum_unnecessary(skb) || !uh->check)
+ return 0;
+
+ inet = inet_sk(sk);
+ psum = csum_tcpudp_nofold(inet->saddr, inet->daddr, ulen,
+ IPPROTO_UDP, 0);
+
+ if ((skb->ip_summed == CHECKSUM_COMPLETE) &&
+ !csum_fold(csum_add(psum, skb->csum)))
+ return 0;
+
+ skb->csum = psum;
+
+ return __skb_checksum_complete(skb);
+}
+
/* Internal receive frame. Do the real work of receiving an L2TP data frame
* here. The skb is not on a list when we get here.
* Returns 0 if the packet was a data packet and was successfully passed on.
@@ -509,6 +533,9 @@ static int pppol2tp_recv_core(struct sock *sock, struct sk_buff *skb)
if (tunnel == NULL)
goto no_tunnel;
+ if (tunnel->sock && pppol2tp_verify_udp_checksum(tunnel->sock, skb))
+ goto discard_bad_csum;
+
/* UDP always verifies the packet length. */
__skb_pull(skb, sizeof(struct udphdr));
@@ -725,6 +752,14 @@ discard:
return 0;
+discard_bad_csum:
+ LIMIT_NETDEBUG("%s: UDP: bad checksum\n", tunnel->name);
+ UDP_INC_STATS_USER(&init_net, UDP_MIB_INERRORS, 0);
+ tunnel->stats.rx_errors++;
+ kfree_skb(skb);
+
+ return 0;
+
error:
/* Put UDP header back */
__skb_push(skb, sizeof(struct udphdr));
@@ -851,7 +886,7 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh
static const unsigned char ppph[2] = { 0xff, 0x03 };
struct sock *sk = sock->sk;
struct inet_sock *inet;
- __wsum csum = 0;
+ __wsum csum;
struct sk_buff *skb;
int error;
int hdr_len;
@@ -859,6 +894,8 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh
struct pppol2tp_tunnel *tunnel;
struct udphdr *uh;
unsigned int len;
+ struct sock *sk_tun;
+ u16 udp_len;
error = -ENOTCONN;
if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED))
@@ -870,7 +907,8 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh
if (session == NULL)
goto error;
- tunnel = pppol2tp_sock_to_tunnel(session->tunnel_sock);
+ sk_tun = session->tunnel_sock;
+ tunnel = pppol2tp_sock_to_tunnel(sk_tun);
if (tunnel == NULL)
goto error_put_sess;
@@ -893,11 +931,12 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh
skb_reset_transport_header(skb);
/* Build UDP header */
- inet = inet_sk(session->tunnel_sock);
+ inet = inet_sk(sk_tun);
+ udp_len = hdr_len + sizeof(ppph) + total_len;
uh = (struct udphdr *) skb->data;
uh->source = inet->sport;
uh->dest = inet->dport;
- uh->len = htons(hdr_len + sizeof(ppph) + total_len);
+ uh->len = htons(udp_len);
uh->check = 0;
skb_put(skb, sizeof(struct udphdr));
@@ -919,8 +958,22 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh
skb_put(skb, total_len);
/* Calculate UDP checksum if configured to do so */
- if (session->tunnel_sock->sk_no_check != UDP_CSUM_NOXMIT)
- csum = udp_csum_outgoing(sk, skb);
+ if (sk_tun->sk_no_check == UDP_CSUM_NOXMIT)
+ skb->ip_summed = CHECKSUM_NONE;
+ else if (!(skb->dst->dev->features & NETIF_F_V4_CSUM)) {
+ skb->ip_summed = CHECKSUM_COMPLETE;
+ csum = skb_checksum(skb, 0, udp_len, 0);
+ uh->check = csum_tcpudp_magic(inet->saddr, inet->daddr,
+ udp_len, IPPROTO_UDP, csum);
+ if (uh->check == 0)
+ uh->check = CSUM_MANGLED_0;
+ } else {
+ skb->ip_summed = CHECKSUM_PARTIAL;
+ skb->csum_start = skb_transport_header(skb) - skb->head;
+ skb->csum_offset = offsetof(struct udphdr, check);
+ uh->check = ~csum_tcpudp_magic(inet->saddr, inet->daddr,
+ udp_len, IPPROTO_UDP, 0);
+ }
/* Debug */
if (session->send_seq)
@@ -1008,13 +1061,14 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
struct sock *sk = (struct sock *) chan->private;
struct sock *sk_tun;
int hdr_len;
+ u16 udp_len;
struct pppol2tp_session *session;
struct pppol2tp_tunnel *tunnel;
int rc;
int headroom;
int data_len = skb->len;
struct inet_sock *inet;
- __wsum csum = 0;
+ __wsum csum;
struct udphdr *uh;
unsigned int len;
int old_headroom;
@@ -1060,6 +1114,8 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
/* Setup L2TP header */
pppol2tp_build_l2tp_header(session, __skb_push(skb, hdr_len));
+ udp_len = sizeof(struct udphdr) + hdr_len + sizeof(ppph) + data_len;
+
/* Setup UDP header */
inet = inet_sk(sk_tun);
__skb_push(skb, sizeof(*uh));
@@ -1067,13 +1123,9 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
uh = udp_hdr(skb);
uh->source = inet->sport;
uh->dest = inet->dport;
- uh->len = htons(sizeof(struct udphdr) + hdr_len + sizeof(ppph) + data_len);
+ uh->len = htons(udp_len);
uh->check = 0;
- /* *BROKEN* Calculate UDP checksum if configured to do so */
- if (sk_tun->sk_no_check != UDP_CSUM_NOXMIT)
- csum = udp_csum_outgoing(sk_tun, skb);
-
/* Debug */
if (session->send_seq)
PRINTK(session->debug, PPPOL2TP_MSG_DATA, KERN_DEBUG,
@@ -1108,6 +1160,24 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb)
skb->dst = dst_clone(__sk_dst_get(sk_tun));
pppol2tp_skb_set_owner_w(skb, sk_tun);
+ /* Calculate UDP checksum if configured to do so */
+ if (sk_tun->sk_no_check == UDP_CSUM_NOXMIT)
+ skb->ip_summed = CHECKSUM_NONE;
+ else if (!(skb->dst->dev->features & NETIF_F_V4_CSUM)) {
+ skb->ip_summed = CHECKSUM_COMPLETE;
+ csum = skb_checksum(skb, 0, udp_len, 0);
+ uh->check = csum_tcpudp_magic(inet->saddr, inet->daddr,
+ udp_len, IPPROTO_UDP, csum);
+ if (uh->check == 0)
+ uh->check = CSUM_MANGLED_0;
+ } else {
+ skb->ip_summed = CHECKSUM_PARTIAL;
+ skb->csum_start = skb_transport_header(skb) - skb->head;
+ skb->csum_offset = offsetof(struct udphdr, check);
+ uh->check = ~csum_tcpudp_magic(inet->saddr, inet->daddr,
+ udp_len, IPPROTO_UDP, 0);
+ }
+
/* Queue the packet to IP for output */
len = skb->len;
rc = ip_queue_xmit(skb, 1);
diff --git a/drivers/net/ps3_gelic_net.c b/drivers/net/ps3_gelic_net.c
index 2eb54fd7bed5..4b564eda5bd9 100644
--- a/drivers/net/ps3_gelic_net.c
+++ b/drivers/net/ps3_gelic_net.c
@@ -1443,7 +1443,6 @@ int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card)
{
int status;
u64 v1, v2;
- DECLARE_MAC_BUF(mac);
netdev->features = NETIF_F_IP_CSUM;
@@ -1474,9 +1473,8 @@ int gelic_net_setup_netdev(struct net_device *netdev, struct gelic_card *card)
__func__, netdev->name, status);
return status;
}
- dev_info(ctodev(card), "%s: MAC addr %s\n",
- netdev->name,
- print_mac(mac, netdev->dev_addr));
+ dev_info(ctodev(card), "%s: MAC addr %pM\n",
+ netdev->name, netdev->dev_addr);
return 0;
}
diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c
index a834b52a6a2c..ec2314246682 100644
--- a/drivers/net/ps3_gelic_wireless.c
+++ b/drivers/net/ps3_gelic_wireless.c
@@ -30,10 +30,11 @@
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/wireless.h>
+#include <linux/ieee80211.h>
+#include <linux/if_arp.h>
#include <linux/ctype.h>
#include <linux/string.h>
#include <net/iw_handler.h>
-#include <net/ieee80211.h>
#include <linux/dma-mapping.h>
#include <net/checksum.h>
@@ -449,9 +450,9 @@ static size_t gelic_wl_synthesize_ie(u8 *buf,
/* element id */
if (rsn)
- *buf++ = MFIE_TYPE_RSN;
+ *buf++ = WLAN_EID_RSN;
else
- *buf++ = MFIE_TYPE_GENERIC;
+ *buf++ = WLAN_EID_GENERIC;
/* length filed; set later */
buf++;
@@ -539,7 +540,7 @@ static void gelic_wl_parse_ie(u8 *data, size_t len,
break;
switch (item_id) {
- case MFIE_TYPE_GENERIC:
+ case WLAN_EID_GENERIC:
if ((OUI_LEN + 1 <= item_len) &&
!memcmp(pos, wpa_oui, OUI_LEN) &&
pos[OUI_LEN] == 0x01) {
@@ -547,7 +548,7 @@ static void gelic_wl_parse_ie(u8 *data, size_t len,
ie_info->wpa.len = item_len + 2;
}
break;
- case MFIE_TYPE_RSN:
+ case WLAN_EID_RSN:
ie_info->rsn.data = pos - 2;
/* length includes the header */
ie_info->rsn.len = item_len + 2;
@@ -581,7 +582,7 @@ static char *gelic_wl_translate_scan(struct net_device *netdev,
char *tmp;
u8 rate;
unsigned int i, j, len;
- u8 buf[MAX_WPA_IE_LEN];
+ u8 buf[64]; /* arbitrary size large enough */
pr_debug("%s: <-\n", __func__);
@@ -763,7 +764,6 @@ static void scan_list_dump(struct gelic_wl_info *wl)
{
struct gelic_wl_scan_info *scan_info;
int i;
- DECLARE_MAC_BUF(mac);
i = 0;
list_for_each_entry(scan_info, &wl->network_list, list) {
@@ -775,8 +775,7 @@ static void scan_list_dump(struct gelic_wl_info *wl)
scan_info->rate_len, scan_info->rate_ext_len,
scan_info->essid_len);
/* -- */
- pr_debug("bssid=%s\n",
- print_mac(mac, &scan_info->hwinfo->bssid[2]));
+ pr_debug("bssid=%pM\n", &scan_info->hwinfo->bssid[2]);
pr_debug("essid=%s\n", scan_info->hwinfo->essid);
}
}
@@ -1167,11 +1166,7 @@ static int gelic_wl_set_ap(struct net_device *netdev,
ETH_ALEN);
set_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat);
set_bit(GELIC_WL_STAT_CONFIGURED, &wl->stat);
- pr_debug("%s: bss=%02x:%02x:%02x:%02x:%02x:%02x\n",
- __func__,
- wl->bssid[0], wl->bssid[1],
- wl->bssid[2], wl->bssid[3],
- wl->bssid[4], wl->bssid[5]);
+ pr_debug("%s: bss=%pM\n", __func__, wl->bssid);
} else {
pr_debug("%s: clear bssid\n", __func__);
clear_bit(GELIC_WL_STAT_BSSID_SET, &wl->stat);
@@ -1632,7 +1627,6 @@ static void gelic_wl_scan_complete_event(struct gelic_wl_info *wl)
unsigned long this_time = jiffies;
unsigned int data_len, i, found, r;
void *buf;
- DECLARE_MAC_BUF(mac);
pr_debug("%s:start\n", __func__);
mutex_lock(&wl->scan_lock);
@@ -1684,9 +1678,9 @@ static void gelic_wl_scan_complete_event(struct gelic_wl_info *wl)
scan_info_size < data_len;
i++, scan_info_size += be16_to_cpu(scan_info->size),
scan_info = (void *)scan_info + be16_to_cpu(scan_info->size)) {
- pr_debug("%s:size=%d bssid=%s scan_info=%p\n", __func__,
+ pr_debug("%s:size=%d bssid=%pM scan_info=%p\n", __func__,
be16_to_cpu(scan_info->size),
- print_mac(mac, &scan_info->bssid[2]), scan_info);
+ &scan_info->bssid[2], scan_info);
/*
* The wireless firmware may return invalid channel 0 and/or
@@ -1741,14 +1735,14 @@ static void gelic_wl_scan_complete_event(struct gelic_wl_info *wl)
target->essid_len = strnlen(scan_info->essid,
sizeof(scan_info->essid));
target->rate_len = 0;
- for (r = 0; r < MAX_RATES_LENGTH; r++)
+ for (r = 0; r < 12; r++)
if (scan_info->rate[r])
target->rate_len++;
if (8 < target->rate_len)
pr_info("%s: AP returns %d rates\n", __func__,
target->rate_len);
target->rate_ext_len = 0;
- for (r = 0; r < MAX_RATES_EX_LENGTH; r++)
+ for (r = 0; r < 16; r++)
if (scan_info->ext_rate[r])
target->rate_ext_len++;
list_move_tail(&target->list, &wl->network_list);
@@ -1787,7 +1781,6 @@ struct gelic_wl_scan_info *gelic_wl_find_best_bss(struct gelic_wl_info *wl)
struct gelic_wl_scan_info *best_bss;
int weight, best_weight;
u16 security;
- DECLARE_MAC_BUF(mac);
pr_debug("%s: <-\n", __func__);
@@ -1857,8 +1850,8 @@ struct gelic_wl_scan_info *gelic_wl_find_best_bss(struct gelic_wl_info *wl)
#ifdef DEBUG
pr_debug("%s: -> bss=%p\n", __func__, best_bss);
if (best_bss) {
- pr_debug("%s:addr=%s\n", __func__,
- print_mac(mac, &best_bss->hwinfo->bssid[2]));
+ pr_debug("%s:addr=%pM\n", __func__,
+ &best_bss->hwinfo->bssid[2]);
}
#endif
return best_bss;
diff --git a/drivers/net/ps3_gelic_wireless.h b/drivers/net/ps3_gelic_wireless.h
index 5339e0078d18..5b631c6c9775 100644
--- a/drivers/net/ps3_gelic_wireless.h
+++ b/drivers/net/ps3_gelic_wireless.h
@@ -164,8 +164,8 @@ struct gelic_eurus_scan_info {
__be16 security;
u8 bssid[8]; /* last ETH_ALEN are valid. bssid[0],[1] are unused */
u8 essid[32]; /* IW_ESSID_MAX_SIZE */
- u8 rate[16]; /* first MAX_RATES_LENGTH(12) are valid */
- u8 ext_rate[16]; /* first MAX_RATES_EX_LENGTH(16) are valid */
+ u8 rate[16]; /* first 12 are valid */
+ u8 ext_rate[16]; /* first 16 are valid */
__be32 reserved1;
__be32 reserved2;
__be32 reserved3;
diff --git a/drivers/net/qla3xxx.c b/drivers/net/qla3xxx.c
index 508452c02151..189ec29ac7a4 100644
--- a/drivers/net/qla3xxx.c
+++ b/drivers/net/qla3xxx.c
@@ -2127,7 +2127,6 @@ static void ql_process_mac_rx_intr(struct ql3_adapter *qdev,
skb->protocol = eth_type_trans(skb, qdev->ndev);
netif_receive_skb(skb);
- qdev->ndev->last_rx = jiffies;
lrg_buf_cb2->skb = NULL;
if (qdev->device_id == QL3022_DEVICE_ID)
@@ -2201,7 +2200,6 @@ static void ql_process_macip_rx_intr(struct ql3_adapter *qdev,
netif_receive_skb(skb2);
ndev->stats.rx_packets++;
ndev->stats.rx_bytes += length;
- ndev->last_rx = jiffies;
lrg_buf_cb2->skb = NULL;
if (qdev->device_id == QL3022_DEVICE_ID)
@@ -2286,7 +2284,6 @@ static int ql_tx_rx_clean(struct ql3_adapter *qdev,
static int ql_poll(struct napi_struct *napi, int budget)
{
struct ql3_adapter *qdev = container_of(napi, struct ql3_adapter, napi);
- struct net_device *ndev = qdev->ndev;
int rx_cleaned = 0, tx_cleaned = 0;
unsigned long hw_flags;
struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
@@ -2295,7 +2292,7 @@ static int ql_poll(struct napi_struct *napi, int budget)
if (tx_cleaned + rx_cleaned != budget) {
spin_lock_irqsave(&qdev->hw_lock, hw_flags);
- __netif_rx_complete(ndev, napi);
+ __netif_rx_complete(napi);
ql_update_small_bufq_prod_index(qdev);
ql_update_lrg_bufq_prod_index(qdev);
writel(qdev->rsp_consumer_index,
@@ -2354,8 +2351,8 @@ static irqreturn_t ql3xxx_isr(int irq, void *dev_id)
spin_unlock(&qdev->adapter_lock);
} else if (value & ISP_IMR_DISABLE_CMPL_INT) {
ql_disable_interrupts(qdev);
- if (likely(netif_rx_schedule_prep(ndev, &qdev->napi))) {
- __netif_rx_schedule(ndev, &qdev->napi);
+ if (likely(netif_rx_schedule_prep(&qdev->napi))) {
+ __netif_rx_schedule(&qdev->napi);
}
} else {
return IRQ_NONE;
@@ -3520,7 +3517,6 @@ static void ql_display_dev_info(struct net_device *ndev)
{
struct ql3_adapter *qdev = (struct ql3_adapter *)netdev_priv(ndev);
struct pci_dev *pdev = qdev->pdev;
- DECLARE_MAC_BUF(mac);
printk(KERN_INFO PFX
"\n%s Adapter %d RevisionID %d found %s on PCI slot %d.\n",
@@ -3546,8 +3542,8 @@ static void ql_display_dev_info(struct net_device *ndev)
if (netif_msg_probe(qdev))
printk(KERN_INFO PFX
- "%s: MAC address %s\n",
- ndev->name, print_mac(mac, ndev->dev_addr));
+ "%s: MAC address %pM\n",
+ ndev->name, ndev->dev_addr);
}
static int ql_adapter_down(struct ql3_adapter *qdev, int do_reset)
@@ -3903,13 +3899,24 @@ static void ql3xxx_timer(unsigned long ptr)
queue_delayed_work(qdev->workqueue, &qdev->link_state_work, 0);
}
+static const struct net_device_ops ql3xxx_netdev_ops = {
+ .ndo_open = ql3xxx_open,
+ .ndo_start_xmit = ql3xxx_send,
+ .ndo_stop = ql3xxx_close,
+ .ndo_set_multicast_list = NULL, /* not allowed on NIC side */
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = ql3xxx_set_mac_address,
+ .ndo_tx_timeout = ql3xxx_tx_timeout,
+};
+
static int __devinit ql3xxx_probe(struct pci_dev *pdev,
const struct pci_device_id *pci_entry)
{
struct net_device *ndev = NULL;
struct ql3_adapter *qdev = NULL;
static int cards_found = 0;
- int pci_using_dac, err;
+ int uninitialized_var(pci_using_dac), err;
err = pci_enable_device(pdev);
if (err) {
@@ -3969,9 +3976,7 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
if (qdev->device_id == QL3032_DEVICE_ID)
ndev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
- qdev->mem_map_registers =
- ioremap_nocache(pci_resource_start(pdev, 1),
- pci_resource_len(qdev->pdev, 1));
+ qdev->mem_map_registers = pci_ioremap_bar(pdev, 1);
if (!qdev->mem_map_registers) {
printk(KERN_ERR PFX "%s: cannot map device registers\n",
pci_name(pdev));
@@ -3983,17 +3988,8 @@ static int __devinit ql3xxx_probe(struct pci_dev *pdev,
spin_lock_init(&qdev->hw_lock);
/* Set driver entry points */
- ndev->open = ql3xxx_open;
- ndev->hard_start_xmit = ql3xxx_send;
- ndev->stop = ql3xxx_close;
- /* ndev->set_multicast_list
- * This device is one side of a two-function adapter
- * (NIC and iSCSI). Promiscuous mode setting/clearing is
- * not allowed from the NIC side.
- */
+ ndev->netdev_ops = &ql3xxx_netdev_ops;
SET_ETHTOOL_OPS(ndev, &ql3xxx_ethtool_ops);
- ndev->set_mac_address = ql3xxx_set_mac_address;
- ndev->tx_timeout = ql3xxx_tx_timeout;
ndev->watchdog_timeo = 5 * HZ;
netif_napi_add(ndev, &qdev->napi, ql_poll, 64);
diff --git a/drivers/net/qlge/qlge_ethtool.c b/drivers/net/qlge/qlge_ethtool.c
index b62fbd4bf00f..eefb81b13758 100644
--- a/drivers/net/qlge/qlge_ethtool.c
+++ b/drivers/net/qlge/qlge_ethtool.c
@@ -97,7 +97,7 @@ exit:
return status;
}
-void ql_update_stats(struct ql_adapter *qdev)
+static void ql_update_stats(struct ql_adapter *qdev)
{
u32 i;
u64 data;
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index b83a9c9b6a97..718a7bd0cd1a 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -336,12 +336,11 @@ static int ql_set_mac_addr_reg(struct ql_adapter *qdev, u8 *addr, u32 type,
(addr[5]);
QPRINTK(qdev, IFUP, INFO,
- "Adding %s address %02x:%02x:%02x:%02x:%02x:%02x"
+ "Adding %s address %pM"
" at index %d in the CAM.\n",
((type ==
MAC_ADDR_TYPE_MULTI_MAC) ? "MULTICAST" :
- "UNICAST"), addr[0], addr[1], addr[2], addr[3],
- addr[4], addr[5], index);
+ "UNICAST"), addr, index);
status =
ql_wait_reg_rdy(qdev,
@@ -643,7 +642,7 @@ static void ql_enable_all_completion_interrupts(struct ql_adapter *qdev)
}
-int ql_read_flash_word(struct ql_adapter *qdev, int offset, u32 *data)
+static int ql_read_flash_word(struct ql_adapter *qdev, int offset, u32 *data)
{
int status = 0;
/* wait for reg to come ready */
@@ -833,7 +832,7 @@ end:
}
/* Get the next large buffer. */
-struct bq_desc *ql_get_curr_lbuf(struct rx_ring *rx_ring)
+static struct bq_desc *ql_get_curr_lbuf(struct rx_ring *rx_ring)
{
struct bq_desc *lbq_desc = &rx_ring->lbq[rx_ring->lbq_curr_idx];
rx_ring->lbq_curr_idx++;
@@ -844,7 +843,7 @@ struct bq_desc *ql_get_curr_lbuf(struct rx_ring *rx_ring)
}
/* Get the next small buffer. */
-struct bq_desc *ql_get_curr_sbuf(struct rx_ring *rx_ring)
+static struct bq_desc *ql_get_curr_sbuf(struct rx_ring *rx_ring)
{
struct bq_desc *sbq_desc = &rx_ring->sbq[rx_ring->sbq_curr_idx];
rx_ring->sbq_curr_idx++;
@@ -1167,7 +1166,7 @@ map_error:
return NETDEV_TX_BUSY;
}
-void ql_realign_skb(struct sk_buff *skb, int len)
+static void ql_realign_skb(struct sk_buff *skb, int len)
{
void *temp_addr = skb->data;
@@ -1452,7 +1451,6 @@ static void ql_process_mac_rx_intr(struct ql_adapter *qdev,
"Passing a normal packet upstream.\n");
netif_rx(skb);
}
- ndev->last_rx = jiffies;
}
/* Process an outbound completion from an rx ring. */
@@ -1649,7 +1647,7 @@ static int ql_napi_poll_msix(struct napi_struct *napi, int budget)
rx_ring->cq_id);
if (work_done < budget) {
- __netif_rx_complete(qdev->ndev, napi);
+ __netif_rx_complete(napi);
ql_enable_completion_interrupt(qdev, rx_ring->irq);
}
return work_done;
@@ -1734,8 +1732,7 @@ static irqreturn_t qlge_msix_tx_isr(int irq, void *dev_id)
static irqreturn_t qlge_msix_rx_isr(int irq, void *dev_id)
{
struct rx_ring *rx_ring = dev_id;
- struct ql_adapter *qdev = rx_ring->qdev;
- netif_rx_schedule(qdev->ndev, &rx_ring->napi);
+ netif_rx_schedule(&rx_ring->napi);
return IRQ_HANDLED;
}
@@ -1821,8 +1818,7 @@ static irqreturn_t qlge_isr(int irq, void *dev_id)
&rx_ring->rx_work,
0);
else
- netif_rx_schedule(qdev->ndev,
- &rx_ring->napi);
+ netif_rx_schedule(&rx_ring->napi);
work_done++;
}
}
@@ -2071,7 +2067,7 @@ err:
return -ENOMEM;
}
-void ql_free_lbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring)
+static void ql_free_lbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring)
{
int i;
struct bq_desc *lbq_desc;
@@ -2134,7 +2130,7 @@ mem_error:
return -ENOMEM;
}
-void ql_free_sbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring)
+static void ql_free_sbq_buffers(struct ql_adapter *qdev, struct rx_ring *rx_ring)
{
int i;
struct bq_desc *sbq_desc;
@@ -2469,7 +2465,7 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
rx_ring->sbq_base_indirect_dma = shadow_reg_dma;
/* PCI doorbell mem area + 0x00 for consumer index register */
- rx_ring->cnsmr_idx_db_reg = (u32 *) doorbell_area;
+ rx_ring->cnsmr_idx_db_reg = (u32 __iomem *) doorbell_area;
rx_ring->cnsmr_idx = 0;
rx_ring->curr_entry = rx_ring->cq_base;
@@ -2477,10 +2473,10 @@ static int ql_start_rx_ring(struct ql_adapter *qdev, struct rx_ring *rx_ring)
rx_ring->valid_db_reg = doorbell_area + 0x04;
/* PCI doorbell mem area + 0x18 for large buffer consumer */
- rx_ring->lbq_prod_idx_db_reg = (u32 *) (doorbell_area + 0x18);
+ rx_ring->lbq_prod_idx_db_reg = (u32 __iomem *) (doorbell_area + 0x18);
/* PCI doorbell mem area + 0x1c */
- rx_ring->sbq_prod_idx_db_reg = (u32 *) (doorbell_area + 0x1c);
+ rx_ring->sbq_prod_idx_db_reg = (u32 __iomem *) (doorbell_area + 0x1c);
memset((void *)cqicb, 0, sizeof(struct cqicb));
cqicb->msix_vect = rx_ring->irq;
@@ -2611,7 +2607,7 @@ static int ql_start_tx_ring(struct ql_adapter *qdev, struct tx_ring *tx_ring)
* Assign doorbell registers for this tx_ring.
*/
/* TX PCI doorbell mem area for tx producer index */
- tx_ring->prod_idx_db_reg = (u32 *) doorbell_area;
+ tx_ring->prod_idx_db_reg = (u32 __iomem *) doorbell_area;
tx_ring->prod_idx = 0;
/* TX PCI doorbell mem area + 0x04 */
tx_ring->valid_db_reg = doorbell_area + 0x04;
@@ -3127,11 +3123,7 @@ static void ql_display_dev_info(struct net_device *ndev)
qdev->chip_rev_id >> 4 & 0x0000000f,
qdev->chip_rev_id >> 8 & 0x0000000f,
qdev->chip_rev_id >> 12 & 0x0000000f);
- QPRINTK(qdev, PROBE, INFO,
- "MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
- ndev->dev_addr[0], ndev->dev_addr[1],
- ndev->dev_addr[2], ndev->dev_addr[3], ndev->dev_addr[4],
- ndev->dev_addr[5]);
+ QPRINTK(qdev, PROBE, INFO, "MAC address %pM\n", ndev->dev_addr);
}
static int ql_adapter_down(struct ql_adapter *qdev)
@@ -3156,7 +3148,7 @@ static int ql_adapter_down(struct ql_adapter *qdev)
* a workqueue only if it's a single interrupt
* environment (MSI/Legacy).
*/
- for (i = 1; i > qdev->rx_ring_count; i++) {
+ for (i = 1; i < qdev->rx_ring_count; i++) {
rx_ring = &qdev->rx_ring[i];
/* Only the RSS rings use NAPI on multi irq
* environment. Outbound completion processing
@@ -3526,6 +3518,7 @@ static int qlge_set_mac_address(struct net_device *ndev, void *p)
{
struct ql_adapter *qdev = (struct ql_adapter *)netdev_priv(ndev);
struct sockaddr *addr = p;
+ int ret = 0;
if (netif_running(ndev))
return -EBUSY;
@@ -3538,11 +3531,11 @@ static int qlge_set_mac_address(struct net_device *ndev, void *p)
if (ql_set_mac_addr_reg(qdev, (u8 *) ndev->dev_addr,
MAC_ADDR_TYPE_CAM_MAC, qdev->func)) {/* Unicast */
QPRINTK(qdev, HW, ERR, "Failed to load MAC address.\n");
- return -1;
+ ret = -1;
}
spin_unlock(&qdev->hw_lock);
- return 0;
+ return ret;
}
static void qlge_tx_timeout(struct net_device *ndev)
@@ -3592,7 +3585,7 @@ static void ql_release_all(struct pci_dev *pdev)
qdev->q_workqueue = NULL;
}
if (qdev->reg_base)
- iounmap((void *)qdev->reg_base);
+ iounmap(qdev->reg_base);
if (qdev->doorbell_area)
iounmap(qdev->doorbell_area);
pci_release_regions(pdev);
@@ -3721,6 +3714,22 @@ err_out:
return err;
}
+
+static const struct net_device_ops qlge_netdev_ops = {
+ .ndo_open = qlge_open,
+ .ndo_stop = qlge_close,
+ .ndo_start_xmit = qlge_send,
+ .ndo_change_mtu = qlge_change_mtu,
+ .ndo_get_stats = qlge_get_stats,
+ .ndo_set_multicast_list = qlge_set_multicast_list,
+ .ndo_set_mac_address = qlge_set_mac_address,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_tx_timeout = qlge_tx_timeout,
+ .ndo_vlan_rx_register = ql_vlan_rx_register,
+ .ndo_vlan_rx_add_vid = ql_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = ql_vlan_rx_kill_vid,
+};
+
static int __devinit qlge_probe(struct pci_dev *pdev,
const struct pci_device_id *pci_entry)
{
@@ -3758,19 +3767,11 @@ static int __devinit qlge_probe(struct pci_dev *pdev,
*/
ndev->tx_queue_len = qdev->tx_ring_size;
ndev->irq = pdev->irq;
- ndev->open = qlge_open;
- ndev->stop = qlge_close;
- ndev->hard_start_xmit = qlge_send;
+
+ ndev->netdev_ops = &qlge_netdev_ops;
SET_ETHTOOL_OPS(ndev, &qlge_ethtool_ops);
- ndev->change_mtu = qlge_change_mtu;
- ndev->get_stats = qlge_get_stats;
- ndev->set_multicast_list = qlge_set_multicast_list;
- ndev->set_mac_address = qlge_set_mac_address;
- ndev->tx_timeout = qlge_tx_timeout;
ndev->watchdog_timeo = 10 * HZ;
- ndev->vlan_rx_register = ql_vlan_rx_register;
- ndev->vlan_rx_add_vid = ql_vlan_rx_add_vid;
- ndev->vlan_rx_kill_vid = ql_vlan_rx_kill_vid;
+
err = register_netdev(ndev);
if (err) {
dev_err(&pdev->dev, "net device registration failed.\n");
diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c
index 24fe344bcf1f..fa31891b6e62 100644
--- a/drivers/net/qlge/qlge_mpi.c
+++ b/drivers/net/qlge/qlge_mpi.c
@@ -19,7 +19,7 @@ exit:
return status;
}
-int ql_get_mb_sts(struct ql_adapter *qdev, struct mbox_params *mbcp)
+static int ql_get_mb_sts(struct ql_adapter *qdev, struct mbox_params *mbcp)
{
int i, status;
diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c
index 34fe7ef8e5ed..53bbddfc8c95 100644
--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -49,8 +49,8 @@
#include <asm/processor.h>
#define DRV_NAME "r6040"
-#define DRV_VERSION "0.18"
-#define DRV_RELDATE "13Jul2008"
+#define DRV_VERSION "0.19"
+#define DRV_RELDATE "18Dec2008"
/* PHY CHIP Address */
#define PHY1_ADDR 1 /* For MAC1 */
@@ -214,7 +214,7 @@ static int r6040_phy_read(void __iomem *ioaddr, int phy_addr, int reg)
/* Wait for the read bit to be cleared */
while (limit--) {
cmd = ioread16(ioaddr + MMDIO);
- if (cmd & MDIO_READ)
+ if (!(cmd & MDIO_READ))
break;
}
@@ -233,7 +233,7 @@ static void r6040_phy_write(void __iomem *ioaddr, int phy_addr, int reg, u16 val
/* Wait for the write bit to be cleared */
while (limit--) {
cmd = ioread16(ioaddr + MMDIO);
- if (cmd & MDIO_WRITE)
+ if (!(cmd & MDIO_WRITE))
break;
}
}
@@ -598,7 +598,6 @@ static int r6040_rx(struct net_device *dev, int limit)
/* Send to upper layer */
netif_receive_skb(skb_ptr);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += descptr->len - 4;
@@ -668,7 +667,7 @@ static int r6040_poll(struct napi_struct *napi, int budget)
work_done = r6040_rx(dev, budget);
if (work_done < budget) {
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
/* Enable RX interrupt */
iowrite16(ioread16(ioaddr + MIER) | RX_INTS, ioaddr + MIER);
}
@@ -681,8 +680,10 @@ static irqreturn_t r6040_interrupt(int irq, void *dev_id)
struct net_device *dev = dev_id;
struct r6040_private *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
- u16 status;
+ u16 misr, status;
+ /* Save MIER */
+ misr = ioread16(ioaddr + MIER);
/* Mask off RDC MAC interrupt */
iowrite16(MSK_INT, ioaddr + MIER);
/* Read MISR status and clear */
@@ -702,14 +703,17 @@ static irqreturn_t r6040_interrupt(int irq, void *dev_id)
dev->stats.rx_fifo_errors++;
/* Mask off RX interrupt */
- iowrite16(ioread16(ioaddr + MIER) & ~RX_INTS, ioaddr + MIER);
- netif_rx_schedule(dev, &lp->napi);
+ misr &= ~RX_INTS;
+ netif_rx_schedule(&lp->napi);
}
/* TX interrupt request */
if (status & TX_INTS)
r6040_tx(dev);
+ /* Restore RDC MAC interrupt */
+ iowrite16(misr, ioaddr + MIER);
+
return IRQ_HANDLED;
}
@@ -1030,13 +1034,28 @@ static u32 netdev_get_link(struct net_device *dev)
return mii_link_ok(&rp->mii_if);
}
-static struct ethtool_ops netdev_ethtool_ops = {
+static const struct ethtool_ops netdev_ethtool_ops = {
.get_drvinfo = netdev_get_drvinfo,
.get_settings = netdev_get_settings,
.set_settings = netdev_set_settings,
.get_link = netdev_get_link,
};
+static const struct net_device_ops r6040_netdev_ops = {
+ .ndo_open = r6040_open,
+ .ndo_stop = r6040_close,
+ .ndo_start_xmit = r6040_start_xmit,
+ .ndo_get_stats = r6040_get_stats,
+ .ndo_set_multicast_list = r6040_multicast_list,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_do_ioctl = r6040_ioctl,
+ .ndo_tx_timeout = r6040_tx_timeout,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = r6040_poll_controller,
+#endif
+};
+
static int __devinit r6040_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -1128,18 +1147,10 @@ static int __devinit r6040_init_one(struct pci_dev *pdev,
lp->switch_sig = 0;
/* The RDC-specific entries in the device structure. */
- dev->open = &r6040_open;
- dev->hard_start_xmit = &r6040_start_xmit;
- dev->stop = &r6040_close;
- dev->get_stats = r6040_get_stats;
- dev->set_multicast_list = &r6040_multicast_list;
- dev->do_ioctl = &r6040_ioctl;
+ dev->netdev_ops = &r6040_netdev_ops;
dev->ethtool_ops = &netdev_ethtool_ops;
- dev->tx_timeout = &r6040_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = r6040_poll_controller;
-#endif
+
netif_napi_add(dev, &lp->napi, r6040_poll, 64);
lp->mii_if.dev = dev;
lp->mii_if.mdio_read = r6040_mdio_read;
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 4b7cb389dc49..2c73ca606b35 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -474,6 +474,7 @@ struct rtl8169_private {
void (*hw_start)(struct net_device *);
unsigned int (*phy_reset_pending)(void __iomem *);
unsigned int (*link_ok)(void __iomem *);
+ int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd);
int pcie_cap;
struct delayed_work task;
unsigned features;
@@ -1829,9 +1830,11 @@ static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
struct rtl8169_private *tp = netdev_priv(dev);
struct mii_ioctl_data *data = if_mii(ifr);
- if (!netif_running(dev))
- return -ENODEV;
+ return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV;
+}
+static int rtl_xmii_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd)
+{
switch (cmd) {
case SIOCGMIIPHY:
data->phy_id = 32; /* Internal PHY */
@@ -1850,6 +1853,11 @@ static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
return -EOPNOTSUPP;
}
+static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd)
+{
+ return -EOPNOTSUPP;
+}
+
static const struct rtl_cfg_info {
void (*hw_start)(struct net_device *);
unsigned int region;
@@ -1915,6 +1923,26 @@ static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp)
}
}
+static const struct net_device_ops rtl8169_netdev_ops = {
+ .ndo_open = rtl8169_open,
+ .ndo_stop = rtl8169_close,
+ .ndo_get_stats = rtl8169_get_stats,
+ .ndo_start_xmit = rtl8169_start_xmit,
+ .ndo_tx_timeout = rtl8169_tx_timeout,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = rtl8169_change_mtu,
+ .ndo_set_mac_address = rtl_set_mac_address,
+ .ndo_do_ioctl = rtl8169_ioctl,
+ .ndo_set_multicast_list = rtl_set_rx_mode,
+#ifdef CONFIG_R8169_VLAN
+ .ndo_vlan_rx_register = rtl8169_vlan_rx_register,
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = rtl8169_netpoll,
+#endif
+
+};
+
static int __devinit
rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
@@ -1941,6 +1969,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
SET_NETDEV_DEV(dev, &pdev->dev);
+ dev->netdev_ops = &rtl8169_netdev_ops;
tp = netdev_priv(dev);
tp->dev = dev;
tp->pci_dev = pdev;
@@ -2076,6 +2105,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->phy_reset_enable = rtl8169_tbi_reset_enable;
tp->phy_reset_pending = rtl8169_tbi_reset_pending;
tp->link_ok = rtl8169_tbi_link_ok;
+ tp->do_ioctl = rtl_tbi_ioctl;
tp->phy_1000_ctrl_reg = ADVERTISE_1000FULL; /* Implied by TBI */
} else {
@@ -2084,8 +2114,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
tp->phy_reset_enable = rtl8169_xmii_reset_enable;
tp->phy_reset_pending = rtl8169_xmii_reset_pending;
tp->link_ok = rtl8169_xmii_link_ok;
-
- dev->do_ioctl = rtl8169_ioctl;
+ tp->do_ioctl = rtl_xmii_ioctl;
}
spin_lock_init(&tp->lock);
@@ -2097,28 +2126,15 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev->dev_addr[i] = RTL_R8(MAC0 + i);
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
- dev->open = rtl8169_open;
- dev->hard_start_xmit = rtl8169_start_xmit;
- dev->get_stats = rtl8169_get_stats;
SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops);
- dev->stop = rtl8169_close;
- dev->tx_timeout = rtl8169_tx_timeout;
- dev->set_multicast_list = rtl_set_rx_mode;
dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
dev->irq = pdev->irq;
dev->base_addr = (unsigned long) ioaddr;
- dev->change_mtu = rtl8169_change_mtu;
- dev->set_mac_address = rtl_set_mac_address;
netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT);
#ifdef CONFIG_R8169_VLAN
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
- dev->vlan_rx_register = rtl8169_vlan_rx_register;
-#endif
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = rtl8169_netpoll;
#endif
tp->intr_mask = 0xffff;
@@ -3484,7 +3500,6 @@ static int rtl8169_rx_interrupt(struct net_device *dev,
if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0)
netif_receive_skb(skb);
- dev->last_rx = jiffies;
dev->stats.rx_bytes += pkt_size;
dev->stats.rx_packets++;
}
@@ -3566,8 +3581,8 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
RTL_W16(IntrMask, tp->intr_event & ~tp->napi_event);
tp->intr_mask = ~tp->napi_event;
- if (likely(netif_rx_schedule_prep(dev, &tp->napi)))
- __netif_rx_schedule(dev, &tp->napi);
+ if (likely(netif_rx_schedule_prep(&tp->napi)))
+ __netif_rx_schedule(&tp->napi);
else if (netif_msg_intr(tp)) {
printk(KERN_INFO "%s: interrupt %04x in poll\n",
dev->name, status);
@@ -3588,7 +3603,7 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
rtl8169_tx_interrupt(dev, tp, ioaddr);
if (work_done < budget) {
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
tp->intr_mask = 0xffff;
/*
* 20040426: the barrier is not strictly required but the
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index 2b8fd68bc516..a6fd27a2cc3d 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -94,7 +94,7 @@ static int rionet_rx_clean(struct net_device *ndev)
{
int i;
int error = 0;
- struct rionet_private *rnet = ndev->priv;
+ struct rionet_private *rnet = netdev_priv(ndev);
void *data;
i = rnet->rx_slot;
@@ -132,7 +132,7 @@ static int rionet_rx_clean(struct net_device *ndev)
static void rionet_rx_fill(struct net_device *ndev, int end)
{
int i;
- struct rionet_private *rnet = ndev->priv;
+ struct rionet_private *rnet = netdev_priv(ndev);
i = rnet->rx_slot;
do {
@@ -151,7 +151,7 @@ static void rionet_rx_fill(struct net_device *ndev, int end)
static int rionet_queue_tx_msg(struct sk_buff *skb, struct net_device *ndev,
struct rio_dev *rdev)
{
- struct rionet_private *rnet = ndev->priv;
+ struct rionet_private *rnet = netdev_priv(ndev);
rio_add_outb_message(rnet->mport, rdev, 0, skb->data, skb->len);
rnet->tx_skb[rnet->tx_slot] = skb;
@@ -175,7 +175,7 @@ static int rionet_queue_tx_msg(struct sk_buff *skb, struct net_device *ndev,
static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
int i;
- struct rionet_private *rnet = ndev->priv;
+ struct rionet_private *rnet = netdev_priv(ndev);
struct ethhdr *eth = (struct ethhdr *)skb->data;
u16 destid;
unsigned long flags;
@@ -215,7 +215,7 @@ static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u
u16 info)
{
struct net_device *ndev = dev_id;
- struct rionet_private *rnet = ndev->priv;
+ struct rionet_private *rnet = netdev_priv(ndev);
struct rionet_peer *peer;
if (netif_msg_intr(rnet))
@@ -243,7 +243,7 @@ static void rionet_inb_msg_event(struct rio_mport *mport, void *dev_id, int mbox
{
int n;
struct net_device *ndev = dev_id;
- struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
+ struct rionet_private *rnet = netdev_priv(ndev);
if (netif_msg_intr(rnet))
printk(KERN_INFO "%s: inbound message event, mbox %d slot %d\n",
@@ -258,7 +258,7 @@ static void rionet_inb_msg_event(struct rio_mport *mport, void *dev_id, int mbox
static void rionet_outb_msg_event(struct rio_mport *mport, void *dev_id, int mbox, int slot)
{
struct net_device *ndev = dev_id;
- struct rionet_private *rnet = ndev->priv;
+ struct rionet_private *rnet = netdev_priv(ndev);
spin_lock(&rnet->lock);
@@ -287,7 +287,7 @@ static int rionet_open(struct net_device *ndev)
int i, rc = 0;
struct rionet_peer *peer, *tmp;
u32 pwdcsr;
- struct rionet_private *rnet = ndev->priv;
+ struct rionet_private *rnet = netdev_priv(ndev);
if (netif_msg_ifup(rnet))
printk(KERN_INFO "%s: open\n", DRV_NAME);
@@ -351,7 +351,7 @@ static int rionet_open(struct net_device *ndev)
static int rionet_close(struct net_device *ndev)
{
- struct rionet_private *rnet = (struct rionet_private *)ndev->priv;
+ struct rionet_private *rnet = netdev_priv(ndev);
struct rionet_peer *peer, *tmp;
int i;
@@ -400,7 +400,7 @@ static void rionet_remove(struct rio_dev *rdev)
static void rionet_get_drvinfo(struct net_device *ndev,
struct ethtool_drvinfo *info)
{
- struct rionet_private *rnet = ndev->priv;
+ struct rionet_private *rnet = netdev_priv(ndev);
strcpy(info->driver, DRV_NAME);
strcpy(info->version, DRV_VERSION);
@@ -410,14 +410,14 @@ static void rionet_get_drvinfo(struct net_device *ndev,
static u32 rionet_get_msglevel(struct net_device *ndev)
{
- struct rionet_private *rnet = ndev->priv;
+ struct rionet_private *rnet = netdev_priv(ndev);
return rnet->msg_enable;
}
static void rionet_set_msglevel(struct net_device *ndev, u32 value)
{
- struct rionet_private *rnet = ndev->priv;
+ struct rionet_private *rnet = netdev_priv(ndev);
rnet->msg_enable = value;
}
@@ -435,7 +435,6 @@ static int rionet_setup_netdev(struct rio_mport *mport)
struct net_device *ndev = NULL;
struct rionet_private *rnet;
u16 device_id;
- DECLARE_MAC_BUF(mac);
/* Allocate our net_device structure */
ndev = alloc_etherdev(sizeof(struct rionet_private));
@@ -456,7 +455,7 @@ static int rionet_setup_netdev(struct rio_mport *mport)
RIO_MAX_ROUTE_ENTRIES(mport->sys_size));
/* Set up private area */
- rnet = (struct rionet_private *)ndev->priv;
+ rnet = netdev_priv(ndev);
rnet->mport = mport;
/* Set the default MAC address */
@@ -485,12 +484,12 @@ static int rionet_setup_netdev(struct rio_mport *mport)
if (rc != 0)
goto out;
- printk("%s: %s %s Version %s, MAC %s\n",
+ printk("%s: %s %s Version %s, MAC %pM\n",
ndev->name,
DRV_NAME,
DRV_DESC,
DRV_VERSION,
- print_mac(mac, ndev->dev_addr));
+ ndev->dev_addr);
out:
return rc;
diff --git a/drivers/net/rrunner.c b/drivers/net/rrunner.c
index 3dd8f1342f70..d890829a9acc 100644
--- a/drivers/net/rrunner.c
+++ b/drivers/net/rrunner.c
@@ -63,6 +63,16 @@ MODULE_LICENSE("GPL");
static char version[] __devinitdata = "rrunner.c: v0.50 11/11/2002 Jes Sorensen (jes@wildopensource.com)\n";
+
+static const struct net_device_ops rr_netdev_ops = {
+ .ndo_open = rr_open,
+ .ndo_stop = rr_close,
+ .ndo_do_ioctl = rr_ioctl,
+ .ndo_start_xmit = rr_start_xmit,
+ .ndo_change_mtu = hippi_change_mtu,
+ .ndo_set_mac_address = hippi_mac_addr,
+};
+
/*
* Implementation notes:
*
@@ -115,10 +125,7 @@ static int __devinit rr_init_one(struct pci_dev *pdev,
spin_lock_init(&rrpriv->lock);
dev->irq = pdev->irq;
- dev->open = &rr_open;
- dev->hard_start_xmit = &rr_start_xmit;
- dev->stop = &rr_close;
- dev->do_ioctl = &rr_ioctl;
+ dev->netdev_ops = &rr_netdev_ops;
dev->base_addr = pci_resource_start(pdev, 0);
@@ -511,7 +518,6 @@ static int __devinit rr_init(struct net_device *dev)
struct rr_private *rrpriv;
struct rr_regs __iomem *regs;
u32 sram_size, rev;
- DECLARE_MAC_BUF(mac);
rrpriv = netdev_priv(dev);
regs = rrpriv->regs;
@@ -549,7 +555,7 @@ static int __devinit rr_init(struct net_device *dev)
*(__be32 *)(dev->dev_addr+2) =
htonl(rr_read_eeprom_word(rrpriv, offsetof(struct eeprom, manf.BoardULA[4])));
- printk(" MAC: %s\n", print_mac(mac, dev->dev_addr));
+ printk(" MAC: %pM\n", dev->dev_addr);
sram_size = rr_read_eeprom_word(rrpriv, 8);
printk(" SRAM size 0x%06x\n", sram_size);
@@ -1006,7 +1012,6 @@ static void rx_int(struct net_device *dev, u32 rxlimit, u32 index)
netif_rx(skb); /* send it up */
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
}
@@ -1708,9 +1713,3 @@ static void __exit rr_cleanup_module(void)
module_init(rr_init_module);
module_exit(rr_cleanup_module);
-
-/*
- * Local variables:
- * compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -pipe -fomit-frame-pointer -fno-strength-reduce -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -c rrunner.c"
- * End:
- */
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 6a1375f9cbb8..f5c57c059bca 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -352,12 +352,13 @@ static void do_s2io_copy_mac_addr(struct s2io_nic *sp, int offset, u64 mac_addr)
sp->def_mac_addr[offset].mac_addr[1] = (u8) (mac_addr >> 32);
sp->def_mac_addr[offset].mac_addr[0] = (u8) (mac_addr >> 40);
}
+
/* Add the vlan */
static void s2io_vlan_rx_register(struct net_device *dev,
- struct vlan_group *grp)
+ struct vlan_group *grp)
{
int i;
- struct s2io_nic *nic = dev->priv;
+ struct s2io_nic *nic = netdev_priv(dev);
unsigned long flags[MAX_TX_FIFOS];
struct mac_info *mac_control = &nic->mac_control;
struct config_param *config = &nic->config;
@@ -372,10 +373,10 @@ static void s2io_vlan_rx_register(struct net_device *dev,
}
/* Unregister the vlan */
-static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned long vid)
+static void s2io_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
{
int i;
- struct s2io_nic *nic = dev->priv;
+ struct s2io_nic *nic = netdev_priv(dev);
unsigned long flags[MAX_TX_FIFOS];
struct mac_info *mac_control = &nic->mac_control;
struct config_param *config = &nic->config;
@@ -2837,7 +2838,7 @@ static int s2io_poll_msix(struct napi_struct *napi, int budget)
int pkts_processed = 0;
u8 __iomem *addr = NULL;
u8 val8 = 0;
- struct s2io_nic *nic = dev->priv;
+ struct s2io_nic *nic = netdev_priv(dev);
struct XENA_dev_config __iomem *bar0 = nic->bar0;
int budget_org = budget;
@@ -2851,7 +2852,7 @@ static int s2io_poll_msix(struct napi_struct *napi, int budget)
s2io_chk_rx_buffers(nic, ring);
if (pkts_processed < budget_org) {
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
/*Re Enable MSI-Rx Vector*/
addr = (u8 __iomem *)&bar0->xmsi_mask_reg;
addr += 7 - ring->ring_no;
@@ -2865,7 +2866,6 @@ static int s2io_poll_inta(struct napi_struct *napi, int budget)
{
struct s2io_nic *nic = container_of(napi, struct s2io_nic, napi);
struct ring_info *ring;
- struct net_device *dev = nic->dev;
struct config_param *config;
struct mac_info *mac_control;
int pkts_processed = 0;
@@ -2889,7 +2889,7 @@ static int s2io_poll_inta(struct napi_struct *napi, int budget)
break;
}
if (pkts_processed < budget_org) {
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
/* Re enable the Rx interrupts for the ring */
writeq(0, &bar0->rx_traffic_mask);
readl(&bar0->rx_traffic_mask);
@@ -2909,7 +2909,7 @@ static int s2io_poll_inta(struct napi_struct *napi, int budget)
*/
static void s2io_netpoll(struct net_device *dev)
{
- struct s2io_nic *nic = dev->priv;
+ struct s2io_nic *nic = netdev_priv(dev);
struct mac_info *mac_control;
struct config_param *config;
struct XENA_dev_config __iomem *bar0 = nic->bar0;
@@ -3171,7 +3171,7 @@ static void tx_intr_handler(struct fifo_info *fifo_data)
static void s2io_mdio_write(u32 mmd_type, u64 addr, u16 value, struct net_device *dev)
{
u64 val64 = 0x0;
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
struct XENA_dev_config __iomem *bar0 = sp->bar0;
//address transaction
@@ -3220,7 +3220,7 @@ static u64 s2io_mdio_read(u32 mmd_type, u64 addr, struct net_device *dev)
{
u64 val64 = 0x0;
u64 rval64 = 0x0;
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
struct XENA_dev_config __iomem *bar0 = sp->bar0;
/* address transaction */
@@ -3324,7 +3324,7 @@ static void s2io_updt_xpak_counter(struct net_device *dev)
u64 val64 = 0x0;
u64 addr = 0x0;
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
struct stat_block *stat_info = sp->mac_control.stats_info;
/* Check the communication with the MDIO slave */
@@ -3990,7 +3990,7 @@ static void remove_inta_isr(struct s2io_nic *sp)
static int s2io_open(struct net_device *dev)
{
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
int err = 0;
/*
@@ -4048,7 +4048,7 @@ hw_init_failed:
static int s2io_close(struct net_device *dev)
{
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
struct config_param *config = &sp->config;
u64 tmp64;
int offset;
@@ -4087,7 +4087,7 @@ static int s2io_close(struct net_device *dev)
static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
u16 frg_cnt, frg_len, i, queue, queue_len, put_off, get_off;
register u64 val64;
struct TxD *txdp;
@@ -4329,7 +4329,6 @@ static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id)
struct ring_info *ring = (struct ring_info *)dev_id;
struct s2io_nic *sp = ring->nic;
struct XENA_dev_config __iomem *bar0 = sp->bar0;
- struct net_device *dev = sp->dev;
if (unlikely(!is_s2io_card_up(sp)))
return IRQ_HANDLED;
@@ -4343,7 +4342,7 @@ static irqreturn_t s2io_msix_ring_handle(int irq, void *dev_id)
val8 = (ring->ring_no == 0) ? 0x7f : 0xff;
writeb(val8, addr);
val8 = readb(addr);
- netif_rx_schedule(dev, &ring->napi);
+ netif_rx_schedule(&ring->napi);
} else {
rx_intr_handler(ring, 0);
s2io_chk_rx_buffers(sp, ring);
@@ -4485,7 +4484,7 @@ static int do_s2io_chk_alarm_bit(u64 value, void __iomem * addr,
static void s2io_handle_errors(void * dev_id)
{
struct net_device *dev = (struct net_device *) dev_id;
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
struct XENA_dev_config __iomem *bar0 = sp->bar0;
u64 temp64 = 0,val64=0;
int i = 0;
@@ -4752,7 +4751,7 @@ reset:
static irqreturn_t s2io_isr(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *) dev_id;
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
struct XENA_dev_config __iomem *bar0 = sp->bar0;
int i;
u64 reason = 0;
@@ -4790,7 +4789,7 @@ static irqreturn_t s2io_isr(int irq, void *dev_id)
if (config->napi) {
if (reason & GEN_INTR_RXTRAFFIC) {
- netif_rx_schedule(dev, &sp->napi);
+ netif_rx_schedule(&sp->napi);
writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_mask);
writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
readl(&bar0->rx_traffic_int);
@@ -4881,7 +4880,7 @@ static void s2io_updt_stats(struct s2io_nic *sp)
static struct net_device_stats *s2io_get_stats(struct net_device *dev)
{
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
struct mac_info *mac_control;
struct config_param *config;
int i;
@@ -4948,7 +4947,7 @@ static void s2io_set_multicast(struct net_device *dev)
{
int i, j, prev_cnt;
struct dev_mc_list *mclist;
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
struct XENA_dev_config __iomem *bar0 = sp->bar0;
u64 val64 = 0, multi_mac = 0x010203040506ULL, mask =
0xfeffffffffffULL;
@@ -5112,7 +5111,7 @@ static void s2io_set_multicast(struct net_device *dev)
/* read from CAM unicast & multicast addresses and store it in
* def_mac_addr structure
*/
-void do_s2io_store_unicast_mc(struct s2io_nic *sp)
+static void do_s2io_store_unicast_mc(struct s2io_nic *sp)
{
int offset;
u64 mac_addr = 0x0;
@@ -5277,7 +5276,7 @@ static int s2io_set_mac_addr(struct net_device *dev, void *p)
static int do_s2io_prog_unicast(struct net_device *dev, u8 *addr)
{
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
register u64 mac_addr = 0, perm_addr = 0;
int i;
u64 tmp64;
@@ -5336,7 +5335,7 @@ static int do_s2io_prog_unicast(struct net_device *dev, u8 *addr)
static int s2io_ethtool_sset(struct net_device *dev,
struct ethtool_cmd *info)
{
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
if ((info->autoneg == AUTONEG_ENABLE) ||
(info->speed != SPEED_10000) || (info->duplex != DUPLEX_FULL))
return -EINVAL;
@@ -5362,7 +5361,7 @@ static int s2io_ethtool_sset(struct net_device *dev,
static int s2io_ethtool_gset(struct net_device *dev, struct ethtool_cmd *info)
{
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
info->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
info->advertising = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
info->port = PORT_FIBRE;
@@ -5397,7 +5396,7 @@ static int s2io_ethtool_gset(struct net_device *dev, struct ethtool_cmd *info)
static void s2io_ethtool_gdrvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
strncpy(info->driver, s2io_driver_name, sizeof(info->driver));
strncpy(info->version, s2io_driver_version, sizeof(info->version));
@@ -5427,7 +5426,7 @@ static void s2io_ethtool_gregs(struct net_device *dev,
int i;
u64 reg;
u8 *reg_space = (u8 *) space;
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
regs->len = XENA_REG_SPACE;
regs->version = sp->pdev->subsystem_device;
@@ -5487,7 +5486,7 @@ static void s2io_phy_id(unsigned long data)
static int s2io_ethtool_idnic(struct net_device *dev, u32 data)
{
u64 val64 = 0, last_gpio_ctrl_val;
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
struct XENA_dev_config __iomem *bar0 = sp->bar0;
u16 subid;
@@ -5525,7 +5524,7 @@ static int s2io_ethtool_idnic(struct net_device *dev, u32 data)
static void s2io_ethtool_gringparam(struct net_device *dev,
struct ethtool_ringparam *ering)
{
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
int i,tx_desc_count=0,rx_desc_count=0;
if (sp->rxd_mode == RXD_MODE_1)
@@ -5568,7 +5567,7 @@ static void s2io_ethtool_getpause_data(struct net_device *dev,
struct ethtool_pauseparam *ep)
{
u64 val64;
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
struct XENA_dev_config __iomem *bar0 = sp->bar0;
val64 = readq(&bar0->rmac_pause_cfg);
@@ -5595,7 +5594,7 @@ static int s2io_ethtool_setpause_data(struct net_device *dev,
struct ethtool_pauseparam *ep)
{
u64 val64;
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
struct XENA_dev_config __iomem *bar0 = sp->bar0;
val64 = readq(&bar0->rmac_pause_cfg);
@@ -5825,7 +5824,7 @@ static int s2io_ethtool_geeprom(struct net_device *dev,
{
u32 i, valid;
u64 data;
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
eeprom->magic = sp->pdev->vendor | (sp->pdev->device << 16);
@@ -5863,7 +5862,7 @@ static int s2io_ethtool_seeprom(struct net_device *dev,
{
int len = eeprom->len, cnt = 0;
u64 valid = 0, data;
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
if (eeprom->magic != (sp->pdev->vendor | (sp->pdev->device << 16))) {
DBG_PRINT(ERR_DBG,
@@ -6243,7 +6242,7 @@ static void s2io_ethtool_test(struct net_device *dev,
struct ethtool_test *ethtest,
uint64_t * data)
{
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
int orig_state = netif_running(sp->dev);
if (ethtest->flags == ETH_TEST_FL_OFFLINE) {
@@ -6299,7 +6298,7 @@ static void s2io_get_ethtool_stats(struct net_device *dev,
u64 * tmp_stats)
{
int i = 0, k;
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
struct stat_block *stat_info = sp->mac_control.stats_info;
s2io_updt_stats(sp);
@@ -6578,14 +6577,14 @@ static int s2io_ethtool_get_regs_len(struct net_device *dev)
static u32 s2io_ethtool_get_rx_csum(struct net_device * dev)
{
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
return (sp->rx_csum);
}
static int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)
{
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
if (data)
sp->rx_csum = 1;
@@ -6602,7 +6601,7 @@ static int s2io_get_eeprom_len(struct net_device *dev)
static int s2io_get_sset_count(struct net_device *dev, int sset)
{
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
switch (sset) {
case ETH_SS_TEST:
@@ -6625,7 +6624,7 @@ static void s2io_ethtool_get_strings(struct net_device *dev,
u32 stringset, u8 * data)
{
int stat_size = 0;
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
switch (stringset) {
case ETH_SS_TEST:
@@ -6727,7 +6726,7 @@ static int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static int s2io_change_mtu(struct net_device *dev, int new_mtu)
{
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
int ret = 0;
if ((new_mtu < MIN_MTU) || (new_mtu > S2IO_JUMBO_SIZE)) {
@@ -7331,7 +7330,7 @@ out_unlock:
static void s2io_tx_watchdog(struct net_device *dev)
{
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
if (netif_carrier_ok(dev)) {
sp->mac_control.stats_info->sw_stat.watchdog_timer_cnt++;
@@ -7366,7 +7365,7 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
int ring_no = ring_data->ring_no;
u16 l3_csum, l4_csum;
unsigned long long err = rxdp->Control_1 & RXD_T_CODE;
- struct lro *lro;
+ struct lro *uninitialized_var(lro);
u8 err_mask;
skb->dev = dev;
@@ -7544,7 +7543,6 @@ static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp)
sp->mac_control.stats_info->sw_stat.mem_freed += skb->truesize;
send_up:
queue_rx_frame(skb, RXD_GET_VLAN_TAG(rxdp->Control_2));
- dev->last_rx = jiffies;
aggregate:
sp->mac_control.rings[ring_no].rx_bufs_left -= 1;
return SUCCESS;
@@ -7718,6 +7716,24 @@ static int rts_ds_steer(struct s2io_nic *nic, u8 ds_codepoint, u8 ring)
S2IO_BIT_RESET);
}
+static const struct net_device_ops s2io_netdev_ops = {
+ .ndo_open = s2io_open,
+ .ndo_stop = s2io_close,
+ .ndo_get_stats = s2io_get_stats,
+ .ndo_start_xmit = s2io_xmit,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_multicast_list = s2io_set_multicast,
+ .ndo_do_ioctl = s2io_ioctl,
+ .ndo_set_mac_address = s2io_set_mac_addr,
+ .ndo_change_mtu = s2io_change_mtu,
+ .ndo_vlan_rx_register = s2io_vlan_rx_register,
+ .ndo_vlan_rx_kill_vid = s2io_vlan_rx_kill_vid,
+ .ndo_tx_timeout = s2io_tx_watchdog,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = s2io_netpoll,
+#endif
+};
+
/**
* s2io_init_nic - Initialization of the adapter .
* @pdev : structure containing the PCI related information of the device.
@@ -7748,7 +7764,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
int mode;
u8 dev_intr_type = intr_type;
u8 dev_multiq = 0;
- DECLARE_MAC_BUF(mac);
ret = s2io_verify_parm(pdev, &dev_intr_type, &dev_multiq);
if (ret)
@@ -7798,7 +7813,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
SET_NETDEV_DEV(dev, &pdev->dev);
/* Private member variable initialized to s2io NIC structure */
- sp = dev->priv;
+ sp = netdev_priv(dev);
memset(sp, 0, sizeof(struct s2io_nic));
sp->dev = dev;
sp->pdev = pdev;
@@ -7918,8 +7933,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
goto mem_alloc_failed;
}
- sp->bar0 = ioremap(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
+ sp->bar0 = pci_ioremap_bar(pdev, 0);
if (!sp->bar0) {
DBG_PRINT(ERR_DBG, "%s: Neterion: cannot remap io mem1\n",
dev->name);
@@ -7927,8 +7941,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
goto bar0_remap_failed;
}
- sp->bar1 = ioremap(pci_resource_start(pdev, 2),
- pci_resource_len(pdev, 2));
+ sp->bar1 = pci_ioremap_bar(pdev, 2);
if (!sp->bar1) {
DBG_PRINT(ERR_DBG, "%s: Neterion: cannot remap io mem2\n",
dev->name);
@@ -7946,26 +7959,9 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
}
/* Driver entry points */
- dev->open = &s2io_open;
- dev->stop = &s2io_close;
- dev->hard_start_xmit = &s2io_xmit;
- dev->get_stats = &s2io_get_stats;
- dev->set_multicast_list = &s2io_set_multicast;
- dev->do_ioctl = &s2io_ioctl;
- dev->set_mac_address = &s2io_set_mac_addr;
- dev->change_mtu = &s2io_change_mtu;
+ dev->netdev_ops = &s2io_netdev_ops;
SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
- dev->vlan_rx_register = s2io_vlan_rx_register;
- dev->vlan_rx_kill_vid = (void *)s2io_vlan_rx_kill_vid;
-
- /*
- * will use eth_mac_addr() for dev->set_mac_address
- * mac address will be set every time dev->open() is called
- */
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = s2io_netpoll;
-#endif
dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
if (sp->high_dma_flag == TRUE)
@@ -7976,7 +7972,6 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
dev->features |= NETIF_F_UFO;
dev->features |= NETIF_F_HW_CSUM;
}
- dev->tx_timeout = &s2io_tx_watchdog;
dev->watchdog_timeo = WATCH_DOG_TIMEOUT;
INIT_WORK(&sp->rst_timer_task, s2io_restart_nic);
INIT_WORK(&sp->set_link_task, s2io_set_link);
@@ -8125,8 +8120,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
sp->product_name, pdev->revision);
DBG_PRINT(ERR_DBG, "%s: Driver version %s\n", dev->name,
s2io_driver_version);
- DBG_PRINT(ERR_DBG, "%s: MAC ADDR: %s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ DBG_PRINT(ERR_DBG, "%s: MAC ADDR: %pM\n", dev->name, dev->dev_addr);
DBG_PRINT(ERR_DBG, "SERIAL NUMBER: %s\n", sp->serial_num);
if (sp->device_type & XFRAME_II_DEVICE) {
mode = s2io_print_pci_mode(sp);
@@ -8255,7 +8249,7 @@ static void __devexit s2io_rem_nic(struct pci_dev *pdev)
flush_scheduled_work();
- sp = dev->priv;
+ sp = netdev_priv(dev);
unregister_netdev(dev);
free_shared_mem(sp);
@@ -8590,7 +8584,7 @@ static void clear_lro_session(struct lro *lro)
static void queue_rx_frame(struct sk_buff *skb, u16 vlan_tag)
{
struct net_device *dev = skb->dev;
- struct s2io_nic *sp = dev->priv;
+ struct s2io_nic *sp = netdev_priv(dev);
skb->protocol = eth_type_trans(skb, dev);
if (sp->vlgrp && vlan_tag
@@ -8639,7 +8633,7 @@ static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,
pci_channel_state_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct s2io_nic *sp = netdev->priv;
+ struct s2io_nic *sp = netdev_priv(netdev);
netif_device_detach(netdev);
@@ -8664,7 +8658,7 @@ static pci_ers_result_t s2io_io_error_detected(struct pci_dev *pdev,
static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct s2io_nic *sp = netdev->priv;
+ struct s2io_nic *sp = netdev_priv(netdev);
if (pci_enable_device(pdev)) {
printk(KERN_ERR "s2io: "
@@ -8688,7 +8682,7 @@ static pci_ers_result_t s2io_io_slot_reset(struct pci_dev *pdev)
static void s2io_io_resume(struct pci_dev *pdev)
{
struct net_device *netdev = pci_get_drvdata(pdev);
- struct s2io_nic *sp = netdev->priv;
+ struct s2io_nic *sp = netdev_priv(netdev);
if (netif_running(netdev)) {
if (s2io_card_up(sp)) {
diff --git a/drivers/net/sb1000.c b/drivers/net/sb1000.c
index 5986cec17f19..be3025310e90 100644
--- a/drivers/net/sb1000.c
+++ b/drivers/net/sb1000.c
@@ -869,7 +869,6 @@ printk("cm0: IP identification: %02x%02x fragment offset: %02x%02x\n", buffer[3
/* datagram completed: send to upper level */
skb_trim(skb, dlen);
netif_rx(skb);
- dev->last_rx = jiffies;
stats->rx_bytes+=dlen;
stats->rx_packets++;
lp->rx_skb[ns] = NULL;
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
index 2615d46e6e50..31e38fae017f 100644
--- a/drivers/net/sb1250-mac.c
+++ b/drivers/net/sb1250-mac.c
@@ -2039,9 +2039,9 @@ static irqreturn_t sbmac_intr(int irq,void *dev_instance)
sbdma_tx_process(sc,&(sc->sbm_txdma), 0);
if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) {
- if (netif_rx_schedule_prep(dev, &sc->napi)) {
+ if (netif_rx_schedule_prep(&sc->napi)) {
__raw_writeq(0, sc->sbm_imr);
- __netif_rx_schedule(dev, &sc->napi);
+ __netif_rx_schedule(&sc->napi);
/* Depend on the exit from poll to reenable intr */
}
else {
@@ -2292,7 +2292,6 @@ static int sbmac_init(struct platform_device *pldev, long long base)
uint64_t ea_reg;
int i;
int err;
- DECLARE_MAC_BUF(mac);
sc->sbm_dev = dev;
sc->sbe_idx = idx;
@@ -2373,8 +2372,8 @@ static int sbmac_init(struct platform_device *pldev, long long base)
* process so we need to finish off the config message that
* was being displayed)
*/
- pr_info("%s: SiByte Ethernet at 0x%08Lx, address: %s\n",
- dev->name, base, print_mac(mac, eaddr));
+ pr_info("%s: SiByte Ethernet at 0x%08Lx, address: %pM\n",
+ dev->name, base, eaddr);
sc->mii_bus->name = sbmac_mdio_string;
snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%x", idx);
@@ -2668,7 +2667,7 @@ static int sbmac_poll(struct napi_struct *napi, int budget)
sbdma_tx_process(sc, &(sc->sbm_txdma), 1);
if (work_done < budget) {
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
#ifdef CONFIG_SBMAC_COALESCE
__raw_writeq(((M_MAC_INT_EOP_COUNT | M_MAC_INT_EOP_TIMER) << S_MAC_TX_CH0) |
diff --git a/drivers/net/sc92031.c b/drivers/net/sc92031.c
index 61955f8d8011..42fd31276602 100644
--- a/drivers/net/sc92031.c
+++ b/drivers/net/sc92031.c
@@ -816,7 +816,6 @@ static void _sc92031_rx_tasklet(struct net_device *dev)
}
skb->protocol = eth_type_trans(skb, dev);
- dev->last_rx = jiffies;
netif_rx(skb);
dev->stats.rx_bytes += pkt_size;
@@ -1387,7 +1386,7 @@ static void sc92031_ethtool_get_ethtool_stats(struct net_device *dev,
spin_unlock_bh(&priv->lock);
}
-static struct ethtool_ops sc92031_ethtool_ops = {
+static const struct ethtool_ops sc92031_ethtool_ops = {
.get_settings = sc92031_ethtool_get_settings,
.set_settings = sc92031_ethtool_set_settings,
.get_drvinfo = sc92031_ethtool_get_drvinfo,
@@ -1400,6 +1399,21 @@ static struct ethtool_ops sc92031_ethtool_ops = {
.get_ethtool_stats = sc92031_ethtool_get_ethtool_stats,
};
+
+static const struct net_device_ops sc92031_netdev_ops = {
+ .ndo_get_stats = sc92031_get_stats,
+ .ndo_start_xmit = sc92031_start_xmit,
+ .ndo_open = sc92031_open,
+ .ndo_stop = sc92031_stop,
+ .ndo_set_multicast_list = sc92031_set_multicast_list,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_tx_timeout = sc92031_tx_timeout,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = sc92031_poll_controller,
+#endif
+};
+
static int __devinit sc92031_probe(struct pci_dev *pdev,
const struct pci_device_id *id)
{
@@ -1453,17 +1467,9 @@ static int __devinit sc92031_probe(struct pci_dev *pdev,
/* faked with skb_copy_and_csum_dev */
dev->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA;
- dev->get_stats = sc92031_get_stats;
- dev->ethtool_ops = &sc92031_ethtool_ops;
- dev->hard_start_xmit = sc92031_start_xmit;
+ dev->netdev_ops = &sc92031_netdev_ops;
dev->watchdog_timeo = TX_TIMEOUT;
- dev->open = sc92031_open;
- dev->stop = sc92031_stop;
- dev->set_multicast_list = sc92031_set_multicast_list;
- dev->tx_timeout = sc92031_tx_timeout;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = sc92031_poll_controller;
-#endif
+ dev->ethtool_ops = &sc92031_ethtool_ops;
priv = netdev_priv(dev);
spin_lock_init(&priv->lock);
diff --git a/drivers/net/seeq8005.c b/drivers/net/seeq8005.c
index 48c64fb20eec..12a8ffffeb03 100644
--- a/drivers/net/seeq8005.c
+++ b/drivers/net/seeq8005.c
@@ -158,7 +158,6 @@ static int __init seeq8005_probe1(struct net_device *dev, int ioaddr)
int old_dmaar;
int old_rear;
int retval;
- DECLARE_MAC_BUF(mac);
if (!request_region(ioaddr, SEEQ8005_IO_EXTENT, "seeq8005"))
return -ENODEV;
@@ -303,7 +302,7 @@ static int __init seeq8005_probe1(struct net_device *dev, int ioaddr)
/* Retrieve and print the ethernet address. */
for (i = 0; i < 6; i++)
dev->dev_addr[i] = SA_prom[i+6];
- printk("%s", print_mac(mac, dev->dev_addr));
+ printk("%pM", dev->dev_addr);
if (dev->irq == 0xff)
; /* Do nothing: a user-level program will set it. */
@@ -564,7 +563,6 @@ static void seeq8005_rx(struct net_device *dev)
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
}
@@ -746,12 +744,3 @@ void __exit cleanup_module(void)
}
#endif /* MODULE */
-
-/*
- * Local variables:
- * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c skeleton.c"
- * version-control: t
- * kept-new-versions: 5
- * tab-width: 4
- * End:
- */
diff --git a/drivers/net/sfc/Kconfig b/drivers/net/sfc/Kconfig
index 3be13b592b4d..c535408ad6be 100644
--- a/drivers/net/sfc/Kconfig
+++ b/drivers/net/sfc/Kconfig
@@ -12,3 +12,11 @@ config SFC
To compile this driver as a module, choose M here. The module
will be called sfc.
+config SFC_MTD
+ bool "Solarflare Solarstorm SFC4000 flash MTD support"
+ depends on SFC && MTD && !(SFC=y && MTD=m)
+ default y
+ help
+ This exposes the on-board flash memory as an MTD device (e.g.
+ /dev/mtd1). This makes it possible to upload new boot code
+ to the NIC.
diff --git a/drivers/net/sfc/Makefile b/drivers/net/sfc/Makefile
index c8f5704c8fb1..b89f9be3cb13 100644
--- a/drivers/net/sfc/Makefile
+++ b/drivers/net/sfc/Makefile
@@ -1,5 +1,6 @@
-sfc-y += efx.o falcon.o tx.o rx.o falcon_xmac.o \
- selftest.o ethtool.o xfp_phy.o \
+sfc-y += efx.o falcon.o tx.o rx.o falcon_gmac.o \
+ falcon_xmac.o selftest.o ethtool.o xfp_phy.o \
mdio_10g.o tenxpress.o boards.o sfe4001.o
+sfc-$(CONFIG_SFC_MTD) += mtd.o
obj-$(CONFIG_SFC) += sfc.o
diff --git a/drivers/net/sfc/boards.c b/drivers/net/sfc/boards.c
index 99e602373269..64903496aa9a 100644
--- a/drivers/net/sfc/boards.c
+++ b/drivers/net/sfc/boards.c
@@ -1,6 +1,6 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2007 Solarflare Communications Inc.
+ * Copyright 2007-2008 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@@ -11,6 +11,7 @@
#include "phy.h"
#include "boards.h"
#include "efx.h"
+#include "workarounds.h"
/* Macros for unpacking the board revision */
/* The revision info is in host byte order. */
@@ -52,9 +53,128 @@ static void board_blink(struct efx_nic *efx, bool blink)
}
/*****************************************************************************
+ * Support for LM87 sensor chip used on several boards
+ */
+#define LM87_REG_ALARMS1 0x41
+#define LM87_REG_ALARMS2 0x42
+#define LM87_IN_LIMITS(nr, _min, _max) \
+ 0x2B + (nr) * 2, _max, 0x2C + (nr) * 2, _min
+#define LM87_AIN_LIMITS(nr, _min, _max) \
+ 0x3B + (nr), _max, 0x1A + (nr), _min
+#define LM87_TEMP_INT_LIMITS(_min, _max) \
+ 0x39, _max, 0x3A, _min
+#define LM87_TEMP_EXT1_LIMITS(_min, _max) \
+ 0x37, _max, 0x38, _min
+
+#define LM87_ALARM_TEMP_INT 0x10
+#define LM87_ALARM_TEMP_EXT1 0x20
+
+#if defined(CONFIG_SENSORS_LM87) || defined(CONFIG_SENSORS_LM87_MODULE)
+
+static int efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info,
+ const u8 *reg_values)
+{
+ struct i2c_client *client = i2c_new_device(&efx->i2c_adap, info);
+ int rc;
+
+ if (!client)
+ return -EIO;
+
+ while (*reg_values) {
+ u8 reg = *reg_values++;
+ u8 value = *reg_values++;
+ rc = i2c_smbus_write_byte_data(client, reg, value);
+ if (rc)
+ goto err;
+ }
+
+ efx->board_info.hwmon_client = client;
+ return 0;
+
+err:
+ i2c_unregister_device(client);
+ return rc;
+}
+
+static void efx_fini_lm87(struct efx_nic *efx)
+{
+ i2c_unregister_device(efx->board_info.hwmon_client);
+}
+
+static int efx_check_lm87(struct efx_nic *efx, unsigned mask)
+{
+ struct i2c_client *client = efx->board_info.hwmon_client;
+ s32 alarms1, alarms2;
+
+ /* If link is up then do not monitor temperature */
+ if (EFX_WORKAROUND_7884(efx) && efx->link_up)
+ return 0;
+
+ alarms1 = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS1);
+ alarms2 = i2c_smbus_read_byte_data(client, LM87_REG_ALARMS2);
+ if (alarms1 < 0)
+ return alarms1;
+ if (alarms2 < 0)
+ return alarms2;
+ alarms1 &= mask;
+ alarms2 &= mask >> 8;
+ if (alarms1 || alarms2) {
+ EFX_ERR(efx,
+ "LM87 detected a hardware failure (status %02x:%02x)"
+ "%s%s\n",
+ alarms1, alarms2,
+ (alarms1 & LM87_ALARM_TEMP_INT) ? " INTERNAL" : "",
+ (alarms1 & LM87_ALARM_TEMP_EXT1) ? " EXTERNAL" : "");
+ return -ERANGE;
+ }
+
+ return 0;
+}
+
+#else /* !CONFIG_SENSORS_LM87 */
+
+static inline int
+efx_init_lm87(struct efx_nic *efx, struct i2c_board_info *info,
+ const u8 *reg_values)
+{
+ return 0;
+}
+static inline void efx_fini_lm87(struct efx_nic *efx)
+{
+}
+static inline int efx_check_lm87(struct efx_nic *efx, unsigned mask)
+{
+ return 0;
+}
+
+#endif /* CONFIG_SENSORS_LM87 */
+
+/*****************************************************************************
* Support for the SFE4002
*
*/
+static u8 sfe4002_lm87_channel = 0x03; /* use AIN not FAN inputs */
+
+static const u8 sfe4002_lm87_regs[] = {
+ LM87_IN_LIMITS(0, 0x83, 0x91), /* 2.5V: 1.8V +/- 5% */
+ LM87_IN_LIMITS(1, 0x51, 0x5a), /* Vccp1: 1.2V +/- 5% */
+ LM87_IN_LIMITS(2, 0xb6, 0xca), /* 3.3V: 3.3V +/- 5% */
+ LM87_IN_LIMITS(3, 0xb0, 0xc9), /* 5V: 4.6-5.2V */
+ LM87_IN_LIMITS(4, 0xb0, 0xe0), /* 12V: 11-14V */
+ LM87_IN_LIMITS(5, 0x44, 0x4b), /* Vccp2: 1.0V +/- 5% */
+ LM87_AIN_LIMITS(0, 0xa0, 0xb2), /* AIN1: 1.66V +/- 5% */
+ LM87_AIN_LIMITS(1, 0x91, 0xa1), /* AIN2: 1.5V +/- 5% */
+ LM87_TEMP_INT_LIMITS(10, 60), /* board */
+ LM87_TEMP_EXT1_LIMITS(10, 70), /* Falcon */
+ 0
+};
+
+static struct i2c_board_info sfe4002_hwmon_info = {
+ I2C_BOARD_INFO("lm87", 0x2e),
+ .platform_data = &sfe4002_lm87_channel,
+ .irq = -1,
+};
+
/****************************************************************************/
/* LED allocations. Note that on rev A0 boards the schematic and the reality
* differ: red and green are swapped. Below is the fixed (A1) layout (there
@@ -84,81 +204,67 @@ static void sfe4002_fault_led(struct efx_nic *efx, bool state)
QUAKE_LED_OFF);
}
+static int sfe4002_check_hw(struct efx_nic *efx)
+{
+ /* A0 board rev. 4002s report a temperature fault the whole time
+ * (bad sensor) so we mask it out. */
+ unsigned alarm_mask =
+ (efx->board_info.major == 0 && efx->board_info.minor == 0) ?
+ ~LM87_ALARM_TEMP_EXT1 : ~0;
+
+ return efx_check_lm87(efx, alarm_mask);
+}
+
static int sfe4002_init(struct efx_nic *efx)
{
+ int rc = efx_init_lm87(efx, &sfe4002_hwmon_info, sfe4002_lm87_regs);
+ if (rc)
+ return rc;
+ efx->board_info.monitor = sfe4002_check_hw;
efx->board_info.init_leds = sfe4002_init_leds;
efx->board_info.set_fault_led = sfe4002_fault_led;
efx->board_info.blink = board_blink;
+ efx->board_info.fini = efx_fini_lm87;
return 0;
}
/* This will get expanded as board-specific details get moved out of the
* PHY drivers. */
struct efx_board_data {
+ enum efx_board_type type;
const char *ref_model;
const char *gen_type;
int (*init) (struct efx_nic *nic);
};
-static int dummy_init(struct efx_nic *nic)
-{
- return 0;
-}
static struct efx_board_data board_data[] = {
- [EFX_BOARD_INVALID] =
- {NULL, NULL, dummy_init},
- [EFX_BOARD_SFE4001] =
- {"SFE4001", "10GBASE-T adapter", sfe4001_init},
- [EFX_BOARD_SFE4002] =
- {"SFE4002", "XFP adapter", sfe4002_init},
+ { EFX_BOARD_SFE4001, "SFE4001", "10GBASE-T adapter", sfe4001_init },
+ { EFX_BOARD_SFE4002, "SFE4002", "XFP adapter", sfe4002_init },
+ { EFX_BOARD_SFN4111T, "SFN4111T", "100/1000/10GBASE-T adapter",
+ sfn4111t_init },
};
-int efx_set_board_info(struct efx_nic *efx, u16 revision_info)
+void efx_set_board_info(struct efx_nic *efx, u16 revision_info)
{
- int rc = 0;
- struct efx_board_data *data;
-
- if (BOARD_TYPE(revision_info) >= EFX_BOARD_MAX) {
- EFX_ERR(efx, "squashing unknown board type %d\n",
- BOARD_TYPE(revision_info));
- revision_info = 0;
- }
+ struct efx_board_data *data = NULL;
+ int i;
- if (BOARD_TYPE(revision_info) == 0) {
- efx->board_info.major = 0;
- efx->board_info.minor = 0;
- /* For early boards that don't have revision info. there is
- * only 1 board for each PHY type, so we can work it out, with
- * the exception of the PHY-less boards. */
- switch (efx->phy_type) {
- case PHY_TYPE_10XPRESS:
- efx->board_info.type = EFX_BOARD_SFE4001;
- break;
- case PHY_TYPE_XFP:
- efx->board_info.type = EFX_BOARD_SFE4002;
- break;
- default:
- efx->board_info.type = 0;
- break;
- }
- } else {
- efx->board_info.type = BOARD_TYPE(revision_info);
- efx->board_info.major = BOARD_MAJOR(revision_info);
- efx->board_info.minor = BOARD_MINOR(revision_info);
- }
+ efx->board_info.type = BOARD_TYPE(revision_info);
+ efx->board_info.major = BOARD_MAJOR(revision_info);
+ efx->board_info.minor = BOARD_MINOR(revision_info);
- data = &board_data[efx->board_info.type];
+ for (i = 0; i < ARRAY_SIZE(board_data); i++)
+ if (board_data[i].type == efx->board_info.type)
+ data = &board_data[i];
- /* Report the board model number or generic type for recognisable
- * boards. */
- if (efx->board_info.type != 0)
+ if (data) {
EFX_INFO(efx, "board is %s rev %c%d\n",
(efx->pci_dev->subsystem_vendor == EFX_VENDID_SFC)
? data->ref_model : data->gen_type,
'A' + efx->board_info.major, efx->board_info.minor);
-
- efx->board_info.init = data->init;
-
- return rc;
+ efx->board_info.init = data->init;
+ } else {
+ EFX_ERR(efx, "unknown board type %d\n", efx->board_info.type);
+ }
}
diff --git a/drivers/net/sfc/boards.h b/drivers/net/sfc/boards.h
index c6e01b64bfb4..d93c6c6a7548 100644
--- a/drivers/net/sfc/boards.h
+++ b/drivers/net/sfc/boards.h
@@ -1,6 +1,6 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2007 Solarflare Communications Inc.
+ * Copyright 2007-2008 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@@ -12,14 +12,16 @@
/* Board IDs (must fit in 8 bits) */
enum efx_board_type {
- EFX_BOARD_INVALID = 0,
- EFX_BOARD_SFE4001 = 1, /* SFE4001 (10GBASE-T) */
+ EFX_BOARD_SFE4001 = 1,
EFX_BOARD_SFE4002 = 2,
- /* Insert new types before here */
- EFX_BOARD_MAX
+ EFX_BOARD_SFN4111T = 0x51,
};
-extern int efx_set_board_info(struct efx_nic *efx, u16 revision_info);
+extern void efx_set_board_info(struct efx_nic *efx, u16 revision_info);
+
+/* SFE4001 (10GBASE-T) */
extern int sfe4001_init(struct efx_nic *efx);
+/* SFN4111T (100/1000/10GBASE-T) */
+extern int sfn4111t_init(struct efx_nic *efx);
#endif
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 06ea71c7e34e..7673fd92eaf5 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -21,14 +21,12 @@
#include <linux/ethtool.h>
#include <linux/topology.h>
#include "net_driver.h"
-#include "gmii.h"
#include "ethtool.h"
#include "tx.h"
#include "rx.h"
#include "efx.h"
#include "mdio_10g.h"
#include "falcon.h"
-#include "mac.h"
#define EFX_MAX_MTU (9 * 1024)
@@ -39,6 +37,12 @@
*/
static struct workqueue_struct *refill_workqueue;
+/* Reset workqueue. If any NIC has a hardware failure then a reset will be
+ * queued onto this work queue. This is not a per-nic work queue, because
+ * efx_reset_work() acquires the rtnl lock, so resets are naturally serialised.
+ */
+static struct workqueue_struct *reset_workqueue;
+
/**************************************************************************
*
* Configurable values
@@ -58,13 +62,15 @@ MODULE_PARM_DESC(lro, "Large receive offload acceleration");
/*
* Use separate channels for TX and RX events
*
- * Set this to 1 to use separate channels for TX and RX. It allows us to
- * apply a higher level of interrupt moderation to TX events.
+ * Set this to 1 to use separate channels for TX and RX. It allows us
+ * to control interrupt affinity separately for TX and RX.
*
- * This is forced to 0 for MSI interrupt mode as the interrupt vector
- * is not written
+ * This is only used in MSI-X interrupt mode
*/
-static unsigned int separate_tx_and_rx_channels = true;
+static unsigned int separate_tx_channels;
+module_param(separate_tx_channels, uint, 0644);
+MODULE_PARM_DESC(separate_tx_channels,
+ "Use separate channels for TX and RX");
/* This is the weight assigned to each of the (per-channel) virtual
* NAPI devices.
@@ -77,11 +83,6 @@ static int napi_weight = 64;
*/
unsigned int efx_monitor_interval = 1 * HZ;
-/* This controls whether or not the hardware monitor will trigger a
- * reset when it detects an error condition.
- */
-static unsigned int monitor_reset = true;
-
/* This controls whether or not the driver will initialise devices
* with invalid MAC addresses stored in the EEPROM or flash. If true,
* such devices will be initialised with a random locally-generated
@@ -128,6 +129,10 @@ static unsigned int rss_cpus;
module_param(rss_cpus, uint, 0444);
MODULE_PARM_DESC(rss_cpus, "Number of CPUs to use for Receive-Side Scaling");
+static int phy_flash_cfg;
+module_param(phy_flash_cfg, int, 0644);
+MODULE_PARM_DESC(phy_flash_cfg, "Set PHYs into reflash mode initially");
+
/**************************************************************************
*
* Utility functions and prototypes
@@ -211,7 +216,6 @@ static int efx_poll(struct napi_struct *napi, int budget)
{
struct efx_channel *channel =
container_of(napi, struct efx_channel, napi_str);
- struct net_device *napi_dev = channel->napi_dev;
int rx_packets;
EFX_TRACE(channel->efx, "channel %d NAPI poll executing on CPU %d\n",
@@ -225,7 +229,7 @@ static int efx_poll(struct napi_struct *napi, int budget)
* since efx_channel_processed() will have no effect if
* interrupts have already been disabled.
*/
- netif_rx_complete(napi_dev, napi);
+ netif_rx_complete(napi);
efx_channel_processed(channel);
}
@@ -349,6 +353,27 @@ static int efx_probe_channel(struct efx_channel *channel)
}
+static void efx_set_channel_names(struct efx_nic *efx)
+{
+ struct efx_channel *channel;
+ const char *type = "";
+ int number;
+
+ efx_for_each_channel(channel, efx) {
+ number = channel->channel;
+ if (efx->n_channels > efx->n_rx_queues) {
+ if (channel->channel < efx->n_rx_queues) {
+ type = "-rx";
+ } else {
+ type = "-tx";
+ number -= efx->n_rx_queues;
+ }
+ }
+ snprintf(channel->name, sizeof(channel->name),
+ "%s%s-%d", efx->name, type, number);
+ }
+}
+
/* Channels are shutdown and reinitialised whilst the NIC is running
* to propagate configuration changes (mtu, checksum offload), or
* to clear hardware error conditions
@@ -523,26 +548,8 @@ static void efx_link_status_changed(struct efx_nic *efx)
/* Status message for kernel log */
if (efx->link_up) {
- struct mii_if_info *gmii = &efx->mii;
- unsigned adv, lpa;
- /* NONE here means direct XAUI from the controller, with no
- * MDIO-attached device we can query. */
- if (efx->phy_type != PHY_TYPE_NONE) {
- adv = gmii_advertised(gmii);
- lpa = gmii_lpa(gmii);
- } else {
- lpa = GM_LPA_10000 | LPA_DUPLEX;
- adv = lpa;
- }
- EFX_INFO(efx, "link up at %dMbps %s-duplex "
- "(adv %04x lpa %04x) (MTU %d)%s\n",
- (efx->link_options & GM_LPA_10000 ? 10000 :
- (efx->link_options & GM_LPA_1000 ? 1000 :
- (efx->link_options & GM_LPA_100 ? 100 :
- 10))),
- (efx->link_options & GM_LPA_DUPLEX ?
- "full" : "half"),
- adv, lpa,
+ EFX_INFO(efx, "link up at %uMbps %s-duplex (MTU %d)%s\n",
+ efx->link_speed, efx->link_fd ? "full" : "half",
efx->net_dev->mtu,
(efx->promiscuous ? " [PROMISC]" : ""));
} else {
@@ -566,10 +573,28 @@ void __efx_reconfigure_port(struct efx_nic *efx)
netif_addr_unlock_bh(efx->net_dev);
}
- falcon_reconfigure_xmac(efx);
+ falcon_deconfigure_mac_wrapper(efx);
+
+ /* Reconfigure the PHY, disabling transmit in mac level loopback. */
+ if (LOOPBACK_INTERNAL(efx))
+ efx->phy_mode |= PHY_MODE_TX_DISABLED;
+ else
+ efx->phy_mode &= ~PHY_MODE_TX_DISABLED;
+ efx->phy_op->reconfigure(efx);
+
+ if (falcon_switch_mac(efx))
+ goto fail;
+
+ efx->mac_op->reconfigure(efx);
/* Inform kernel of loss/gain of carrier */
efx_link_status_changed(efx);
+ return;
+
+fail:
+ EFX_ERR(efx, "failed to reconfigure MAC\n");
+ efx->phy_op->fini(efx);
+ efx->port_initialized = false;
}
/* Reinitialise the MAC to pick up new PHY settings, even if the port is
@@ -586,10 +611,9 @@ void efx_reconfigure_port(struct efx_nic *efx)
/* Asynchronous efx_reconfigure_port work item. To speed up efx_flush_all()
* we don't efx_reconfigure_port() if the port is disabled. Care is taken
* in efx_stop_all() and efx_start_port() to prevent PHY events being lost */
-static void efx_reconfigure_work(struct work_struct *data)
+static void efx_phy_work(struct work_struct *data)
{
- struct efx_nic *efx = container_of(data, struct efx_nic,
- reconfigure_work);
+ struct efx_nic *efx = container_of(data, struct efx_nic, phy_work);
mutex_lock(&efx->mac_lock);
if (efx->port_enabled)
@@ -597,6 +621,16 @@ static void efx_reconfigure_work(struct work_struct *data)
mutex_unlock(&efx->mac_lock);
}
+static void efx_mac_work(struct work_struct *data)
+{
+ struct efx_nic *efx = container_of(data, struct efx_nic, mac_work);
+
+ mutex_lock(&efx->mac_lock);
+ if (efx->port_enabled)
+ efx->mac_op->irq(efx);
+ mutex_unlock(&efx->mac_lock);
+}
+
static int efx_probe_port(struct efx_nic *efx)
{
int rc;
@@ -608,21 +642,22 @@ static int efx_probe_port(struct efx_nic *efx)
if (rc)
goto err;
+ if (phy_flash_cfg)
+ efx->phy_mode = PHY_MODE_SPECIAL;
+
/* Sanity check MAC address */
if (is_valid_ether_addr(efx->mac_address)) {
memcpy(efx->net_dev->dev_addr, efx->mac_address, ETH_ALEN);
} else {
- DECLARE_MAC_BUF(mac);
-
- EFX_ERR(efx, "invalid MAC address %s\n",
- print_mac(mac, efx->mac_address));
+ EFX_ERR(efx, "invalid MAC address %pM\n",
+ efx->mac_address);
if (!allow_bad_hwaddr) {
rc = -EINVAL;
goto err;
}
random_ether_addr(efx->net_dev->dev_addr);
- EFX_INFO(efx, "using locally-generated MAC %s\n",
- print_mac(mac, efx->net_dev->dev_addr));
+ EFX_INFO(efx, "using locally-generated MAC %pM\n",
+ efx->net_dev->dev_addr);
}
return 0;
@@ -638,23 +673,30 @@ static int efx_init_port(struct efx_nic *efx)
EFX_LOG(efx, "init port\n");
- /* Initialise the MAC and PHY */
- rc = falcon_init_xmac(efx);
+ rc = efx->phy_op->init(efx);
if (rc)
return rc;
+ efx->phy_op->reconfigure(efx);
+
+ mutex_lock(&efx->mac_lock);
+ rc = falcon_switch_mac(efx);
+ mutex_unlock(&efx->mac_lock);
+ if (rc)
+ goto fail;
+ efx->mac_op->reconfigure(efx);
efx->port_initialized = true;
efx->stats_enabled = true;
-
- /* Reconfigure port to program MAC registers */
- falcon_reconfigure_xmac(efx);
-
return 0;
+
+fail:
+ efx->phy_op->fini(efx);
+ return rc;
}
/* Allow efx_reconfigure_port() to be scheduled, and close the window
* between efx_stop_port and efx_flush_all whereby a previously scheduled
- * efx_reconfigure_port() may have been cancelled */
+ * efx_phy_work()/efx_mac_work() may have been cancelled */
static void efx_start_port(struct efx_nic *efx)
{
EFX_LOG(efx, "start port\n");
@@ -663,13 +705,14 @@ static void efx_start_port(struct efx_nic *efx)
mutex_lock(&efx->mac_lock);
efx->port_enabled = true;
__efx_reconfigure_port(efx);
+ efx->mac_op->irq(efx);
mutex_unlock(&efx->mac_lock);
}
-/* Prevent efx_reconfigure_work and efx_monitor() from executing, and
- * efx_set_multicast_list() from scheduling efx_reconfigure_work.
- * efx_reconfigure_work can still be scheduled via NAPI processing
- * until efx_flush_all() is called */
+/* Prevent efx_phy_work, efx_mac_work, and efx_monitor() from executing,
+ * and efx_set_multicast_list() from scheduling efx_phy_work. efx_phy_work
+ * and efx_mac_work may still be scheduled via NAPI processing until
+ * efx_flush_all() is called */
static void efx_stop_port(struct efx_nic *efx)
{
EFX_LOG(efx, "stop port\n");
@@ -692,7 +735,7 @@ static void efx_fini_port(struct efx_nic *efx)
if (!efx->port_initialized)
return;
- falcon_fini_xmac(efx);
+ efx->phy_op->fini(efx);
efx->port_initialized = false;
efx->link_up = false;
@@ -840,26 +883,33 @@ static void efx_probe_interrupts(struct efx_nic *efx)
if (efx->interrupt_mode == EFX_INT_MODE_MSIX) {
struct msix_entry xentries[EFX_MAX_CHANNELS];
int wanted_ints;
+ int rx_queues;
/* We want one RX queue and interrupt per CPU package
* (or as specified by the rss_cpus module parameter).
* We will need one channel per interrupt.
*/
- wanted_ints = rss_cpus ? rss_cpus : efx_wanted_rx_queues();
- efx->n_rx_queues = min(wanted_ints, max_channels);
+ rx_queues = rss_cpus ? rss_cpus : efx_wanted_rx_queues();
+ wanted_ints = rx_queues + (separate_tx_channels ? 1 : 0);
+ wanted_ints = min(wanted_ints, max_channels);
- for (i = 0; i < efx->n_rx_queues; i++)
+ for (i = 0; i < wanted_ints; i++)
xentries[i].entry = i;
- rc = pci_enable_msix(efx->pci_dev, xentries, efx->n_rx_queues);
+ rc = pci_enable_msix(efx->pci_dev, xentries, wanted_ints);
if (rc > 0) {
- EFX_BUG_ON_PARANOID(rc >= efx->n_rx_queues);
- efx->n_rx_queues = rc;
+ EFX_ERR(efx, "WARNING: Insufficient MSI-X vectors"
+ " available (%d < %d).\n", rc, wanted_ints);
+ EFX_ERR(efx, "WARNING: Performance may be reduced.\n");
+ EFX_BUG_ON_PARANOID(rc >= wanted_ints);
+ wanted_ints = rc;
rc = pci_enable_msix(efx->pci_dev, xentries,
- efx->n_rx_queues);
+ wanted_ints);
}
if (rc == 0) {
- for (i = 0; i < efx->n_rx_queues; i++)
+ efx->n_rx_queues = min(rx_queues, wanted_ints);
+ efx->n_channels = wanted_ints;
+ for (i = 0; i < wanted_ints; i++)
efx->channel[i].irq = xentries[i].vector;
} else {
/* Fall back to single channel MSI */
@@ -871,6 +921,7 @@ static void efx_probe_interrupts(struct efx_nic *efx)
/* Try single interrupt MSI */
if (efx->interrupt_mode == EFX_INT_MODE_MSI) {
efx->n_rx_queues = 1;
+ efx->n_channels = 1;
rc = pci_enable_msi(efx->pci_dev);
if (rc == 0) {
efx->channel[0].irq = efx->pci_dev->irq;
@@ -883,6 +934,7 @@ static void efx_probe_interrupts(struct efx_nic *efx)
/* Assume legacy interrupts */
if (efx->interrupt_mode == EFX_INT_MODE_LEGACY) {
efx->n_rx_queues = 1;
+ efx->n_channels = 1 + (separate_tx_channels ? 1 : 0);
efx->legacy_irq = efx->pci_dev->irq;
}
}
@@ -907,8 +959,8 @@ static void efx_set_channels(struct efx_nic *efx)
struct efx_rx_queue *rx_queue;
efx_for_each_tx_queue(tx_queue, efx) {
- if (!EFX_INT_MODE_USE_MSI(efx) && separate_tx_and_rx_channels)
- tx_queue->channel = &efx->channel[1];
+ if (separate_tx_channels)
+ tx_queue->channel = &efx->channel[efx->n_channels-1];
else
tx_queue->channel = &efx->channel[0];
tx_queue->channel->used_flags |= EFX_USED_BY_TX;
@@ -985,6 +1037,7 @@ static int efx_probe_all(struct efx_nic *efx)
goto fail3;
}
}
+ efx_set_channel_names(efx);
return 0;
@@ -1050,7 +1103,8 @@ static void efx_flush_all(struct efx_nic *efx)
cancel_delayed_work_sync(&rx_queue->work);
/* Stop scheduled port reconfigurations */
- cancel_work_sync(&efx->reconfigure_work);
+ cancel_work_sync(&efx->mac_work);
+ cancel_work_sync(&efx->phy_work);
}
@@ -1087,7 +1141,7 @@ static void efx_stop_all(struct efx_nic *efx)
* window to loose phy events */
efx_stop_port(efx);
- /* Flush reconfigure_work, refill_workqueue, monitor_work */
+ /* Flush efx_phy_work, efx_mac_work, refill_workqueue, monitor_work */
efx_flush_all(efx);
/* Isolate the MAC from the TX and RX engines, so that queue
@@ -1159,36 +1213,31 @@ static void efx_monitor(struct work_struct *data)
{
struct efx_nic *efx = container_of(data, struct efx_nic,
monitor_work.work);
- int rc = 0;
+ int rc;
EFX_TRACE(efx, "hardware monitor executing on CPU %d\n",
raw_smp_processor_id());
-
/* If the mac_lock is already held then it is likely a port
* reconfiguration is already in place, which will likely do
* most of the work of check_hw() anyway. */
- if (!mutex_trylock(&efx->mac_lock)) {
- queue_delayed_work(efx->workqueue, &efx->monitor_work,
- efx_monitor_interval);
- return;
- }
-
- if (efx->port_enabled)
- rc = falcon_check_xmac(efx);
- mutex_unlock(&efx->mac_lock);
-
+ if (!mutex_trylock(&efx->mac_lock))
+ goto out_requeue;
+ if (!efx->port_enabled)
+ goto out_unlock;
+ rc = efx->board_info.monitor(efx);
if (rc) {
- if (monitor_reset) {
- EFX_ERR(efx, "hardware monitor detected a fault: "
- "triggering reset\n");
- efx_schedule_reset(efx, RESET_TYPE_MONITOR);
- } else {
- EFX_ERR(efx, "hardware monitor detected a fault, "
- "skipping reset\n");
- }
+ EFX_ERR(efx, "Board sensor %s; shutting down PHY\n",
+ (rc == -ERANGE) ? "reported fault" : "failed");
+ efx->phy_mode |= PHY_MODE_LOW_POWER;
+ falcon_sim_phy_event(efx);
}
+ efx->phy_op->poll(efx);
+ efx->mac_op->poll(efx);
+out_unlock:
+ mutex_unlock(&efx->mac_lock);
+out_requeue:
queue_delayed_work(efx->workqueue, &efx->monitor_work,
efx_monitor_interval);
}
@@ -1282,6 +1331,8 @@ static int efx_net_open(struct net_device *net_dev)
EFX_LOG(efx, "opening device %s on CPU %d\n", net_dev->name,
raw_smp_processor_id());
+ if (efx->state == STATE_DISABLED)
+ return -EIO;
if (efx->phy_mode & PHY_MODE_SPECIAL)
return -EBUSY;
@@ -1300,10 +1351,12 @@ static int efx_net_stop(struct net_device *net_dev)
EFX_LOG(efx, "closing %s on CPU %d\n", net_dev->name,
raw_smp_processor_id());
- /* Stop the device and flush all the channels */
- efx_stop_all(efx);
- efx_fini_channels(efx);
- efx_init_channels(efx);
+ if (efx->state != STATE_DISABLED) {
+ /* Stop the device and flush all the channels */
+ efx_stop_all(efx);
+ efx_fini_channels(efx);
+ efx_init_channels(efx);
+ }
return 0;
}
@@ -1322,7 +1375,7 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
if (!spin_trylock(&efx->stats_lock))
return stats;
if (efx->stats_enabled) {
- falcon_update_stats_xmac(efx);
+ efx->mac_op->update_stats(efx);
falcon_update_nic_stats(efx);
}
spin_unlock(&efx->stats_lock);
@@ -1360,12 +1413,11 @@ static void efx_watchdog(struct net_device *net_dev)
{
struct efx_nic *efx = netdev_priv(net_dev);
- EFX_ERR(efx, "TX stuck with stop_count=%d port_enabled=%d: %s\n",
- atomic_read(&efx->netif_stop_count), efx->port_enabled,
- monitor_reset ? "resetting channels" : "skipping reset");
+ EFX_ERR(efx, "TX stuck with stop_count=%d port_enabled=%d:"
+ " resetting channels\n",
+ atomic_read(&efx->netif_stop_count), efx->port_enabled);
- if (monitor_reset)
- efx_schedule_reset(efx, RESET_TYPE_MONITOR);
+ efx_schedule_reset(efx, RESET_TYPE_TX_WATCHDOG);
}
@@ -1401,9 +1453,8 @@ static int efx_set_mac_address(struct net_device *net_dev, void *data)
EFX_ASSERT_RESET_SERIALISED(efx);
if (!is_valid_ether_addr(new_addr)) {
- DECLARE_MAC_BUF(mac);
- EFX_ERR(efx, "invalid ethernet MAC address requested: %s\n",
- print_mac(mac, new_addr));
+ EFX_ERR(efx, "invalid ethernet MAC address requested: %pM\n",
+ new_addr);
return -EINVAL;
}
@@ -1447,22 +1498,43 @@ static void efx_set_multicast_list(struct net_device *net_dev)
return;
if (changed)
- queue_work(efx->workqueue, &efx->reconfigure_work);
+ queue_work(efx->workqueue, &efx->phy_work);
/* Create and activate new global multicast hash table */
falcon_set_multicast_hash(efx);
}
+static const struct net_device_ops efx_netdev_ops = {
+ .ndo_open = efx_net_open,
+ .ndo_stop = efx_net_stop,
+ .ndo_get_stats = efx_net_stats,
+ .ndo_tx_timeout = efx_watchdog,
+ .ndo_start_xmit = efx_hard_start_xmit,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_do_ioctl = efx_ioctl,
+ .ndo_change_mtu = efx_change_mtu,
+ .ndo_set_mac_address = efx_set_mac_address,
+ .ndo_set_multicast_list = efx_set_multicast_list,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = efx_netpoll,
+#endif
+};
+
+static void efx_update_name(struct efx_nic *efx)
+{
+ strcpy(efx->name, efx->net_dev->name);
+ efx_mtd_rename(efx);
+ efx_set_channel_names(efx);
+}
+
static int efx_netdev_event(struct notifier_block *this,
unsigned long event, void *ptr)
{
struct net_device *net_dev = ptr;
- if (net_dev->open == efx_net_open && event == NETDEV_CHANGENAME) {
- struct efx_nic *efx = netdev_priv(net_dev);
-
- strcpy(efx->name, net_dev->name);
- }
+ if (net_dev->netdev_ops == &efx_netdev_ops &&
+ event == NETDEV_CHANGENAME)
+ efx_update_name(netdev_priv(net_dev));
return NOTIFY_DONE;
}
@@ -1471,6 +1543,14 @@ static struct notifier_block efx_netdev_notifier = {
.notifier_call = efx_netdev_event,
};
+static ssize_t
+show_phy_type(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
+ return sprintf(buf, "%d\n", efx->phy_type);
+}
+static DEVICE_ATTR(phy_type, 0644, show_phy_type, NULL);
+
static int efx_register_netdev(struct efx_nic *efx)
{
struct net_device *net_dev = efx->net_dev;
@@ -1478,18 +1558,7 @@ static int efx_register_netdev(struct efx_nic *efx)
net_dev->watchdog_timeo = 5 * HZ;
net_dev->irq = efx->pci_dev->irq;
- net_dev->open = efx_net_open;
- net_dev->stop = efx_net_stop;
- net_dev->get_stats = efx_net_stats;
- net_dev->tx_timeout = &efx_watchdog;
- net_dev->hard_start_xmit = efx_hard_start_xmit;
- net_dev->do_ioctl = efx_ioctl;
- net_dev->change_mtu = efx_change_mtu;
- net_dev->set_mac_address = efx_set_mac_address;
- net_dev->set_multicast_list = efx_set_multicast_list;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- net_dev->poll_controller = efx_netpoll;
-#endif
+ net_dev->netdev_ops = &efx_netdev_ops;
SET_NETDEV_DEV(net_dev, &efx->pci_dev->dev);
SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops);
@@ -1497,7 +1566,7 @@ static int efx_register_netdev(struct efx_nic *efx)
netif_carrier_off(efx->net_dev);
/* Clear MAC statistics */
- falcon_update_stats_xmac(efx);
+ efx->mac_op->update_stats(efx);
memset(&efx->mac_stats, 0, sizeof(efx->mac_stats));
rc = register_netdev(net_dev);
@@ -1505,9 +1574,22 @@ static int efx_register_netdev(struct efx_nic *efx)
EFX_ERR(efx, "could not register net dev\n");
return rc;
}
- strcpy(efx->name, net_dev->name);
+
+ rtnl_lock();
+ efx_update_name(efx);
+ rtnl_unlock();
+
+ rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_type);
+ if (rc) {
+ EFX_ERR(efx, "failed to init net dev attributes\n");
+ goto fail_registered;
+ }
return 0;
+
+fail_registered:
+ unregister_netdev(net_dev);
+ return rc;
}
static void efx_unregister_netdev(struct efx_nic *efx)
@@ -1527,6 +1609,7 @@ static void efx_unregister_netdev(struct efx_nic *efx)
if (efx_dev_registered(efx)) {
strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
+ device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type);
unregister_netdev(efx->net_dev);
}
}
@@ -1541,8 +1624,6 @@ static void efx_unregister_netdev(struct efx_nic *efx)
* before reset. */
void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
{
- int rc;
-
EFX_ASSERT_RESET_SERIALISED(efx);
/* The net_dev->get_stats handler is quite slow, and will fail
@@ -1553,10 +1634,9 @@ void efx_reset_down(struct efx_nic *efx, struct ethtool_cmd *ecmd)
efx_stop_all(efx);
mutex_lock(&efx->mac_lock);
+ mutex_lock(&efx->spi_lock);
- rc = falcon_xmac_get_settings(efx, ecmd);
- if (rc)
- EFX_ERR(efx, "could not back up PHY settings\n");
+ efx->phy_op->get_settings(efx, ecmd);
efx_fini_channels(efx);
}
@@ -1581,10 +1661,11 @@ int efx_reset_up(struct efx_nic *efx, struct ethtool_cmd *ecmd, bool ok)
if (ok) {
efx_init_channels(efx);
- if (falcon_xmac_set_settings(efx, ecmd))
+ if (efx->phy_op->set_settings(efx, ecmd))
EFX_ERR(efx, "could not restore PHY settings\n");
}
+ mutex_unlock(&efx->spi_lock);
mutex_unlock(&efx->mac_lock);
if (ok) {
@@ -1607,7 +1688,7 @@ static int efx_reset(struct efx_nic *efx)
{
struct ethtool_cmd ecmd;
enum reset_type method = efx->reset_pending;
- int rc;
+ int rc = 0;
/* Serialise with kernel interfaces */
rtnl_lock();
@@ -1616,7 +1697,7 @@ static int efx_reset(struct efx_nic *efx)
* flag set so that efx_pci_probe_main will be retried */
if (efx->state != STATE_RUNNING) {
EFX_INFO(efx, "scheduled reset quenched. NIC not RUNNING\n");
- goto unlock_rtnl;
+ goto out_unlock;
}
EFX_INFO(efx, "resetting (%d)\n", method);
@@ -1626,7 +1707,7 @@ static int efx_reset(struct efx_nic *efx)
rc = falcon_reset_hw(efx, method);
if (rc) {
EFX_ERR(efx, "failed to reset hardware\n");
- goto fail;
+ goto out_disable;
}
/* Allow resets to be rescheduled. */
@@ -1640,28 +1721,23 @@ static int efx_reset(struct efx_nic *efx)
/* Leave device stopped if necessary */
if (method == RESET_TYPE_DISABLE) {
+ efx_reset_up(efx, &ecmd, false);
rc = -EIO;
- goto fail;
+ } else {
+ rc = efx_reset_up(efx, &ecmd, true);
}
- rc = efx_reset_up(efx, &ecmd, true);
- if (rc)
- goto disable;
-
- EFX_LOG(efx, "reset complete\n");
- unlock_rtnl:
- rtnl_unlock();
- return 0;
-
- fail:
- efx_reset_up(efx, &ecmd, false);
- disable:
- EFX_ERR(efx, "has been disabled\n");
- efx->state = STATE_DISABLED;
+out_disable:
+ if (rc) {
+ EFX_ERR(efx, "has been disabled\n");
+ efx->state = STATE_DISABLED;
+ dev_close(efx->net_dev);
+ } else {
+ EFX_LOG(efx, "reset complete\n");
+ }
+out_unlock:
rtnl_unlock();
- efx_unregister_netdev(efx);
- efx_fini_port(efx);
return rc;
}
@@ -1709,7 +1785,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
efx->reset_pending = method;
- queue_work(efx->reset_workqueue, &efx->reset_work);
+ queue_work(reset_workqueue, &efx->reset_work);
}
/**************************************************************************
@@ -1743,10 +1819,16 @@ int efx_port_dummy_op_int(struct efx_nic *efx)
void efx_port_dummy_op_void(struct efx_nic *efx) {}
void efx_port_dummy_op_blink(struct efx_nic *efx, bool blink) {}
+static struct efx_mac_operations efx_dummy_mac_operations = {
+ .reconfigure = efx_port_dummy_op_void,
+ .poll = efx_port_dummy_op_void,
+ .irq = efx_port_dummy_op_void,
+};
+
static struct efx_phy_operations efx_dummy_phy_operations = {
.init = efx_port_dummy_op_int,
.reconfigure = efx_port_dummy_op_void,
- .check_hw = efx_port_dummy_op_int,
+ .poll = efx_port_dummy_op_void,
.fini = efx_port_dummy_op_void,
.clear_interrupt = efx_port_dummy_op_void,
};
@@ -1755,6 +1837,7 @@ static struct efx_board efx_dummy_board_info = {
.init = efx_port_dummy_op_int,
.init_leds = efx_port_dummy_op_int,
.set_fault_led = efx_port_dummy_op_blink,
+ .monitor = efx_port_dummy_op_int,
.blink = efx_port_dummy_op_blink,
.fini = efx_port_dummy_op_void,
};
@@ -1774,12 +1857,13 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
struct efx_channel *channel;
struct efx_tx_queue *tx_queue;
struct efx_rx_queue *rx_queue;
- int i, rc;
+ int i;
/* Initialise common structures */
memset(efx, 0, sizeof(*efx));
spin_lock_init(&efx->biu_lock);
spin_lock_init(&efx->phy_lock);
+ mutex_init(&efx->spi_lock);
INIT_WORK(&efx->reset_work, efx_reset_work);
INIT_DELAYED_WORK(&efx->monitor_work, efx_monitor);
efx->pci_dev = pci_dev;
@@ -1793,9 +1877,11 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
spin_lock_init(&efx->netif_stop_lock);
spin_lock_init(&efx->stats_lock);
mutex_init(&efx->mac_lock);
+ efx->mac_op = &efx_dummy_mac_operations;
efx->phy_op = &efx_dummy_phy_operations;
efx->mii.dev = net_dev;
- INIT_WORK(&efx->reconfigure_work, efx_reconfigure_work);
+ INIT_WORK(&efx->phy_work, efx_phy_work);
+ INIT_WORK(&efx->mac_work, efx_mac_work);
atomic_set(&efx->netif_stop_count, 1);
for (i = 0; i < EFX_MAX_CHANNELS; i++) {
@@ -1841,34 +1927,18 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
efx->interrupt_mode = max(efx->type->max_interrupt_mode,
interrupt_mode);
- efx->workqueue = create_singlethread_workqueue("sfc_work");
- if (!efx->workqueue) {
- rc = -ENOMEM;
- goto fail1;
- }
-
- efx->reset_workqueue = create_singlethread_workqueue("sfc_reset");
- if (!efx->reset_workqueue) {
- rc = -ENOMEM;
- goto fail2;
- }
+ /* Would be good to use the net_dev name, but we're too early */
+ snprintf(efx->workqueue_name, sizeof(efx->workqueue_name), "sfc%s",
+ pci_name(pci_dev));
+ efx->workqueue = create_singlethread_workqueue(efx->workqueue_name);
+ if (!efx->workqueue)
+ return -ENOMEM;
return 0;
-
- fail2:
- destroy_workqueue(efx->workqueue);
- efx->workqueue = NULL;
-
- fail1:
- return rc;
}
static void efx_fini_struct(struct efx_nic *efx)
{
- if (efx->reset_workqueue) {
- destroy_workqueue(efx->reset_workqueue);
- efx->reset_workqueue = NULL;
- }
if (efx->workqueue) {
destroy_workqueue(efx->workqueue);
efx->workqueue = NULL;
@@ -1927,11 +1997,13 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
efx_unregister_netdev(efx);
+ efx_mtd_remove(efx);
+
/* Wait for any scheduled resets to complete. No more will be
* scheduled from this point because efx_stop_all() has been
* called, we are no longer registered with driverlink, and
* the net_device's have been removed. */
- flush_workqueue(efx->reset_workqueue);
+ cancel_work_sync(&efx->reset_work);
efx_pci_remove_main(efx);
@@ -1992,6 +2064,7 @@ static int efx_pci_probe_main(struct efx_nic *efx)
efx_fini_port(efx);
fail5:
fail4:
+ efx->board_info.fini(efx);
fail3:
efx_fini_napi(efx);
fail2:
@@ -2045,14 +2118,23 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
* we're in STATE_INIT. */
for (i = 0; i < 5; i++) {
rc = efx_pci_probe_main(efx);
- if (rc == 0)
- break;
/* Serialise against efx_reset(). No more resets will be
* scheduled since efx_stop_all() has been called, and we
* have not and never have been registered with either
* the rtnetlink or driverlink layers. */
- flush_workqueue(efx->reset_workqueue);
+ cancel_work_sync(&efx->reset_work);
+
+ if (rc == 0) {
+ if (efx->reset_pending != RESET_TYPE_NONE) {
+ /* If there was a scheduled reset during
+ * probe, the NIC is probably hosed anyway */
+ efx_pci_remove_main(efx);
+ rc = -EIO;
+ } else {
+ break;
+ }
+ }
/* Retry if a recoverably reset event has been scheduled */
if ((efx->reset_pending != RESET_TYPE_INVISIBLE) &&
@@ -2070,16 +2152,15 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
/* Switch to the running state before we expose the device to
* the OS. This is to ensure that the initial gathering of
* MAC stats succeeds. */
- rtnl_lock();
efx->state = STATE_RUNNING;
- rtnl_unlock();
+
+ efx_mtd_probe(efx); /* allowed to fail */
rc = efx_register_netdev(efx);
if (rc)
goto fail5;
EFX_LOG(efx, "initialisation successful\n");
-
return 0;
fail5:
@@ -2127,6 +2208,11 @@ static int __init efx_init_module(void)
rc = -ENOMEM;
goto err_refill;
}
+ reset_workqueue = create_singlethread_workqueue("sfc_reset");
+ if (!reset_workqueue) {
+ rc = -ENOMEM;
+ goto err_reset;
+ }
rc = pci_register_driver(&efx_pci_driver);
if (rc < 0)
@@ -2135,6 +2221,8 @@ static int __init efx_init_module(void)
return 0;
err_pci:
+ destroy_workqueue(reset_workqueue);
+ err_reset:
destroy_workqueue(refill_workqueue);
err_refill:
unregister_netdevice_notifier(&efx_netdev_notifier);
@@ -2147,6 +2235,7 @@ static void __exit efx_exit_module(void)
printk(KERN_INFO "Solarflare NET driver unloading\n");
pci_unregister_driver(&efx_pci_driver);
+ destroy_workqueue(reset_workqueue);
destroy_workqueue(refill_workqueue);
unregister_netdevice_notifier(&efx_netdev_notifier);
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h
index d02937b70eee..0dd7a532c78a 100644
--- a/drivers/net/sfc/efx.h
+++ b/drivers/net/sfc/efx.h
@@ -58,6 +58,16 @@ extern int efx_port_dummy_op_int(struct efx_nic *efx);
extern void efx_port_dummy_op_void(struct efx_nic *efx);
extern void efx_port_dummy_op_blink(struct efx_nic *efx, bool blink);
+/* MTD */
+#ifdef CONFIG_SFC_MTD
+extern int efx_mtd_probe(struct efx_nic *efx);
+extern void efx_mtd_rename(struct efx_nic *efx);
+extern void efx_mtd_remove(struct efx_nic *efx);
+#else
+static inline int efx_mtd_probe(struct efx_nic *efx) { return 0; }
+static inline void efx_mtd_rename(struct efx_nic *efx) {}
+static inline void efx_mtd_remove(struct efx_nic *efx) {}
+#endif
extern unsigned int efx_monitor_interval;
@@ -67,7 +77,7 @@ static inline void efx_schedule_channel(struct efx_channel *channel)
channel->channel, raw_smp_processor_id());
channel->work_pending = true;
- netif_rx_schedule(channel->napi_dev, &channel->napi_str);
+ netif_rx_schedule(&channel->napi_str);
}
#endif /* EFX_EFX_H */
diff --git a/drivers/net/sfc/enum.h b/drivers/net/sfc/enum.h
index cec15dbb88e4..60cbc6e1e66b 100644
--- a/drivers/net/sfc/enum.h
+++ b/drivers/net/sfc/enum.h
@@ -1,6 +1,6 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2007 Solarflare Communications Inc.
+ * Copyright 2007-2008 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@@ -13,22 +13,24 @@
/**
* enum efx_loopback_mode - loopback modes
* @LOOPBACK_NONE: no loopback
- * @LOOPBACK_XGMII: loopback within MAC at XGMII level
- * @LOOPBACK_XGXS: loopback within MAC at XGXS level
- * @LOOPBACK_XAUI: loopback within MAC at XAUI level
- * @LOOPBACK_PHYXS: loopback within PHY at PHYXS level
- * @LOOPBACK_PCS: loopback within PHY at PCS level
- * @LOOPBACK_PMAPMD: loopback within PHY at PMAPMD level
+ * @LOOPBACK_GMAC: loopback within GMAC at unspecified level
+ * @LOOPBACK_XGMII: loopback within XMAC at XGMII level
+ * @LOOPBACK_XGXS: loopback within XMAC at XGXS level
+ * @LOOPBACK_XAUI: loopback within XMAC at XAUI level
+ * @LOOPBACK_GPHY: loopback within 1G PHY at unspecified level
+ * @LOOPBACK_PHYXS: loopback within 10G PHY at PHYXS level
+ * @LOOPBACK_PCS: loopback within 10G PHY at PCS level
+ * @LOOPBACK_PMAPMD: loopback within 10G PHY at PMAPMD level
* @LOOPBACK_NETWORK: reflecting loopback (even further than furthest!)
*/
/* Please keep in order and up-to-date w.r.t the following two #defines */
enum efx_loopback_mode {
LOOPBACK_NONE = 0,
- LOOPBACK_MAC = 1,
+ LOOPBACK_GMAC = 1,
LOOPBACK_XGMII = 2,
LOOPBACK_XGXS = 3,
LOOPBACK_XAUI = 4,
- LOOPBACK_PHY = 5,
+ LOOPBACK_GPHY = 5,
LOOPBACK_PHYXS = 6,
LOOPBACK_PCS = 7,
LOOPBACK_PMAPMD = 8,
@@ -45,15 +47,19 @@ extern const char *efx_loopback_mode_names[];
LOOPBACK_MODE_NAME(efx->loopback_mode)
/* These loopbacks occur within the controller */
-#define LOOPBACKS_10G_INTERNAL ((1 << LOOPBACK_XGMII)| \
- (1 << LOOPBACK_XGXS) | \
- (1 << LOOPBACK_XAUI))
+#define LOOPBACKS_INTERNAL ((1 << LOOPBACK_GMAC) | \
+ (1 << LOOPBACK_XGMII)| \
+ (1 << LOOPBACK_XGXS) | \
+ (1 << LOOPBACK_XAUI))
#define LOOPBACK_MASK(_efx) \
(1 << (_efx)->loopback_mode)
#define LOOPBACK_INTERNAL(_efx) \
- (!!(LOOPBACKS_10G_INTERNAL & LOOPBACK_MASK(_efx)))
+ (!!(LOOPBACKS_INTERNAL & LOOPBACK_MASK(_efx)))
+
+#define LOOPBACK_CHANGED(_from, _to, _mask) \
+ (!!((LOOPBACK_MASK(_from) ^ LOOPBACK_MASK(_to)) & (_mask)))
#define LOOPBACK_OUT_OF(_from, _to, _mask) \
((LOOPBACK_MASK(_from) & (_mask)) && !(LOOPBACK_MASK(_to) & (_mask)))
@@ -72,7 +78,7 @@ extern const char *efx_loopback_mode_names[];
* @RESET_TYPE_ALL: reset everything but PCI core blocks
* @RESET_TYPE_WORLD: reset everything, save & restore PCI config
* @RESET_TYPE_DISABLE: disable NIC
- * @RESET_TYPE_MONITOR: reset due to hardware monitor
+ * @RESET_TYPE_TX_WATCHDOG: reset due to TX watchdog
* @RESET_TYPE_INT_ERROR: reset due to internal error
* @RESET_TYPE_RX_RECOVERY: reset to recover from RX datapath errors
* @RESET_TYPE_RX_DESC_FETCH: pcie error during rx descriptor fetch
@@ -86,7 +92,7 @@ enum reset_type {
RESET_TYPE_WORLD = 2,
RESET_TYPE_DISABLE = 3,
RESET_TYPE_MAX_METHOD,
- RESET_TYPE_MONITOR,
+ RESET_TYPE_TX_WATCHDOG,
RESET_TYPE_INT_ERROR,
RESET_TYPE_RX_RECOVERY,
RESET_TYPE_RX_DESC_FETCH,
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index cd0d0873d978..53d259e90187 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -12,24 +12,24 @@
#include <linux/ethtool.h>
#include <linux/rtnetlink.h>
#include "net_driver.h"
+#include "workarounds.h"
#include "selftest.h"
#include "efx.h"
#include "ethtool.h"
#include "falcon.h"
-#include "gmii.h"
#include "spi.h"
-#include "mac.h"
+#include "mdio_10g.h"
const char *efx_loopback_mode_names[] = {
[LOOPBACK_NONE] = "NONE",
- [LOOPBACK_MAC] = "MAC",
+ [LOOPBACK_GMAC] = "GMAC",
[LOOPBACK_XGMII] = "XGMII",
[LOOPBACK_XGXS] = "XGXS",
[LOOPBACK_XAUI] = "XAUI",
- [LOOPBACK_PHY] = "PHY",
- [LOOPBACK_PHYXS] = "PHY(XS)",
- [LOOPBACK_PCS] = "PHY(PCS)",
- [LOOPBACK_PMAPMD] = "PHY(PMAPMD)",
+ [LOOPBACK_GPHY] = "GPHY",
+ [LOOPBACK_PHYXS] = "PHYXS",
+ [LOOPBACK_PCS] = "PCS",
+ [LOOPBACK_PMAPMD] = "PMA/PMD",
[LOOPBACK_NETWORK] = "NETWORK",
};
@@ -172,10 +172,7 @@ static struct efx_ethtool_stat efx_ethtool_stats[] = {
/* Number of ethtool statistics */
#define EFX_ETHTOOL_NUM_STATS ARRAY_SIZE(efx_ethtool_stats)
-/* EEPROM range with gPXE configuration */
#define EFX_ETHTOOL_EEPROM_MAGIC 0xEFAB
-#define EFX_ETHTOOL_EEPROM_MIN 0x800U
-#define EFX_ETHTOOL_EEPROM_MAX 0x1800U
/**************************************************************************
*
@@ -185,12 +182,16 @@ static struct efx_ethtool_stat efx_ethtool_stats[] = {
*/
/* Identify device by flashing LEDs */
-static int efx_ethtool_phys_id(struct net_device *net_dev, u32 seconds)
+static int efx_ethtool_phys_id(struct net_device *net_dev, u32 count)
{
struct efx_nic *efx = netdev_priv(net_dev);
efx->board_info.blink(efx, 1);
- schedule_timeout_interruptible(seconds * HZ);
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (count)
+ schedule_timeout(count * HZ);
+ else
+ schedule();
efx->board_info.blink(efx, 0);
return 0;
}
@@ -200,13 +201,15 @@ int efx_ethtool_get_settings(struct net_device *net_dev,
struct ethtool_cmd *ecmd)
{
struct efx_nic *efx = netdev_priv(net_dev);
- int rc;
mutex_lock(&efx->mac_lock);
- rc = falcon_xmac_get_settings(efx, ecmd);
+ efx->phy_op->get_settings(efx, ecmd);
mutex_unlock(&efx->mac_lock);
- return rc;
+ /* Falcon GMAC does not support 1000Mbps HD */
+ ecmd->supported &= ~SUPPORTED_1000baseT_Half;
+
+ return 0;
}
/* This must be called with rtnl_lock held. */
@@ -216,8 +219,18 @@ int efx_ethtool_set_settings(struct net_device *net_dev,
struct efx_nic *efx = netdev_priv(net_dev);
int rc;
+ if (EFX_WORKAROUND_13963(efx) && !ecmd->autoneg)
+ return -EINVAL;
+
+ /* Falcon GMAC does not support 1000Mbps HD */
+ if (ecmd->speed == SPEED_1000 && ecmd->duplex != DUPLEX_FULL) {
+ EFX_LOG(efx, "rejecting unsupported 1000Mbps HD"
+ " setting\n");
+ return -EINVAL;
+ }
+
mutex_lock(&efx->mac_lock);
- rc = falcon_xmac_set_settings(efx, ecmd);
+ rc = efx->phy_op->set_settings(efx, ecmd);
mutex_unlock(&efx->mac_lock);
if (!rc)
efx_reconfigure_port(efx);
@@ -241,10 +254,10 @@ static void efx_ethtool_get_drvinfo(struct net_device *net_dev,
* @strings: Ethtool strings, or %NULL
* @data: Ethtool test results, or %NULL
* @test: Pointer to test result (used only if data != %NULL)
- * @unit_format: Unit name format (e.g. "channel\%d")
- * @unit_id: Unit id (e.g. 0 for "channel0")
+ * @unit_format: Unit name format (e.g. "chan\%d")
+ * @unit_id: Unit id (e.g. 0 for "chan0")
* @test_format: Test name format (e.g. "loopback.\%s.tx.sent")
- * @test_id: Test id (e.g. "PHY" for "loopback.PHY.tx_sent")
+ * @test_id: Test id (e.g. "PHYXS" for "loopback.PHYXS.tx_sent")
*
* Fill in an individual self-test entry.
*/
@@ -261,18 +274,20 @@ static void efx_fill_test(unsigned int test_index,
/* Fill string, if applicable */
if (strings) {
- snprintf(unit_str.name, sizeof(unit_str.name),
- unit_format, unit_id);
+ if (strchr(unit_format, '%'))
+ snprintf(unit_str.name, sizeof(unit_str.name),
+ unit_format, unit_id);
+ else
+ strcpy(unit_str.name, unit_format);
snprintf(test_str.name, sizeof(test_str.name),
test_format, test_id);
snprintf(strings[test_index].name,
sizeof(strings[test_index].name),
- "%-9s%-17s", unit_str.name, test_str.name);
+ "%-6s %-24s", unit_str.name, test_str.name);
}
}
-#define EFX_PORT_NAME "port%d", 0
-#define EFX_CHANNEL_NAME(_channel) "channel%d", _channel->channel
+#define EFX_CHANNEL_NAME(_channel) "chan%d", _channel->channel
#define EFX_TX_QUEUE_NAME(_tx_queue) "txq%d", _tx_queue->queue
#define EFX_RX_QUEUE_NAME(_rx_queue) "rxq%d", _rx_queue->queue
#define EFX_LOOPBACK_NAME(_mode, _counter) \
@@ -307,11 +322,11 @@ static int efx_fill_loopback_test(struct efx_nic *efx,
}
efx_fill_test(test_index++, strings, data,
&lb_tests->rx_good,
- EFX_PORT_NAME,
+ "rx", 0,
EFX_LOOPBACK_NAME(mode, "rx_good"));
efx_fill_test(test_index++, strings, data,
&lb_tests->rx_bad,
- EFX_PORT_NAME,
+ "rx", 0,
EFX_LOOPBACK_NAME(mode, "rx_bad"));
return test_index;
@@ -330,7 +345,7 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
u64 *data)
{
struct efx_channel *channel;
- unsigned int n = 0;
+ unsigned int n = 0, i;
enum efx_loopback_mode mode;
efx_fill_test(n++, strings, data, &tests->mii,
@@ -358,14 +373,12 @@ static int efx_ethtool_fill_self_tests(struct efx_nic *efx,
efx_fill_test(n++, strings, data, &tests->registers,
"core", 0, "registers", NULL);
- efx_fill_test(n++, strings, data, &tests->phy,
- EFX_PORT_NAME, "phy", NULL);
+
+ for (i = 0; i < efx->phy_op->num_tests; i++)
+ efx_fill_test(n++, strings, data, &tests->phy[i],
+ "phy", 0, efx->phy_op->test_names[i], NULL);
/* Loopback tests */
- efx_fill_test(n++, strings, data, &tests->loopback_speed,
- EFX_PORT_NAME, "loopback.speed", NULL);
- efx_fill_test(n++, strings, data, &tests->loopback_full_duplex,
- EFX_PORT_NAME, "loopback.full_duplex", NULL);
for (mode = LOOPBACK_NONE; mode <= LOOPBACK_TEST_MAX; mode++) {
if (!(efx->loopback_modes & (1 << mode)))
continue;
@@ -429,7 +442,7 @@ static void efx_ethtool_get_stats(struct net_device *net_dev,
EFX_BUG_ON_PARANOID(stats->n_stats != EFX_ETHTOOL_NUM_STATS);
/* Update MAC and NIC statistics */
- net_dev->get_stats(net_dev);
+ dev_get_stats(net_dev);
/* Fill detailed statistics buffer */
for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) {
@@ -476,7 +489,7 @@ static void efx_ethtool_self_test(struct net_device *net_dev,
{
struct efx_nic *efx = netdev_priv(net_dev);
struct efx_self_tests efx_tests;
- int offline, already_up;
+ int already_up;
int rc;
ASSERT_RTNL();
@@ -496,24 +509,15 @@ static void efx_ethtool_self_test(struct net_device *net_dev,
}
memset(&efx_tests, 0, sizeof(efx_tests));
- offline = (test->flags & ETH_TEST_FL_OFFLINE);
-
- /* Perform online self tests first */
- rc = efx_online_test(efx, &efx_tests);
- if (rc)
- goto out;
- /* Perform offline tests only if online tests passed */
- if (offline)
- rc = efx_offline_test(efx, &efx_tests,
- efx->loopback_modes);
+ rc = efx_selftest(efx, &efx_tests, test->flags);
- out:
if (!already_up)
dev_close(efx->net_dev);
- EFX_LOG(efx, "%s all %sline self-tests\n",
- rc == 0 ? "passed" : "failed", offline ? "off" : "on");
+ EFX_LOG(efx, "%s %sline self-tests\n",
+ rc == 0 ? "passed" : "failed",
+ (test->flags & ETH_TEST_FL_OFFLINE) ? "off" : "on");
fail2:
fail1:
@@ -545,8 +549,8 @@ static int efx_ethtool_get_eeprom_len(struct net_device *net_dev)
if (!spi)
return 0;
- return min(spi->size, EFX_ETHTOOL_EEPROM_MAX) -
- min(spi->size, EFX_ETHTOOL_EEPROM_MIN);
+ return min(spi->size, EFX_EEPROM_BOOTCONFIG_END) -
+ min(spi->size, EFX_EEPROM_BOOTCONFIG_START);
}
static int efx_ethtool_get_eeprom(struct net_device *net_dev,
@@ -557,8 +561,13 @@ static int efx_ethtool_get_eeprom(struct net_device *net_dev,
size_t len;
int rc;
- rc = falcon_spi_read(spi, eeprom->offset + EFX_ETHTOOL_EEPROM_MIN,
+ rc = mutex_lock_interruptible(&efx->spi_lock);
+ if (rc)
+ return rc;
+ rc = falcon_spi_read(spi, eeprom->offset + EFX_EEPROM_BOOTCONFIG_START,
eeprom->len, &len, buf);
+ mutex_unlock(&efx->spi_lock);
+
eeprom->magic = EFX_ETHTOOL_EEPROM_MAGIC;
eeprom->len = len;
return rc;
@@ -575,8 +584,13 @@ static int efx_ethtool_set_eeprom(struct net_device *net_dev,
if (eeprom->magic != EFX_ETHTOOL_EEPROM_MAGIC)
return -EINVAL;
- rc = falcon_spi_write(spi, eeprom->offset + EFX_ETHTOOL_EEPROM_MIN,
+ rc = mutex_lock_interruptible(&efx->spi_lock);
+ if (rc)
+ return rc;
+ rc = falcon_spi_write(spi, eeprom->offset + EFX_EEPROM_BOOTCONFIG_START,
eeprom->len, &len, buf);
+ mutex_unlock(&efx->spi_lock);
+
eeprom->len = len;
return rc;
}
@@ -666,23 +680,52 @@ static int efx_ethtool_set_pauseparam(struct net_device *net_dev,
struct ethtool_pauseparam *pause)
{
struct efx_nic *efx = netdev_priv(net_dev);
- enum efx_fc_type flow_control = efx->flow_control;
- int rc;
+ enum efx_fc_type wanted_fc;
+ bool reset;
- flow_control &= ~(EFX_FC_RX | EFX_FC_TX | EFX_FC_AUTO);
- flow_control |= pause->rx_pause ? EFX_FC_RX : 0;
- flow_control |= pause->tx_pause ? EFX_FC_TX : 0;
- flow_control |= pause->autoneg ? EFX_FC_AUTO : 0;
+ wanted_fc = ((pause->rx_pause ? EFX_FC_RX : 0) |
+ (pause->tx_pause ? EFX_FC_TX : 0) |
+ (pause->autoneg ? EFX_FC_AUTO : 0));
+
+ if ((wanted_fc & EFX_FC_TX) && !(wanted_fc & EFX_FC_RX)) {
+ EFX_LOG(efx, "Flow control unsupported: tx ON rx OFF\n");
+ return -EINVAL;
+ }
+
+ if (!(efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) &&
+ (wanted_fc & EFX_FC_AUTO)) {
+ EFX_LOG(efx, "PHY does not support flow control "
+ "autonegotiation\n");
+ return -EINVAL;
+ }
+
+ /* TX flow control may automatically turn itself off if the
+ * link partner (intermittently) stops responding to pause
+ * frames. There isn't any indication that this has happened,
+ * so the best we do is leave it up to the user to spot this
+ * and fix it be cycling transmit flow control on this end. */
+ reset = (wanted_fc & EFX_FC_TX) && !(efx->wanted_fc & EFX_FC_TX);
+ if (EFX_WORKAROUND_11482(efx) && reset) {
+ if (falcon_rev(efx) >= FALCON_REV_B0) {
+ /* Recover by resetting the EM block */
+ if (efx->link_up)
+ falcon_drain_tx_fifo(efx);
+ } else {
+ /* Schedule a reset to recover */
+ efx_schedule_reset(efx, RESET_TYPE_INVISIBLE);
+ }
+ }
/* Try to push the pause parameters */
mutex_lock(&efx->mac_lock);
- rc = falcon_xmac_set_pause(efx, flow_control);
- mutex_unlock(&efx->mac_lock);
- if (!rc)
- efx_reconfigure_port(efx);
+ efx->wanted_fc = wanted_fc;
+ mdio_clause45_set_pause(efx);
+ __efx_reconfigure_port(efx);
- return rc;
+ mutex_unlock(&efx->mac_lock);
+
+ return 0;
}
static void efx_ethtool_get_pauseparam(struct net_device *net_dev,
@@ -690,9 +733,9 @@ static void efx_ethtool_get_pauseparam(struct net_device *net_dev,
{
struct efx_nic *efx = netdev_priv(net_dev);
- pause->rx_pause = !!(efx->flow_control & EFX_FC_RX);
- pause->tx_pause = !!(efx->flow_control & EFX_FC_TX);
- pause->autoneg = !!(efx->flow_control & EFX_FC_AUTO);
+ pause->rx_pause = !!(efx->wanted_fc & EFX_FC_RX);
+ pause->tx_pause = !!(efx->wanted_fc & EFX_FC_TX);
+ pause->autoneg = !!(efx->wanted_fc & EFX_FC_AUTO);
}
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 31ed1f49de00..6884dc8c1f82 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -15,11 +15,11 @@
#include <linux/seq_file.h>
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
+#include <linux/mii.h>
#include "net_driver.h"
#include "bitfield.h"
#include "efx.h"
#include "mac.h"
-#include "gmii.h"
#include "spi.h"
#include "falcon.h"
#include "falcon_hwdefs.h"
@@ -70,6 +70,20 @@ static int disable_dma_stats;
#define RX_DC_ENTRIES_ORDER 2
#define RX_DC_BASE 0x100000
+static const unsigned int
+/* "Large" EEPROM device: Atmel AT25640 or similar
+ * 8 KB, 16-bit address, 32 B write block */
+large_eeprom_type = ((13 << SPI_DEV_TYPE_SIZE_LBN)
+ | (2 << SPI_DEV_TYPE_ADDR_LEN_LBN)
+ | (5 << SPI_DEV_TYPE_BLOCK_SIZE_LBN)),
+/* Default flash device: Atmel AT25F1024
+ * 128 KB, 24-bit address, 32 KB erase block, 256 B write block */
+default_flash_type = ((17 << SPI_DEV_TYPE_SIZE_LBN)
+ | (3 << SPI_DEV_TYPE_ADDR_LEN_LBN)
+ | (0x52 << SPI_DEV_TYPE_ERASE_CMD_LBN)
+ | (15 << SPI_DEV_TYPE_ERASE_SIZE_LBN)
+ | (8 << SPI_DEV_TYPE_BLOCK_SIZE_LBN));
+
/* RX FIFO XOFF watermark
*
* When the amount of the RX FIFO increases used increases past this
@@ -770,15 +784,18 @@ static void falcon_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
rx_ev_buf_owner_id_err | rx_ev_eth_crc_err |
rx_ev_frm_trunc | rx_ev_ip_hdr_chksum_err);
- /* Count errors that are not in MAC stats. */
+ /* Count errors that are not in MAC stats. Ignore expected
+ * checksum errors during self-test. */
if (rx_ev_frm_trunc)
++rx_queue->channel->n_rx_frm_trunc;
else if (rx_ev_tobe_disc)
++rx_queue->channel->n_rx_tobe_disc;
- else if (rx_ev_ip_hdr_chksum_err)
- ++rx_queue->channel->n_rx_ip_hdr_chksum_err;
- else if (rx_ev_tcp_udp_chksum_err)
- ++rx_queue->channel->n_rx_tcp_udp_chksum_err;
+ else if (!efx->loopback_selftest) {
+ if (rx_ev_ip_hdr_chksum_err)
+ ++rx_queue->channel->n_rx_ip_hdr_chksum_err;
+ else if (rx_ev_tcp_udp_chksum_err)
+ ++rx_queue->channel->n_rx_tcp_udp_chksum_err;
+ }
if (rx_ev_ip_frag_err)
++rx_queue->channel->n_rx_ip_frag_err;
@@ -809,7 +826,7 @@ static void falcon_handle_rx_not_ok(struct efx_rx_queue *rx_queue,
#endif
if (unlikely(rx_ev_eth_crc_err && EFX_WORKAROUND_10750(efx) &&
- efx->phy_type == PHY_TYPE_10XPRESS))
+ efx->phy_type == PHY_TYPE_SFX7101))
tenxpress_crc_err(efx);
}
@@ -893,22 +910,20 @@ static void falcon_handle_global_event(struct efx_channel *channel,
efx_qword_t *event)
{
struct efx_nic *efx = channel->efx;
- bool is_phy_event = false, handled = false;
+ bool handled = false;
- /* Check for interrupt on either port. Some boards have a
- * single PHY wired to the interrupt line for port 1. */
if (EFX_QWORD_FIELD(*event, G_PHY0_INTR) ||
EFX_QWORD_FIELD(*event, G_PHY1_INTR) ||
- EFX_QWORD_FIELD(*event, XG_PHY_INTR))
- is_phy_event = true;
+ EFX_QWORD_FIELD(*event, XG_PHY_INTR) ||
+ EFX_QWORD_FIELD(*event, XFP_PHY_INTR)) {
+ efx->phy_op->clear_interrupt(efx);
+ queue_work(efx->workqueue, &efx->phy_work);
+ handled = true;
+ }
if ((falcon_rev(efx) >= FALCON_REV_B0) &&
- EFX_QWORD_FIELD(*event, XG_MNT_INTR_B0))
- is_phy_event = true;
-
- if (is_phy_event) {
- efx->phy_op->clear_interrupt(efx);
- queue_work(efx->workqueue, &efx->reconfigure_work);
+ EFX_QWORD_FIELD(*event, XG_MNT_INTR_B0)) {
+ queue_work(efx->workqueue, &efx->mac_work);
handled = true;
}
@@ -1151,6 +1166,19 @@ void falcon_generate_test_event(struct efx_channel *channel, unsigned int magic)
falcon_generate_event(channel, &test_event);
}
+void falcon_sim_phy_event(struct efx_nic *efx)
+{
+ efx_qword_t phy_event;
+
+ EFX_POPULATE_QWORD_1(phy_event, EV_CODE, GLOBAL_EV_DECODE);
+ if (EFX_IS10G(efx))
+ EFX_SET_OWORD_FIELD(phy_event, XG_PHY_INTR, 1);
+ else
+ EFX_SET_OWORD_FIELD(phy_event, G_PHY0_INTR, 1);
+
+ falcon_generate_event(&efx->channel[0], &phy_event);
+}
+
/**************************************************************************
*
* Flush handling
@@ -1560,7 +1588,7 @@ int falcon_init_interrupt(struct efx_nic *efx)
efx_for_each_channel(channel, efx) {
rc = request_irq(channel->irq, falcon_msi_interrupt,
IRQF_PROBE_SHARED, /* Not shared */
- efx->name, channel);
+ channel->name, channel);
if (rc) {
EFX_ERR(efx, "failed to hook IRQ %d\n", channel->irq);
goto fail2;
@@ -1605,32 +1633,45 @@ void falcon_fini_interrupt(struct efx_nic *efx)
**************************************************************************
*/
-#define FALCON_SPI_MAX_LEN ((unsigned) sizeof(efx_oword_t))
+#define FALCON_SPI_MAX_LEN sizeof(efx_oword_t)
+
+static int falcon_spi_poll(struct efx_nic *efx)
+{
+ efx_oword_t reg;
+ falcon_read(efx, &reg, EE_SPI_HCMD_REG_KER);
+ return EFX_OWORD_FIELD(reg, EE_SPI_HCMD_CMD_EN) ? -EBUSY : 0;
+}
/* Wait for SPI command completion */
static int falcon_spi_wait(struct efx_nic *efx)
{
- unsigned long timeout = jiffies + DIV_ROUND_UP(HZ, 10);
- efx_oword_t reg;
- bool cmd_en, timer_active;
+ /* Most commands will finish quickly, so we start polling at
+ * very short intervals. Sometimes the command may have to
+ * wait for VPD or expansion ROM access outside of our
+ * control, so we allow up to 100 ms. */
+ unsigned long timeout = jiffies + 1 + DIV_ROUND_UP(HZ, 10);
+ int i;
+
+ for (i = 0; i < 10; i++) {
+ if (!falcon_spi_poll(efx))
+ return 0;
+ udelay(10);
+ }
for (;;) {
- falcon_read(efx, &reg, EE_SPI_HCMD_REG_KER);
- cmd_en = EFX_OWORD_FIELD(reg, EE_SPI_HCMD_CMD_EN);
- timer_active = EFX_OWORD_FIELD(reg, EE_WR_TIMER_ACTIVE);
- if (!cmd_en && !timer_active)
+ if (!falcon_spi_poll(efx))
return 0;
if (time_after_eq(jiffies, timeout)) {
EFX_ERR(efx, "timed out waiting for SPI\n");
return -ETIMEDOUT;
}
- cpu_relax();
+ schedule_timeout_uninterruptible(1);
}
}
-static int falcon_spi_cmd(const struct efx_spi_device *spi,
- unsigned int command, int address,
- const void *in, void *out, unsigned int len)
+int falcon_spi_cmd(const struct efx_spi_device *spi,
+ unsigned int command, int address,
+ const void *in, void *out, size_t len)
{
struct efx_nic *efx = spi->efx;
bool addressed = (address >= 0);
@@ -1641,9 +1682,10 @@ static int falcon_spi_cmd(const struct efx_spi_device *spi,
/* Input validation */
if (len > FALCON_SPI_MAX_LEN)
return -EINVAL;
+ BUG_ON(!mutex_is_locked(&efx->spi_lock));
- /* Check SPI not currently being accessed */
- rc = falcon_spi_wait(efx);
+ /* Check that previous command is not still running */
+ rc = falcon_spi_poll(efx);
if (rc)
return rc;
@@ -1685,8 +1727,8 @@ static int falcon_spi_cmd(const struct efx_spi_device *spi,
return 0;
}
-static unsigned int
-falcon_spi_write_limit(const struct efx_spi_device *spi, unsigned int start)
+static size_t
+falcon_spi_write_limit(const struct efx_spi_device *spi, size_t start)
{
return min(FALCON_SPI_MAX_LEN,
(spi->block_size - (start & (spi->block_size - 1))));
@@ -1699,38 +1741,40 @@ efx_spi_munge_command(const struct efx_spi_device *spi,
return command | (((address >> 8) & spi->munge_address) << 3);
}
-
-static int falcon_spi_fast_wait(const struct efx_spi_device *spi)
+/* Wait up to 10 ms for buffered write completion */
+int falcon_spi_wait_write(const struct efx_spi_device *spi)
{
+ struct efx_nic *efx = spi->efx;
+ unsigned long timeout = jiffies + 1 + DIV_ROUND_UP(HZ, 100);
u8 status;
- int i, rc;
-
- /* Wait up to 1000us for flash/EEPROM to finish a fast operation. */
- for (i = 0; i < 50; i++) {
- udelay(20);
+ int rc;
+ for (;;) {
rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL,
&status, sizeof(status));
if (rc)
return rc;
if (!(status & SPI_STATUS_NRDY))
return 0;
+ if (time_after_eq(jiffies, timeout)) {
+ EFX_ERR(efx, "SPI write timeout on device %d"
+ " last status=0x%02x\n",
+ spi->device_id, status);
+ return -ETIMEDOUT;
+ }
+ schedule_timeout_uninterruptible(1);
}
- EFX_ERR(spi->efx,
- "timed out waiting for device %d last status=0x%02x\n",
- spi->device_id, status);
- return -ETIMEDOUT;
}
int falcon_spi_read(const struct efx_spi_device *spi, loff_t start,
size_t len, size_t *retlen, u8 *buffer)
{
- unsigned int command, block_len, pos = 0;
+ size_t block_len, pos = 0;
+ unsigned int command;
int rc = 0;
while (pos < len) {
- block_len = min((unsigned int)len - pos,
- FALCON_SPI_MAX_LEN);
+ block_len = min(len - pos, FALCON_SPI_MAX_LEN);
command = efx_spi_munge_command(spi, SPI_READ, start + pos);
rc = falcon_spi_cmd(spi, command, start + pos, NULL,
@@ -1756,7 +1800,8 @@ int falcon_spi_write(const struct efx_spi_device *spi, loff_t start,
size_t len, size_t *retlen, const u8 *buffer)
{
u8 verify_buffer[FALCON_SPI_MAX_LEN];
- unsigned int command, block_len, pos = 0;
+ size_t block_len, pos = 0;
+ unsigned int command;
int rc = 0;
while (pos < len) {
@@ -1764,7 +1809,7 @@ int falcon_spi_write(const struct efx_spi_device *spi, loff_t start,
if (rc)
break;
- block_len = min((unsigned int)len - pos,
+ block_len = min(len - pos,
falcon_spi_write_limit(spi, start + pos));
command = efx_spi_munge_command(spi, SPI_WRITE, start + pos);
rc = falcon_spi_cmd(spi, command, start + pos,
@@ -1772,7 +1817,7 @@ int falcon_spi_write(const struct efx_spi_device *spi, loff_t start,
if (rc)
break;
- rc = falcon_spi_fast_wait(spi);
+ rc = falcon_spi_wait_write(spi);
if (rc)
break;
@@ -1805,40 +1850,61 @@ int falcon_spi_write(const struct efx_spi_device *spi, loff_t start,
*
**************************************************************************
*/
-void falcon_drain_tx_fifo(struct efx_nic *efx)
+
+static int falcon_reset_macs(struct efx_nic *efx)
{
- efx_oword_t temp;
+ efx_oword_t reg;
int count;
- if ((falcon_rev(efx) < FALCON_REV_B0) ||
- (efx->loopback_mode != LOOPBACK_NONE))
- return;
+ if (falcon_rev(efx) < FALCON_REV_B0) {
+ /* It's not safe to use GLB_CTL_REG to reset the
+ * macs, so instead use the internal MAC resets
+ */
+ if (!EFX_IS10G(efx)) {
+ EFX_POPULATE_OWORD_1(reg, GM_SW_RST, 1);
+ falcon_write(efx, &reg, GM_CFG1_REG);
+ udelay(1000);
+
+ EFX_POPULATE_OWORD_1(reg, GM_SW_RST, 0);
+ falcon_write(efx, &reg, GM_CFG1_REG);
+ udelay(1000);
+ return 0;
+ } else {
+ EFX_POPULATE_OWORD_1(reg, XM_CORE_RST, 1);
+ falcon_write(efx, &reg, XM_GLB_CFG_REG);
+
+ for (count = 0; count < 10000; count++) {
+ falcon_read(efx, &reg, XM_GLB_CFG_REG);
+ if (EFX_OWORD_FIELD(reg, XM_CORE_RST) == 0)
+ return 0;
+ udelay(10);
+ }
- falcon_read(efx, &temp, MAC0_CTRL_REG_KER);
- /* There is no point in draining more than once */
- if (EFX_OWORD_FIELD(temp, TXFIFO_DRAIN_EN_B0))
- return;
+ EFX_ERR(efx, "timed out waiting for XMAC core reset\n");
+ return -ETIMEDOUT;
+ }
+ }
/* MAC stats will fail whilst the TX fifo is draining. Serialise
* the drain sequence with the statistics fetch */
spin_lock(&efx->stats_lock);
- EFX_SET_OWORD_FIELD(temp, TXFIFO_DRAIN_EN_B0, 1);
- falcon_write(efx, &temp, MAC0_CTRL_REG_KER);
+ falcon_read(efx, &reg, MAC0_CTRL_REG_KER);
+ EFX_SET_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0, 1);
+ falcon_write(efx, &reg, MAC0_CTRL_REG_KER);
- /* Reset the MAC and EM block. */
- falcon_read(efx, &temp, GLB_CTL_REG_KER);
- EFX_SET_OWORD_FIELD(temp, RST_XGTX, 1);
- EFX_SET_OWORD_FIELD(temp, RST_XGRX, 1);
- EFX_SET_OWORD_FIELD(temp, RST_EM, 1);
- falcon_write(efx, &temp, GLB_CTL_REG_KER);
+ falcon_read(efx, &reg, GLB_CTL_REG_KER);
+ EFX_SET_OWORD_FIELD(reg, RST_XGTX, 1);
+ EFX_SET_OWORD_FIELD(reg, RST_XGRX, 1);
+ EFX_SET_OWORD_FIELD(reg, RST_EM, 1);
+ falcon_write(efx, &reg, GLB_CTL_REG_KER);
count = 0;
while (1) {
- falcon_read(efx, &temp, GLB_CTL_REG_KER);
- if (!EFX_OWORD_FIELD(temp, RST_XGTX) &&
- !EFX_OWORD_FIELD(temp, RST_XGRX) &&
- !EFX_OWORD_FIELD(temp, RST_EM)) {
+ falcon_read(efx, &reg, GLB_CTL_REG_KER);
+ if (!EFX_OWORD_FIELD(reg, RST_XGTX) &&
+ !EFX_OWORD_FIELD(reg, RST_XGRX) &&
+ !EFX_OWORD_FIELD(reg, RST_EM)) {
EFX_LOG(efx, "Completed MAC reset after %d loops\n",
count);
break;
@@ -1855,21 +1921,39 @@ void falcon_drain_tx_fifo(struct efx_nic *efx)
/* If we've reset the EM block and the link is up, then
* we'll have to kick the XAUI link so the PHY can recover */
- if (efx->link_up && EFX_WORKAROUND_5147(efx))
+ if (efx->link_up && EFX_IS10G(efx) && EFX_WORKAROUND_5147(efx))
falcon_reset_xaui(efx);
+
+ return 0;
+}
+
+void falcon_drain_tx_fifo(struct efx_nic *efx)
+{
+ efx_oword_t reg;
+
+ if ((falcon_rev(efx) < FALCON_REV_B0) ||
+ (efx->loopback_mode != LOOPBACK_NONE))
+ return;
+
+ falcon_read(efx, &reg, MAC0_CTRL_REG_KER);
+ /* There is no point in draining more than once */
+ if (EFX_OWORD_FIELD(reg, TXFIFO_DRAIN_EN_B0))
+ return;
+
+ falcon_reset_macs(efx);
}
void falcon_deconfigure_mac_wrapper(struct efx_nic *efx)
{
- efx_oword_t temp;
+ efx_oword_t reg;
if (falcon_rev(efx) < FALCON_REV_B0)
return;
/* Isolate the MAC -> RX */
- falcon_read(efx, &temp, RX_CFG_REG_KER);
- EFX_SET_OWORD_FIELD(temp, RX_INGR_EN_B0, 0);
- falcon_write(efx, &temp, RX_CFG_REG_KER);
+ falcon_read(efx, &reg, RX_CFG_REG_KER);
+ EFX_SET_OWORD_FIELD(reg, RX_INGR_EN_B0, 0);
+ falcon_write(efx, &reg, RX_CFG_REG_KER);
if (!efx->link_up)
falcon_drain_tx_fifo(efx);
@@ -1881,14 +1965,12 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
int link_speed;
bool tx_fc;
- if (efx->link_options & GM_LPA_10000)
- link_speed = 0x3;
- else if (efx->link_options & GM_LPA_1000)
- link_speed = 0x2;
- else if (efx->link_options & GM_LPA_100)
- link_speed = 0x1;
- else
- link_speed = 0x0;
+ switch (efx->link_speed) {
+ case 10000: link_speed = 3; break;
+ case 1000: link_speed = 2; break;
+ case 100: link_speed = 1; break;
+ default: link_speed = 0; break;
+ }
/* MAC_LINK_STATUS controls MAC backpressure but doesn't work
* as advertised. Disable to ensure packets are not
* indefinitely held and TX queue can be flushed at any point
@@ -1914,7 +1996,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
/* Transmission of pause frames when RX crosses the threshold is
* covered by RX_XOFF_MAC_EN and XM_TX_CFG_REG:XM_FCNTL.
* Action on receipt of pause frames is controller by XM_DIS_FCNTL */
- tx_fc = !!(efx->flow_control & EFX_FC_TX);
+ tx_fc = !!(efx->link_fc & EFX_FC_TX);
falcon_read(efx, &reg, RX_CFG_REG_KER);
EFX_SET_OWORD_FIELD_VER(efx, reg, RX_XOFF_MAC_EN, tx_fc);
@@ -1998,7 +2080,8 @@ static int falcon_gmii_wait(struct efx_nic *efx)
efx_dword_t md_stat;
int count;
- for (count = 0; count < 1000; count++) { /* wait upto 10ms */
+ /* wait upto 50ms - taken max from datasheet */
+ for (count = 0; count < 5000; count++) {
falcon_readl(efx, &md_stat, MD_STAT_REG_KER);
if (EFX_DWORD_FIELD(md_stat, MD_BSY) == 0) {
if (EFX_DWORD_FIELD(md_stat, MD_LNFL) != 0 ||
@@ -2162,10 +2245,14 @@ static void falcon_init_mdio(struct mii_if_info *gmii)
static int falcon_probe_phy(struct efx_nic *efx)
{
switch (efx->phy_type) {
- case PHY_TYPE_10XPRESS:
- efx->phy_op = &falcon_tenxpress_phy_ops;
+ case PHY_TYPE_SFX7101:
+ efx->phy_op = &falcon_sfx7101_phy_ops;
+ break;
+ case PHY_TYPE_SFT9001A:
+ case PHY_TYPE_SFT9001B:
+ efx->phy_op = &falcon_sft9001_phy_ops;
break;
- case PHY_TYPE_XFP:
+ case PHY_TYPE_QT2022C2:
efx->phy_op = &falcon_xfp_phy_ops;
break;
default:
@@ -2174,10 +2261,59 @@ static int falcon_probe_phy(struct efx_nic *efx)
return -1;
}
- efx->loopback_modes = LOOPBACKS_10G_INTERNAL | efx->phy_op->loopbacks;
+ if (efx->phy_op->macs & EFX_XMAC)
+ efx->loopback_modes |= ((1 << LOOPBACK_XGMII) |
+ (1 << LOOPBACK_XGXS) |
+ (1 << LOOPBACK_XAUI));
+ if (efx->phy_op->macs & EFX_GMAC)
+ efx->loopback_modes |= (1 << LOOPBACK_GMAC);
+ efx->loopback_modes |= efx->phy_op->loopbacks;
+
return 0;
}
+int falcon_switch_mac(struct efx_nic *efx)
+{
+ struct efx_mac_operations *old_mac_op = efx->mac_op;
+ efx_oword_t nic_stat;
+ unsigned strap_val;
+
+ /* Internal loopbacks override the phy speed setting */
+ if (efx->loopback_mode == LOOPBACK_GMAC) {
+ efx->link_speed = 1000;
+ efx->link_fd = true;
+ } else if (LOOPBACK_INTERNAL(efx)) {
+ efx->link_speed = 10000;
+ efx->link_fd = true;
+ }
+
+ efx->mac_op = (EFX_IS10G(efx) ?
+ &falcon_xmac_operations : &falcon_gmac_operations);
+ if (old_mac_op == efx->mac_op)
+ return 0;
+
+ WARN_ON(!mutex_is_locked(&efx->mac_lock));
+
+ /* Not all macs support a mac-level link state */
+ efx->mac_up = true;
+
+ falcon_read(efx, &nic_stat, NIC_STAT_REG);
+ strap_val = EFX_IS10G(efx) ? 5 : 3;
+ if (falcon_rev(efx) >= FALCON_REV_B0) {
+ EFX_SET_OWORD_FIELD(nic_stat, EE_STRAP_EN, 1);
+ EFX_SET_OWORD_FIELD(nic_stat, EE_STRAP_OVR, strap_val);
+ falcon_write(efx, &nic_stat, NIC_STAT_REG);
+ } else {
+ /* Falcon A1 does not support 1G/10G speed switching
+ * and must not be used with a PHY that does. */
+ BUG_ON(EFX_OWORD_FIELD(nic_stat, STRAP_PINS) != strap_val);
+ }
+
+
+ EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G');
+ return falcon_reset_macs(efx);
+}
+
/* This call is responsible for hooking in the MAC and PHY operations */
int falcon_probe_port(struct efx_nic *efx)
{
@@ -2194,9 +2330,9 @@ int falcon_probe_port(struct efx_nic *efx)
/* Hardware flow ctrl. FalconA RX FIFO too small for pause generation */
if (falcon_rev(efx) >= FALCON_REV_B0)
- efx->flow_control = EFX_FC_RX | EFX_FC_TX;
+ efx->wanted_fc = EFX_FC_RX | EFX_FC_TX;
else
- efx->flow_control = EFX_FC_RX;
+ efx->wanted_fc = EFX_FC_RX;
/* Allocate buffer for stats */
rc = falcon_alloc_buffer(efx, &efx->stats_buffer,
@@ -2253,13 +2389,18 @@ int falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out)
__le16 *word, *limit;
u32 csum;
- region = kmalloc(NVCONFIG_END, GFP_KERNEL);
+ spi = efx->spi_flash ? efx->spi_flash : efx->spi_eeprom;
+ if (!spi)
+ return -EINVAL;
+
+ region = kmalloc(FALCON_NVCONFIG_END, GFP_KERNEL);
if (!region)
return -ENOMEM;
nvconfig = region + NVCONFIG_OFFSET;
- spi = efx->spi_flash ? efx->spi_flash : efx->spi_eeprom;
- rc = falcon_spi_read(spi, 0, NVCONFIG_END, NULL, region);
+ mutex_lock(&efx->spi_lock);
+ rc = falcon_spi_read(spi, 0, FALCON_NVCONFIG_END, NULL, region);
+ mutex_unlock(&efx->spi_lock);
if (rc) {
EFX_ERR(efx, "Failed to read %s\n",
efx->spi_flash ? "flash" : "EEPROM");
@@ -2283,7 +2424,7 @@ int falcon_read_nvram(struct efx_nic *efx, struct falcon_nvconfig *nvconfig_out)
limit = (__le16 *) (nvconfig + 1);
} else {
word = region;
- limit = region + NVCONFIG_END;
+ limit = region + FALCON_NVCONFIG_END;
}
for (csum = 0; word < limit; ++word)
csum += le16_to_cpu(*word);
@@ -2325,6 +2466,10 @@ static struct {
EFX_OWORD32(0x000003FF, 0x00000000, 0x00000000, 0x00000000) },
{ DP_CTRL_REG,
EFX_OWORD32(0x00000FFF, 0x00000000, 0x00000000, 0x00000000) },
+ { GM_CFG2_REG,
+ EFX_OWORD32(0x00007337, 0x00000000, 0x00000000, 0x00000000) },
+ { GMF_CFG0_REG,
+ EFX_OWORD32(0x00001F1F, 0x00000000, 0x00000000, 0x00000000) },
{ XM_GLB_CFG_REG,
EFX_OWORD32(0x00000C68, 0x00000000, 0x00000000, 0x00000000) },
{ XM_TX_CFG_REG,
@@ -2545,7 +2690,7 @@ static int falcon_spi_device_init(struct efx_nic *efx,
struct efx_spi_device *spi_device;
if (device_type != 0) {
- spi_device = kmalloc(sizeof(*spi_device), GFP_KERNEL);
+ spi_device = kzalloc(sizeof(*spi_device), GFP_KERNEL);
if (!spi_device)
return -ENOMEM;
spi_device->device_id = device_id;
@@ -2555,6 +2700,11 @@ static int falcon_spi_device_init(struct efx_nic *efx,
SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_ADDR_LEN);
spi_device->munge_address = (spi_device->size == 1 << 9 &&
spi_device->addr_len == 1);
+ spi_device->erase_command =
+ SPI_DEV_TYPE_FIELD(device_type, SPI_DEV_TYPE_ERASE_CMD);
+ spi_device->erase_size =
+ 1 << SPI_DEV_TYPE_FIELD(device_type,
+ SPI_DEV_TYPE_ERASE_SIZE);
spi_device->block_size =
1 << SPI_DEV_TYPE_FIELD(device_type,
SPI_DEV_TYPE_BLOCK_SIZE);
@@ -2645,6 +2795,7 @@ static int falcon_probe_nvconfig(struct efx_nic *efx)
static int falcon_probe_nic_variant(struct efx_nic *efx)
{
efx_oword_t altera_build;
+ efx_oword_t nic_stat;
falcon_read(efx, &altera_build, ALTERA_BUILD_REG_KER);
if (EFX_OWORD_FIELD(altera_build, VER_ALL)) {
@@ -2652,27 +2803,20 @@ static int falcon_probe_nic_variant(struct efx_nic *efx)
return -ENODEV;
}
+ falcon_read(efx, &nic_stat, NIC_STAT_REG);
+
switch (falcon_rev(efx)) {
case FALCON_REV_A0:
case 0xff:
EFX_ERR(efx, "Falcon rev A0 not supported\n");
return -ENODEV;
- case FALCON_REV_A1:{
- efx_oword_t nic_stat;
-
- falcon_read(efx, &nic_stat, NIC_STAT_REG);
-
+ case FALCON_REV_A1:
if (EFX_OWORD_FIELD(nic_stat, STRAP_PCIE) == 0) {
EFX_ERR(efx, "Falcon rev A1 PCI-X not supported\n");
return -ENODEV;
}
- if (!EFX_OWORD_FIELD(nic_stat, STRAP_10G)) {
- EFX_ERR(efx, "1G mode not supported\n");
- return -ENODEV;
- }
break;
- }
case FALCON_REV_B0:
break;
@@ -2682,6 +2826,9 @@ static int falcon_probe_nic_variant(struct efx_nic *efx)
return -ENODEV;
}
+ /* Initial assumed speed */
+ efx->link_speed = EFX_OWORD_FIELD(nic_stat, STRAP_10G) ? 10000 : 1000;
+
return 0;
}
@@ -2689,80 +2836,37 @@ static int falcon_probe_nic_variant(struct efx_nic *efx)
static void falcon_probe_spi_devices(struct efx_nic *efx)
{
efx_oword_t nic_stat, gpio_ctl, ee_vpd_cfg;
- bool has_flash, has_eeprom, boot_is_external;
+ int boot_dev;
falcon_read(efx, &gpio_ctl, GPIO_CTL_REG_KER);
falcon_read(efx, &nic_stat, NIC_STAT_REG);
falcon_read(efx, &ee_vpd_cfg, EE_VPD_CFG_REG_KER);
- has_flash = EFX_OWORD_FIELD(nic_stat, SF_PRST);
- has_eeprom = EFX_OWORD_FIELD(nic_stat, EE_PRST);
- boot_is_external = EFX_OWORD_FIELD(gpio_ctl, BOOTED_USING_NVDEVICE);
-
- if (has_flash) {
- /* Default flash SPI device: Atmel AT25F1024
- * 128 KB, 24-bit address, 32 KB erase block,
- * 256 B write block
- */
- u32 flash_device_type =
- (17 << SPI_DEV_TYPE_SIZE_LBN)
- | (3 << SPI_DEV_TYPE_ADDR_LEN_LBN)
- | (0x52 << SPI_DEV_TYPE_ERASE_CMD_LBN)
- | (15 << SPI_DEV_TYPE_ERASE_SIZE_LBN)
- | (8 << SPI_DEV_TYPE_BLOCK_SIZE_LBN);
-
- falcon_spi_device_init(efx, &efx->spi_flash,
- EE_SPI_FLASH, flash_device_type);
-
- if (!boot_is_external) {
- /* Disable VPD and set clock dividers to safe
- * values for initial programming.
- */
- EFX_LOG(efx, "Booted from internal ASIC settings;"
- " setting SPI config\n");
- EFX_POPULATE_OWORD_3(ee_vpd_cfg, EE_VPD_EN, 0,
- /* 125 MHz / 7 ~= 20 MHz */
- EE_SF_CLOCK_DIV, 7,
- /* 125 MHz / 63 ~= 2 MHz */
- EE_EE_CLOCK_DIV, 63);
- falcon_write(efx, &ee_vpd_cfg, EE_VPD_CFG_REG_KER);
- }
- }
-
- if (has_eeprom) {
- u32 eeprom_device_type;
-
- /* If it has no flash, it must have a large EEPROM
- * for chip config; otherwise check whether 9-bit
- * addressing is used for VPD configuration
- */
- if (has_flash &&
- (!boot_is_external ||
- EFX_OWORD_FIELD(ee_vpd_cfg, EE_VPD_EN_AD9_MODE))) {
- /* Default SPI device: Atmel AT25040 or similar
- * 512 B, 9-bit address, 8 B write block
- */
- eeprom_device_type =
- (9 << SPI_DEV_TYPE_SIZE_LBN)
- | (1 << SPI_DEV_TYPE_ADDR_LEN_LBN)
- | (3 << SPI_DEV_TYPE_BLOCK_SIZE_LBN);
- } else {
- /* "Large" SPI device: Atmel AT25640 or similar
- * 8 KB, 16-bit address, 32 B write block
- */
- eeprom_device_type =
- (13 << SPI_DEV_TYPE_SIZE_LBN)
- | (2 << SPI_DEV_TYPE_ADDR_LEN_LBN)
- | (5 << SPI_DEV_TYPE_BLOCK_SIZE_LBN);
- }
-
- falcon_spi_device_init(efx, &efx->spi_eeprom,
- EE_SPI_EEPROM, eeprom_device_type);
- }
-
- EFX_LOG(efx, "flash is %s, EEPROM is %s\n",
- (has_flash ? "present" : "absent"),
- (has_eeprom ? "present" : "absent"));
+ if (EFX_OWORD_FIELD(gpio_ctl, BOOTED_USING_NVDEVICE)) {
+ boot_dev = (EFX_OWORD_FIELD(nic_stat, SF_PRST) ?
+ EE_SPI_FLASH : EE_SPI_EEPROM);
+ EFX_LOG(efx, "Booted from %s\n",
+ boot_dev == EE_SPI_FLASH ? "flash" : "EEPROM");
+ } else {
+ /* Disable VPD and set clock dividers to safe
+ * values for initial programming. */
+ boot_dev = -1;
+ EFX_LOG(efx, "Booted from internal ASIC settings;"
+ " setting SPI config\n");
+ EFX_POPULATE_OWORD_3(ee_vpd_cfg, EE_VPD_EN, 0,
+ /* 125 MHz / 7 ~= 20 MHz */
+ EE_SF_CLOCK_DIV, 7,
+ /* 125 MHz / 63 ~= 2 MHz */
+ EE_EE_CLOCK_DIV, 63);
+ falcon_write(efx, &ee_vpd_cfg, EE_VPD_CFG_REG_KER);
+ }
+
+ if (boot_dev == EE_SPI_FLASH)
+ falcon_spi_device_init(efx, &efx->spi_flash, EE_SPI_FLASH,
+ default_flash_type);
+ if (boot_dev == EE_SPI_EEPROM)
+ falcon_spi_device_init(efx, &efx->spi_eeprom, EE_SPI_EEPROM,
+ large_eeprom_type);
}
int falcon_probe_nic(struct efx_nic *efx)
@@ -2825,10 +2929,10 @@ int falcon_probe_nic(struct efx_nic *efx)
goto fail5;
/* Initialise I2C adapter */
- efx->i2c_adap.owner = THIS_MODULE;
+ efx->i2c_adap.owner = THIS_MODULE;
nic_data->i2c_data = falcon_i2c_bit_operations;
nic_data->i2c_data.data = efx;
- efx->i2c_adap.algo_data = &nic_data->i2c_data;
+ efx->i2c_adap.algo_data = &nic_data->i2c_data;
efx->i2c_adap.dev.parent = &efx->pci_dev->dev;
strlcpy(efx->i2c_adap.name, "SFC4000 GPIO", sizeof(efx->i2c_adap.name));
rc = i2c_bit_add_bus(&efx->i2c_adap);
@@ -2862,20 +2966,18 @@ int falcon_init_nic(struct efx_nic *efx)
unsigned thresh;
int rc;
- /* Set up the address region register. This is only needed
- * for the B0 FPGA, but since we are just pushing in the
- * reset defaults this may as well be unconditional. */
- EFX_POPULATE_OWORD_4(temp, ADR_REGION0, 0,
- ADR_REGION1, (1 << 16),
- ADR_REGION2, (2 << 16),
- ADR_REGION3, (3 << 16));
- falcon_write(efx, &temp, ADR_REGION_REG_KER);
-
/* Use on-chip SRAM */
falcon_read(efx, &temp, NIC_STAT_REG);
EFX_SET_OWORD_FIELD(temp, ONCHIP_SRAM, 1);
falcon_write(efx, &temp, NIC_STAT_REG);
+ /* Set the source of the GMAC clock */
+ if (falcon_rev(efx) == FALCON_REV_B0) {
+ falcon_read(efx, &temp, GPIO_CTL_REG_KER);
+ EFX_SET_OWORD_FIELD(temp, GPIO_USE_NIC_CLK, true);
+ falcon_write(efx, &temp, GPIO_CTL_REG_KER);
+ }
+
/* Set buffer table mode */
EFX_POPULATE_OWORD_1(temp, BUF_TBL_MODE, BUF_TBL_MODE_FULL);
falcon_write(efx, &temp, BUF_TBL_CFG_REG_KER);
diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h
index be025ba7a6c6..7869c3d74383 100644
--- a/drivers/net/sfc/falcon.h
+++ b/drivers/net/sfc/falcon.h
@@ -12,6 +12,7 @@
#define EFX_FALCON_H
#include "net_driver.h"
+#include "efx.h"
/*
* Falcon hardware control
@@ -65,6 +66,7 @@ extern int falcon_probe_port(struct efx_nic *efx);
extern void falcon_remove_port(struct efx_nic *efx);
/* MAC/PHY */
+extern int falcon_switch_mac(struct efx_nic *efx);
extern bool falcon_xaui_link_ok(struct efx_nic *efx);
extern int falcon_dma_stats(struct efx_nic *efx,
unsigned int done_offset);
@@ -77,6 +79,7 @@ extern int falcon_init_interrupt(struct efx_nic *efx);
extern void falcon_enable_interrupts(struct efx_nic *efx);
extern void falcon_generate_test_event(struct efx_channel *channel,
unsigned int magic);
+extern void falcon_sim_phy_event(struct efx_nic *efx);
extern void falcon_generate_interrupt(struct efx_nic *efx);
extern void falcon_set_int_moderation(struct efx_channel *channel);
extern void falcon_disable_interrupts(struct efx_nic *efx);
diff --git a/drivers/net/sfc/falcon_gmac.c b/drivers/net/sfc/falcon_gmac.c
new file mode 100644
index 000000000000..8865eae20ac5
--- /dev/null
+++ b/drivers/net/sfc/falcon_gmac.c
@@ -0,0 +1,229 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2008 Solarflare Communications Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include <linux/delay.h>
+#include "net_driver.h"
+#include "efx.h"
+#include "falcon.h"
+#include "mac.h"
+#include "falcon_hwdefs.h"
+#include "falcon_io.h"
+#include "gmii.h"
+
+/**************************************************************************
+ *
+ * MAC operations
+ *
+ *************************************************************************/
+
+static void falcon_reconfigure_gmac(struct efx_nic *efx)
+{
+ bool loopback, tx_fc, rx_fc, bytemode;
+ int if_mode;
+ unsigned int max_frame_len;
+ efx_oword_t reg;
+
+ /* Configuration register 1 */
+ tx_fc = (efx->link_fc & EFX_FC_TX) || !efx->link_fd;
+ rx_fc = !!(efx->link_fc & EFX_FC_RX);
+ loopback = (efx->loopback_mode == LOOPBACK_GMAC);
+ bytemode = (efx->link_speed == 1000);
+
+ EFX_POPULATE_OWORD_5(reg,
+ GM_LOOP, loopback,
+ GM_TX_EN, 1,
+ GM_TX_FC_EN, tx_fc,
+ GM_RX_EN, 1,
+ GM_RX_FC_EN, rx_fc);
+ falcon_write(efx, &reg, GM_CFG1_REG);
+ udelay(10);
+
+ /* Configuration register 2 */
+ if_mode = (bytemode) ? 2 : 1;
+ EFX_POPULATE_OWORD_5(reg,
+ GM_IF_MODE, if_mode,
+ GM_PAD_CRC_EN, 1,
+ GM_LEN_CHK, 1,
+ GM_FD, efx->link_fd,
+ GM_PAMBL_LEN, 0x7/*datasheet recommended */);
+
+ falcon_write(efx, &reg, GM_CFG2_REG);
+ udelay(10);
+
+ /* Max frame len register */
+ max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu);
+ EFX_POPULATE_OWORD_1(reg, GM_MAX_FLEN, max_frame_len);
+ falcon_write(efx, &reg, GM_MAX_FLEN_REG);
+ udelay(10);
+
+ /* FIFO configuration register 0 */
+ EFX_POPULATE_OWORD_5(reg,
+ GMF_FTFENREQ, 1,
+ GMF_STFENREQ, 1,
+ GMF_FRFENREQ, 1,
+ GMF_SRFENREQ, 1,
+ GMF_WTMENREQ, 1);
+ falcon_write(efx, &reg, GMF_CFG0_REG);
+ udelay(10);
+
+ /* FIFO configuration register 1 */
+ EFX_POPULATE_OWORD_2(reg,
+ GMF_CFGFRTH, 0x12,
+ GMF_CFGXOFFRTX, 0xffff);
+ falcon_write(efx, &reg, GMF_CFG1_REG);
+ udelay(10);
+
+ /* FIFO configuration register 2 */
+ EFX_POPULATE_OWORD_2(reg,
+ GMF_CFGHWM, 0x3f,
+ GMF_CFGLWM, 0xa);
+ falcon_write(efx, &reg, GMF_CFG2_REG);
+ udelay(10);
+
+ /* FIFO configuration register 3 */
+ EFX_POPULATE_OWORD_2(reg,
+ GMF_CFGHWMFT, 0x1c,
+ GMF_CFGFTTH, 0x08);
+ falcon_write(efx, &reg, GMF_CFG3_REG);
+ udelay(10);
+
+ /* FIFO configuration register 4 */
+ EFX_POPULATE_OWORD_1(reg, GMF_HSTFLTRFRM_PAUSE, 1);
+ falcon_write(efx, &reg, GMF_CFG4_REG);
+ udelay(10);
+
+ /* FIFO configuration register 5 */
+ falcon_read(efx, &reg, GMF_CFG5_REG);
+ EFX_SET_OWORD_FIELD(reg, GMF_CFGBYTMODE, bytemode);
+ EFX_SET_OWORD_FIELD(reg, GMF_CFGHDPLX, !efx->link_fd);
+ EFX_SET_OWORD_FIELD(reg, GMF_HSTDRPLT64, !efx->link_fd);
+ EFX_SET_OWORD_FIELD(reg, GMF_HSTFLTRFRMDC_PAUSE, 0);
+ falcon_write(efx, &reg, GMF_CFG5_REG);
+ udelay(10);
+
+ /* MAC address */
+ EFX_POPULATE_OWORD_4(reg,
+ GM_HWADDR_5, efx->net_dev->dev_addr[5],
+ GM_HWADDR_4, efx->net_dev->dev_addr[4],
+ GM_HWADDR_3, efx->net_dev->dev_addr[3],
+ GM_HWADDR_2, efx->net_dev->dev_addr[2]);
+ falcon_write(efx, &reg, GM_ADR1_REG);
+ udelay(10);
+ EFX_POPULATE_OWORD_2(reg,
+ GM_HWADDR_1, efx->net_dev->dev_addr[1],
+ GM_HWADDR_0, efx->net_dev->dev_addr[0]);
+ falcon_write(efx, &reg, GM_ADR2_REG);
+ udelay(10);
+
+ falcon_reconfigure_mac_wrapper(efx);
+}
+
+static void falcon_update_stats_gmac(struct efx_nic *efx)
+{
+ struct efx_mac_stats *mac_stats = &efx->mac_stats;
+ unsigned long old_rx_pause, old_tx_pause;
+ unsigned long new_rx_pause, new_tx_pause;
+ int rc;
+
+ rc = falcon_dma_stats(efx, GDmaDone_offset);
+ if (rc)
+ return;
+
+ /* Pause frames are erroneously counted as errors (SFC bug 3269) */
+ old_rx_pause = mac_stats->rx_pause;
+ old_tx_pause = mac_stats->tx_pause;
+
+ /* Update MAC stats from DMAed values */
+ FALCON_STAT(efx, GRxGoodOct, rx_good_bytes);
+ FALCON_STAT(efx, GRxBadOct, rx_bad_bytes);
+ FALCON_STAT(efx, GRxMissPkt, rx_missed);
+ FALCON_STAT(efx, GRxFalseCRS, rx_false_carrier);
+ FALCON_STAT(efx, GRxPausePkt, rx_pause);
+ FALCON_STAT(efx, GRxBadPkt, rx_bad);
+ FALCON_STAT(efx, GRxUcastPkt, rx_unicast);
+ FALCON_STAT(efx, GRxMcastPkt, rx_multicast);
+ FALCON_STAT(efx, GRxBcastPkt, rx_broadcast);
+ FALCON_STAT(efx, GRxGoodLt64Pkt, rx_good_lt64);
+ FALCON_STAT(efx, GRxBadLt64Pkt, rx_bad_lt64);
+ FALCON_STAT(efx, GRx64Pkt, rx_64);
+ FALCON_STAT(efx, GRx65to127Pkt, rx_65_to_127);
+ FALCON_STAT(efx, GRx128to255Pkt, rx_128_to_255);
+ FALCON_STAT(efx, GRx256to511Pkt, rx_256_to_511);
+ FALCON_STAT(efx, GRx512to1023Pkt, rx_512_to_1023);
+ FALCON_STAT(efx, GRx1024to15xxPkt, rx_1024_to_15xx);
+ FALCON_STAT(efx, GRx15xxtoJumboPkt, rx_15xx_to_jumbo);
+ FALCON_STAT(efx, GRxGtJumboPkt, rx_gtjumbo);
+ FALCON_STAT(efx, GRxFcsErr64to15xxPkt, rx_bad_64_to_15xx);
+ FALCON_STAT(efx, GRxFcsErr15xxtoJumboPkt, rx_bad_15xx_to_jumbo);
+ FALCON_STAT(efx, GRxFcsErrGtJumboPkt, rx_bad_gtjumbo);
+ FALCON_STAT(efx, GTxGoodBadOct, tx_bytes);
+ FALCON_STAT(efx, GTxGoodOct, tx_good_bytes);
+ FALCON_STAT(efx, GTxSglColPkt, tx_single_collision);
+ FALCON_STAT(efx, GTxMultColPkt, tx_multiple_collision);
+ FALCON_STAT(efx, GTxExColPkt, tx_excessive_collision);
+ FALCON_STAT(efx, GTxDefPkt, tx_deferred);
+ FALCON_STAT(efx, GTxLateCol, tx_late_collision);
+ FALCON_STAT(efx, GTxExDefPkt, tx_excessive_deferred);
+ FALCON_STAT(efx, GTxPausePkt, tx_pause);
+ FALCON_STAT(efx, GTxBadPkt, tx_bad);
+ FALCON_STAT(efx, GTxUcastPkt, tx_unicast);
+ FALCON_STAT(efx, GTxMcastPkt, tx_multicast);
+ FALCON_STAT(efx, GTxBcastPkt, tx_broadcast);
+ FALCON_STAT(efx, GTxLt64Pkt, tx_lt64);
+ FALCON_STAT(efx, GTx64Pkt, tx_64);
+ FALCON_STAT(efx, GTx65to127Pkt, tx_65_to_127);
+ FALCON_STAT(efx, GTx128to255Pkt, tx_128_to_255);
+ FALCON_STAT(efx, GTx256to511Pkt, tx_256_to_511);
+ FALCON_STAT(efx, GTx512to1023Pkt, tx_512_to_1023);
+ FALCON_STAT(efx, GTx1024to15xxPkt, tx_1024_to_15xx);
+ FALCON_STAT(efx, GTx15xxtoJumboPkt, tx_15xx_to_jumbo);
+ FALCON_STAT(efx, GTxGtJumboPkt, tx_gtjumbo);
+ FALCON_STAT(efx, GTxNonTcpUdpPkt, tx_non_tcpudp);
+ FALCON_STAT(efx, GTxMacSrcErrPkt, tx_mac_src_error);
+ FALCON_STAT(efx, GTxIpSrcErrPkt, tx_ip_src_error);
+
+ /* Pause frames are erroneously counted as errors (SFC bug 3269) */
+ new_rx_pause = mac_stats->rx_pause;
+ new_tx_pause = mac_stats->tx_pause;
+ mac_stats->rx_bad -= (new_rx_pause - old_rx_pause);
+ mac_stats->tx_bad -= (new_tx_pause - old_tx_pause);
+
+ /* Derive stats that the MAC doesn't provide directly */
+ mac_stats->tx_bad_bytes =
+ mac_stats->tx_bytes - mac_stats->tx_good_bytes;
+ mac_stats->tx_packets =
+ mac_stats->tx_lt64 + mac_stats->tx_64 +
+ mac_stats->tx_65_to_127 + mac_stats->tx_128_to_255 +
+ mac_stats->tx_256_to_511 + mac_stats->tx_512_to_1023 +
+ mac_stats->tx_1024_to_15xx + mac_stats->tx_15xx_to_jumbo +
+ mac_stats->tx_gtjumbo;
+ mac_stats->tx_collision =
+ mac_stats->tx_single_collision +
+ mac_stats->tx_multiple_collision +
+ mac_stats->tx_excessive_collision +
+ mac_stats->tx_late_collision;
+ mac_stats->rx_bytes =
+ mac_stats->rx_good_bytes + mac_stats->rx_bad_bytes;
+ mac_stats->rx_packets =
+ mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64 +
+ mac_stats->rx_64 + mac_stats->rx_65_to_127 +
+ mac_stats->rx_128_to_255 + mac_stats->rx_256_to_511 +
+ mac_stats->rx_512_to_1023 + mac_stats->rx_1024_to_15xx +
+ mac_stats->rx_15xx_to_jumbo + mac_stats->rx_gtjumbo;
+ mac_stats->rx_good = mac_stats->rx_packets - mac_stats->rx_bad;
+ mac_stats->rx_lt64 = mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64;
+}
+
+struct efx_mac_operations falcon_gmac_operations = {
+ .reconfigure = falcon_reconfigure_gmac,
+ .update_stats = falcon_update_stats_gmac,
+ .irq = efx_port_dummy_op_void,
+ .poll = efx_port_dummy_op_void,
+};
diff --git a/drivers/net/sfc/falcon_hwdefs.h b/drivers/net/sfc/falcon_hwdefs.h
index 5d584b0dbb51..bda8d5bb72e4 100644
--- a/drivers/net/sfc/falcon_hwdefs.h
+++ b/drivers/net/sfc/falcon_hwdefs.h
@@ -111,12 +111,18 @@
/* NIC status register */
#define NIC_STAT_REG 0x0200
+#define EE_STRAP_EN_LBN 31
+#define EE_STRAP_EN_WIDTH 1
+#define EE_STRAP_OVR_LBN 24
+#define EE_STRAP_OVR_WIDTH 4
#define ONCHIP_SRAM_LBN 16
#define ONCHIP_SRAM_WIDTH 1
#define SF_PRST_LBN 9
#define SF_PRST_WIDTH 1
#define EE_PRST_LBN 8
#define EE_PRST_WIDTH 1
+#define STRAP_PINS_LBN 0
+#define STRAP_PINS_WIDTH 3
/* These bit definitions are extrapolated from the list of numerical
* values for STRAP_PINS.
*/
@@ -130,6 +136,8 @@
/* GPIO control register */
#define GPIO_CTL_REG_KER 0x0210
+#define GPIO_USE_NIC_CLK_LBN (30)
+#define GPIO_USE_NIC_CLK_WIDTH (1)
#define GPIO_OUTPUTS_LBN (16)
#define GPIO_OUTPUTS_WIDTH (4)
#define GPIO_INPUTS_LBN (8)
@@ -492,6 +500,107 @@
#define MAC_MCAST_HASH_REG0_KER 0xca0
#define MAC_MCAST_HASH_REG1_KER 0xcb0
+/* GMAC configuration register 1 */
+#define GM_CFG1_REG 0xe00
+#define GM_SW_RST_LBN 31
+#define GM_SW_RST_WIDTH 1
+#define GM_LOOP_LBN 8
+#define GM_LOOP_WIDTH 1
+#define GM_RX_FC_EN_LBN 5
+#define GM_RX_FC_EN_WIDTH 1
+#define GM_TX_FC_EN_LBN 4
+#define GM_TX_FC_EN_WIDTH 1
+#define GM_RX_EN_LBN 2
+#define GM_RX_EN_WIDTH 1
+#define GM_TX_EN_LBN 0
+#define GM_TX_EN_WIDTH 1
+
+/* GMAC configuration register 2 */
+#define GM_CFG2_REG 0xe10
+#define GM_PAMBL_LEN_LBN 12
+#define GM_PAMBL_LEN_WIDTH 4
+#define GM_IF_MODE_LBN 8
+#define GM_IF_MODE_WIDTH 2
+#define GM_LEN_CHK_LBN 4
+#define GM_LEN_CHK_WIDTH 1
+#define GM_PAD_CRC_EN_LBN 2
+#define GM_PAD_CRC_EN_WIDTH 1
+#define GM_FD_LBN 0
+#define GM_FD_WIDTH 1
+
+/* GMAC maximum frame length register */
+#define GM_MAX_FLEN_REG 0xe40
+#define GM_MAX_FLEN_LBN 0
+#define GM_MAX_FLEN_WIDTH 16
+
+/* GMAC station address register 1 */
+#define GM_ADR1_REG 0xf00
+#define GM_HWADDR_5_LBN 24
+#define GM_HWADDR_5_WIDTH 8
+#define GM_HWADDR_4_LBN 16
+#define GM_HWADDR_4_WIDTH 8
+#define GM_HWADDR_3_LBN 8
+#define GM_HWADDR_3_WIDTH 8
+#define GM_HWADDR_2_LBN 0
+#define GM_HWADDR_2_WIDTH 8
+
+/* GMAC station address register 2 */
+#define GM_ADR2_REG 0xf10
+#define GM_HWADDR_1_LBN 24
+#define GM_HWADDR_1_WIDTH 8
+#define GM_HWADDR_0_LBN 16
+#define GM_HWADDR_0_WIDTH 8
+
+/* GMAC FIFO configuration register 0 */
+#define GMF_CFG0_REG 0xf20
+#define GMF_FTFENREQ_LBN 12
+#define GMF_FTFENREQ_WIDTH 1
+#define GMF_STFENREQ_LBN 11
+#define GMF_STFENREQ_WIDTH 1
+#define GMF_FRFENREQ_LBN 10
+#define GMF_FRFENREQ_WIDTH 1
+#define GMF_SRFENREQ_LBN 9
+#define GMF_SRFENREQ_WIDTH 1
+#define GMF_WTMENREQ_LBN 8
+#define GMF_WTMENREQ_WIDTH 1
+
+/* GMAC FIFO configuration register 1 */
+#define GMF_CFG1_REG 0xf30
+#define GMF_CFGFRTH_LBN 16
+#define GMF_CFGFRTH_WIDTH 5
+#define GMF_CFGXOFFRTX_LBN 0
+#define GMF_CFGXOFFRTX_WIDTH 16
+
+/* GMAC FIFO configuration register 2 */
+#define GMF_CFG2_REG 0xf40
+#define GMF_CFGHWM_LBN 16
+#define GMF_CFGHWM_WIDTH 6
+#define GMF_CFGLWM_LBN 0
+#define GMF_CFGLWM_WIDTH 6
+
+/* GMAC FIFO configuration register 3 */
+#define GMF_CFG3_REG 0xf50
+#define GMF_CFGHWMFT_LBN 16
+#define GMF_CFGHWMFT_WIDTH 6
+#define GMF_CFGFTTH_LBN 0
+#define GMF_CFGFTTH_WIDTH 6
+
+/* GMAC FIFO configuration register 4 */
+#define GMF_CFG4_REG 0xf60
+#define GMF_HSTFLTRFRM_PAUSE_LBN 12
+#define GMF_HSTFLTRFRM_PAUSE_WIDTH 12
+
+/* GMAC FIFO configuration register 5 */
+#define GMF_CFG5_REG 0xf70
+#define GMF_CFGHDPLX_LBN 22
+#define GMF_CFGHDPLX_WIDTH 1
+#define GMF_CFGBYTMODE_LBN 19
+#define GMF_CFGBYTMODE_WIDTH 1
+#define GMF_HSTDRPLT64_LBN 18
+#define GMF_HSTDRPLT64_WIDTH 1
+#define GMF_HSTFLTRFRMDC_PAUSE_LBN 12
+#define GMF_HSTFLTRFRMDC_PAUSE_WIDTH 1
+
/* XGMAC address register low */
#define XM_ADR_LO_REG 0x1200
#define XM_ADR_3_LBN 24
@@ -944,6 +1053,8 @@
#define XG_MNT_INTR_B0_WIDTH 1
#define RX_RECOVERY_A1_LBN 11
#define RX_RECOVERY_A1_WIDTH 1
+#define XFP_PHY_INTR_LBN 10
+#define XFP_PHY_INTR_WIDTH 1
#define XG_PHY_INTR_LBN 9
#define XG_PHY_INTR_WIDTH 1
#define G_PHY1_INTR_LBN 8
@@ -962,54 +1073,103 @@
**************************************************************************
*
*/
+
#define GRxGoodOct_offset 0x0
+#define GRxGoodOct_WIDTH 48
#define GRxBadOct_offset 0x8
+#define GRxBadOct_WIDTH 48
#define GRxMissPkt_offset 0x10
+#define GRxMissPkt_WIDTH 32
#define GRxFalseCRS_offset 0x14
+#define GRxFalseCRS_WIDTH 32
#define GRxPausePkt_offset 0x18
+#define GRxPausePkt_WIDTH 32
#define GRxBadPkt_offset 0x1C
+#define GRxBadPkt_WIDTH 32
#define GRxUcastPkt_offset 0x20
+#define GRxUcastPkt_WIDTH 32
#define GRxMcastPkt_offset 0x24
+#define GRxMcastPkt_WIDTH 32
#define GRxBcastPkt_offset 0x28
+#define GRxBcastPkt_WIDTH 32
#define GRxGoodLt64Pkt_offset 0x2C
+#define GRxGoodLt64Pkt_WIDTH 32
#define GRxBadLt64Pkt_offset 0x30
+#define GRxBadLt64Pkt_WIDTH 32
#define GRx64Pkt_offset 0x34
+#define GRx64Pkt_WIDTH 32
#define GRx65to127Pkt_offset 0x38
+#define GRx65to127Pkt_WIDTH 32
#define GRx128to255Pkt_offset 0x3C
+#define GRx128to255Pkt_WIDTH 32
#define GRx256to511Pkt_offset 0x40
+#define GRx256to511Pkt_WIDTH 32
#define GRx512to1023Pkt_offset 0x44
+#define GRx512to1023Pkt_WIDTH 32
#define GRx1024to15xxPkt_offset 0x48
+#define GRx1024to15xxPkt_WIDTH 32
#define GRx15xxtoJumboPkt_offset 0x4C
+#define GRx15xxtoJumboPkt_WIDTH 32
#define GRxGtJumboPkt_offset 0x50
+#define GRxGtJumboPkt_WIDTH 32
#define GRxFcsErr64to15xxPkt_offset 0x54
+#define GRxFcsErr64to15xxPkt_WIDTH 32
#define GRxFcsErr15xxtoJumboPkt_offset 0x58
+#define GRxFcsErr15xxtoJumboPkt_WIDTH 32
#define GRxFcsErrGtJumboPkt_offset 0x5C
+#define GRxFcsErrGtJumboPkt_WIDTH 32
#define GTxGoodBadOct_offset 0x80
+#define GTxGoodBadOct_WIDTH 48
#define GTxGoodOct_offset 0x88
+#define GTxGoodOct_WIDTH 48
#define GTxSglColPkt_offset 0x90
+#define GTxSglColPkt_WIDTH 32
#define GTxMultColPkt_offset 0x94
+#define GTxMultColPkt_WIDTH 32
#define GTxExColPkt_offset 0x98
+#define GTxExColPkt_WIDTH 32
#define GTxDefPkt_offset 0x9C
+#define GTxDefPkt_WIDTH 32
#define GTxLateCol_offset 0xA0
+#define GTxLateCol_WIDTH 32
#define GTxExDefPkt_offset 0xA4
+#define GTxExDefPkt_WIDTH 32
#define GTxPausePkt_offset 0xA8
+#define GTxPausePkt_WIDTH 32
#define GTxBadPkt_offset 0xAC
+#define GTxBadPkt_WIDTH 32
#define GTxUcastPkt_offset 0xB0
+#define GTxUcastPkt_WIDTH 32
#define GTxMcastPkt_offset 0xB4
+#define GTxMcastPkt_WIDTH 32
#define GTxBcastPkt_offset 0xB8
+#define GTxBcastPkt_WIDTH 32
#define GTxLt64Pkt_offset 0xBC
+#define GTxLt64Pkt_WIDTH 32
#define GTx64Pkt_offset 0xC0
+#define GTx64Pkt_WIDTH 32
#define GTx65to127Pkt_offset 0xC4
+#define GTx65to127Pkt_WIDTH 32
#define GTx128to255Pkt_offset 0xC8
+#define GTx128to255Pkt_WIDTH 32
#define GTx256to511Pkt_offset 0xCC
+#define GTx256to511Pkt_WIDTH 32
#define GTx512to1023Pkt_offset 0xD0
+#define GTx512to1023Pkt_WIDTH 32
#define GTx1024to15xxPkt_offset 0xD4
+#define GTx1024to15xxPkt_WIDTH 32
#define GTx15xxtoJumboPkt_offset 0xD8
+#define GTx15xxtoJumboPkt_WIDTH 32
#define GTxGtJumboPkt_offset 0xDC
+#define GTxGtJumboPkt_WIDTH 32
#define GTxNonTcpUdpPkt_offset 0xE0
+#define GTxNonTcpUdpPkt_WIDTH 16
#define GTxMacSrcErrPkt_offset 0xE4
+#define GTxMacSrcErrPkt_WIDTH 16
#define GTxIpSrcErrPkt_offset 0xE8
+#define GTxIpSrcErrPkt_WIDTH 16
#define GDmaDone_offset 0xEC
+#define GDmaDone_WIDTH 32
#define XgRxOctets_offset 0x0
#define XgRxOctets_WIDTH 48
@@ -1150,7 +1310,6 @@ struct falcon_nvconfig_board_v3 {
(((type) >> EFX_LOW_BIT(field)) & EFX_MASK32(EFX_WIDTH(field)))
#define NVCONFIG_OFFSET 0x300
-#define NVCONFIG_END 0x400
#define NVCONFIG_BOARD_MAGIC_NUM 0xFA1C
struct falcon_nvconfig {
diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c
index d4012314dd01..5a03713685ac 100644
--- a/drivers/net/sfc/falcon_xmac.c
+++ b/drivers/net/sfc/falcon_xmac.c
@@ -15,7 +15,6 @@
#include "falcon_hwdefs.h"
#include "falcon_io.h"
#include "mac.h"
-#include "gmii.h"
#include "mdio_10g.h"
#include "phy.h"
#include "boards.h"
@@ -26,24 +25,6 @@
* MAC operations
*
*************************************************************************/
-static int falcon_reset_xmac(struct efx_nic *efx)
-{
- efx_oword_t reg;
- int count;
-
- EFX_POPULATE_OWORD_1(reg, XM_CORE_RST, 1);
- falcon_write(efx, &reg, XM_GLB_CFG_REG);
-
- for (count = 0; count < 10000; count++) { /* wait upto 100ms */
- falcon_read(efx, &reg, XM_GLB_CFG_REG);
- if (EFX_OWORD_FIELD(reg, XM_CORE_RST) == 0)
- return 0;
- udelay(10);
- }
-
- EFX_ERR(efx, "timed out waiting for XMAC core reset\n");
- return -ETIMEDOUT;
-}
/* Configure the XAUI driver that is an output from Falcon */
static void falcon_setup_xaui(struct efx_nic *efx)
@@ -99,31 +80,20 @@ int falcon_reset_xaui(struct efx_nic *efx)
return -ETIMEDOUT;
}
-static bool falcon_xgmii_status(struct efx_nic *efx)
+static void falcon_mask_status_intr(struct efx_nic *efx, bool enable)
{
efx_oword_t reg;
- if (falcon_rev(efx) < FALCON_REV_B0)
- return true;
-
- /* The ISR latches, so clear it and re-read */
- falcon_read(efx, &reg, XM_MGT_INT_REG_B0);
- falcon_read(efx, &reg, XM_MGT_INT_REG_B0);
-
- if (EFX_OWORD_FIELD(reg, XM_LCLFLT) ||
- EFX_OWORD_FIELD(reg, XM_RMTFLT)) {
- EFX_INFO(efx, "MGT_INT: "EFX_DWORD_FMT"\n", EFX_DWORD_VAL(reg));
- return false;
- }
-
- return true;
-}
+ if ((falcon_rev(efx) != FALCON_REV_B0) || LOOPBACK_INTERNAL(efx))
+ return;
-static void falcon_mask_status_intr(struct efx_nic *efx, bool enable)
-{
- efx_oword_t reg;
+ /* We expect xgmii faults if the wireside link is up */
+ if (!EFX_WORKAROUND_5147(efx) || !efx->link_up)
+ return;
- if ((falcon_rev(efx) < FALCON_REV_B0) || LOOPBACK_INTERNAL(efx))
+ /* We can only use this interrupt to signal the negative edge of
+ * xaui_align [we have to poll the positive edge]. */
+ if (!efx->mac_up)
return;
/* Flush the ISR */
@@ -136,35 +106,7 @@ static void falcon_mask_status_intr(struct efx_nic *efx, bool enable)
falcon_write(efx, &reg, XM_MGT_INT_MSK_REG_B0);
}
-int falcon_init_xmac(struct efx_nic *efx)
-{
- int rc;
-
- /* Initialize the PHY first so the clock is around */
- rc = efx->phy_op->init(efx);
- if (rc)
- goto fail1;
-
- rc = falcon_reset_xaui(efx);
- if (rc)
- goto fail2;
-
- /* Wait again. Give the PHY and MAC time to come back */
- schedule_timeout_uninterruptible(HZ / 10);
-
- rc = falcon_reset_xmac(efx);
- if (rc)
- goto fail2;
-
- falcon_mask_status_intr(efx, true);
- return 0;
-
- fail2:
- efx->phy_op->fini(efx);
- fail1:
- return rc;
-}
-
+/* Get status of XAUI link */
bool falcon_xaui_link_ok(struct efx_nic *efx)
{
efx_oword_t reg;
@@ -188,18 +130,10 @@ bool falcon_xaui_link_ok(struct efx_nic *efx)
EFX_SET_OWORD_FIELD(reg, XX_DISPERR, XX_DISPERR_RESET);
falcon_write(efx, &reg, XX_CORE_STAT_REG);
- /* If the link is up, then check the phy side of the xaui link
- * (error conditions from the wire side propoagate back through
- * the phy to the xaui side). */
- if (efx->link_up && link_ok) {
+ /* If the link is up, then check the phy side of the xaui link */
+ if (efx->link_up && link_ok)
if (efx->phy_op->mmds & (1 << MDIO_MMD_PHYXS))
link_ok = mdio_clause45_phyxgxs_lane_sync(efx);
- }
-
- /* If the PHY and XAUI links are up, then check the mac's xgmii
- * fault state */
- if (efx->link_up && link_ok)
- link_ok = falcon_xgmii_status(efx);
return link_ok;
}
@@ -208,7 +142,7 @@ static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
{
unsigned int max_frame_len;
efx_oword_t reg;
- bool rx_fc = !!(efx->flow_control & EFX_FC_RX);
+ bool rx_fc = !!(efx->link_fc & EFX_FC_RX);
/* Configure MAC - cut-thru mode is hard wired on */
EFX_POPULATE_DWORD_3(reg,
@@ -311,70 +245,39 @@ static void falcon_reconfigure_xgxs_core(struct efx_nic *efx)
/* Try and bring the Falcon side of the Falcon-Phy XAUI link fails
* to come back up. Bash it until it comes back up */
-static bool falcon_check_xaui_link_up(struct efx_nic *efx)
+static void falcon_check_xaui_link_up(struct efx_nic *efx, int tries)
{
- int max_tries, tries;
- tries = EFX_WORKAROUND_5147(efx) ? 5 : 1;
- max_tries = tries;
+ efx->mac_up = falcon_xaui_link_ok(efx);
if ((efx->loopback_mode == LOOPBACK_NETWORK) ||
- (efx->phy_type == PHY_TYPE_NONE) ||
efx_phy_mode_disabled(efx->phy_mode))
- return false;
-
- while (tries) {
- if (falcon_xaui_link_ok(efx))
- return true;
+ /* XAUI link is expected to be down */
+ return;
- EFX_LOG(efx, "%s Clobbering XAUI (%d tries left).\n",
- __func__, tries);
+ while (!efx->mac_up && tries) {
+ EFX_LOG(efx, "bashing xaui\n");
falcon_reset_xaui(efx);
udelay(200);
- tries--;
- }
- EFX_LOG(efx, "Failed to bring XAUI link back up in %d tries!\n",
- max_tries);
- return false;
+ efx->mac_up = falcon_xaui_link_ok(efx);
+ --tries;
+ }
}
-void falcon_reconfigure_xmac(struct efx_nic *efx)
+static void falcon_reconfigure_xmac(struct efx_nic *efx)
{
- bool xaui_link_ok;
-
falcon_mask_status_intr(efx, false);
- falcon_deconfigure_mac_wrapper(efx);
-
- /* Reconfigure the PHY, disabling transmit in mac level loopback. */
- if (LOOPBACK_INTERNAL(efx))
- efx->phy_mode |= PHY_MODE_TX_DISABLED;
- else
- efx->phy_mode &= ~PHY_MODE_TX_DISABLED;
- efx->phy_op->reconfigure(efx);
-
falcon_reconfigure_xgxs_core(efx);
falcon_reconfigure_xmac_core(efx);
falcon_reconfigure_mac_wrapper(efx);
- /* Ensure XAUI link is up */
- xaui_link_ok = falcon_check_xaui_link_up(efx);
-
- if (xaui_link_ok && efx->link_up)
- falcon_mask_status_intr(efx, true);
-}
-
-void falcon_fini_xmac(struct efx_nic *efx)
-{
- /* Isolate the MAC - PHY */
- falcon_deconfigure_mac_wrapper(efx);
-
- /* Potentially power down the PHY */
- efx->phy_op->fini(efx);
+ falcon_check_xaui_link_up(efx, 5);
+ falcon_mask_status_intr(efx, true);
}
-void falcon_update_stats_xmac(struct efx_nic *efx)
+static void falcon_update_stats_xmac(struct efx_nic *efx)
{
struct efx_mac_stats *mac_stats = &efx->mac_stats;
int rc;
@@ -439,97 +342,35 @@ void falcon_update_stats_xmac(struct efx_nic *efx)
mac_stats->rx_control * 64);
}
-int falcon_check_xmac(struct efx_nic *efx)
+static void falcon_xmac_irq(struct efx_nic *efx)
{
- bool xaui_link_ok;
- int rc;
-
- if ((efx->loopback_mode == LOOPBACK_NETWORK) ||
- efx_phy_mode_disabled(efx->phy_mode))
- return 0;
-
- falcon_mask_status_intr(efx, false);
- xaui_link_ok = falcon_xaui_link_ok(efx);
-
- if (EFX_WORKAROUND_5147(efx) && !xaui_link_ok)
- falcon_reset_xaui(efx);
-
- /* Call the PHY check_hw routine */
- rc = efx->phy_op->check_hw(efx);
-
- /* Unmask interrupt if everything was (and still is) ok */
- if (xaui_link_ok && efx->link_up)
- falcon_mask_status_intr(efx, true);
-
- return rc;
-}
-
-/* Simulate a PHY event */
-void falcon_xmac_sim_phy_event(struct efx_nic *efx)
-{
- efx_qword_t phy_event;
-
- EFX_POPULATE_QWORD_2(phy_event,
- EV_CODE, GLOBAL_EV_DECODE,
- XG_PHY_INTR, 1);
- falcon_generate_event(&efx->channel[0], &phy_event);
+ /* The XGMII link has a transient fault, which indicates either:
+ * - there's a transient xgmii fault
+ * - falcon's end of the xaui link may need a kick
+ * - the wire-side link may have gone down, but the lasi/poll()
+ * hasn't noticed yet.
+ *
+ * We only want to even bother polling XAUI if we're confident it's
+ * not (1) or (3). In both cases, the only reliable way to spot this
+ * is to wait a bit. We do this here by forcing the mac link state
+ * to down, and waiting for the mac poll to come round and check
+ */
+ efx->mac_up = false;
}
-int falcon_xmac_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+static void falcon_poll_xmac(struct efx_nic *efx)
{
- mdio_clause45_get_settings(efx, ecmd);
- ecmd->transceiver = XCVR_INTERNAL;
- ecmd->phy_address = efx->mii.phy_id;
- ecmd->autoneg = AUTONEG_DISABLE;
- ecmd->duplex = DUPLEX_FULL;
- return 0;
-}
+ if (!EFX_WORKAROUND_5147(efx) || !efx->link_up || efx->mac_up)
+ return;
-int falcon_xmac_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
-{
- if (ecmd->transceiver != XCVR_INTERNAL)
- return -EINVAL;
- if (ecmd->autoneg != AUTONEG_DISABLE)
- return -EINVAL;
- if (ecmd->duplex != DUPLEX_FULL)
- return -EINVAL;
-
- return mdio_clause45_set_settings(efx, ecmd);
+ falcon_mask_status_intr(efx, false);
+ falcon_check_xaui_link_up(efx, 1);
+ falcon_mask_status_intr(efx, true);
}
-
-int falcon_xmac_set_pause(struct efx_nic *efx, enum efx_fc_type flow_control)
-{
- bool reset;
-
- if (flow_control & EFX_FC_AUTO) {
- EFX_LOG(efx, "10G does not support flow control "
- "autonegotiation\n");
- return -EINVAL;
- }
-
- if ((flow_control & EFX_FC_TX) && !(flow_control & EFX_FC_RX))
- return -EINVAL;
-
- /* TX flow control may automatically turn itself off if the
- * link partner (intermittently) stops responding to pause
- * frames. There isn't any indication that this has happened,
- * so the best we do is leave it up to the user to spot this
- * and fix it be cycling transmit flow control on this end. */
- reset = ((flow_control & EFX_FC_TX) &&
- !(efx->flow_control & EFX_FC_TX));
- if (EFX_WORKAROUND_11482(efx) && reset) {
- if (falcon_rev(efx) >= FALCON_REV_B0) {
- /* Recover by resetting the EM block */
- if (efx->link_up)
- falcon_drain_tx_fifo(efx);
- } else {
- /* Schedule a reset to recover */
- efx_schedule_reset(efx, RESET_TYPE_INVISIBLE);
- }
- }
-
- efx->flow_control = flow_control;
-
- return 0;
-}
+struct efx_mac_operations falcon_xmac_operations = {
+ .reconfigure = falcon_reconfigure_xmac,
+ .update_stats = falcon_update_stats_xmac,
+ .irq = falcon_xmac_irq,
+ .poll = falcon_poll_xmac,
+};
diff --git a/drivers/net/sfc/gmii.h b/drivers/net/sfc/gmii.h
index d25bbd1297f4..dfccaa7b573e 100644
--- a/drivers/net/sfc/gmii.h
+++ b/drivers/net/sfc/gmii.h
@@ -1,7 +1,7 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006 Solarflare Communications Inc.
+ * Copyright 2006-2008 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@@ -57,139 +57,4 @@
#define ISR_POLARITY_CHG 0x0002 /* Bit 1 - polarity changed */
#define ISR_JABBER 0x0001 /* Bit 0 - jabber */
-/* Logically extended advertisement register */
-#define GM_ADVERTISE_SLCT ADVERTISE_SLCT
-#define GM_ADVERTISE_CSMA ADVERTISE_CSMA
-#define GM_ADVERTISE_10HALF ADVERTISE_10HALF
-#define GM_ADVERTISE_1000XFULL ADVERTISE_1000XFULL
-#define GM_ADVERTISE_10FULL ADVERTISE_10FULL
-#define GM_ADVERTISE_1000XHALF ADVERTISE_1000XHALF
-#define GM_ADVERTISE_100HALF ADVERTISE_100HALF
-#define GM_ADVERTISE_1000XPAUSE ADVERTISE_1000XPAUSE
-#define GM_ADVERTISE_100FULL ADVERTISE_100FULL
-#define GM_ADVERTISE_1000XPSE_ASYM ADVERTISE_1000XPSE_ASYM
-#define GM_ADVERTISE_100BASE4 ADVERTISE_100BASE4
-#define GM_ADVERTISE_PAUSE_CAP ADVERTISE_PAUSE_CAP
-#define GM_ADVERTISE_PAUSE_ASYM ADVERTISE_PAUSE_ASYM
-#define GM_ADVERTISE_RESV ADVERTISE_RESV
-#define GM_ADVERTISE_RFAULT ADVERTISE_RFAULT
-#define GM_ADVERTISE_LPACK ADVERTISE_LPACK
-#define GM_ADVERTISE_NPAGE ADVERTISE_NPAGE
-#define GM_ADVERTISE_1000FULL (ADVERTISE_1000FULL << 8)
-#define GM_ADVERTISE_1000HALF (ADVERTISE_1000HALF << 8)
-#define GM_ADVERTISE_1000 (GM_ADVERTISE_1000FULL | \
- GM_ADVERTISE_1000HALF)
-#define GM_ADVERTISE_FULL (GM_ADVERTISE_1000FULL | \
- ADVERTISE_FULL)
-#define GM_ADVERTISE_ALL (GM_ADVERTISE_1000FULL | \
- GM_ADVERTISE_1000HALF | \
- ADVERTISE_ALL)
-
-/* Logically extended link partner ability register */
-#define GM_LPA_SLCT LPA_SLCT
-#define GM_LPA_10HALF LPA_10HALF
-#define GM_LPA_1000XFULL LPA_1000XFULL
-#define GM_LPA_10FULL LPA_10FULL
-#define GM_LPA_1000XHALF LPA_1000XHALF
-#define GM_LPA_100HALF LPA_100HALF
-#define GM_LPA_1000XPAUSE LPA_1000XPAUSE
-#define GM_LPA_100FULL LPA_100FULL
-#define GM_LPA_1000XPAUSE_ASYM LPA_1000XPAUSE_ASYM
-#define GM_LPA_100BASE4 LPA_100BASE4
-#define GM_LPA_PAUSE_CAP LPA_PAUSE_CAP
-#define GM_LPA_PAUSE_ASYM LPA_PAUSE_ASYM
-#define GM_LPA_RESV LPA_RESV
-#define GM_LPA_RFAULT LPA_RFAULT
-#define GM_LPA_LPACK LPA_LPACK
-#define GM_LPA_NPAGE LPA_NPAGE
-#define GM_LPA_1000FULL (LPA_1000FULL << 6)
-#define GM_LPA_1000HALF (LPA_1000HALF << 6)
-#define GM_LPA_10000FULL 0x00040000
-#define GM_LPA_10000HALF 0x00080000
-#define GM_LPA_DUPLEX (GM_LPA_1000FULL | GM_LPA_10000FULL \
- | LPA_DUPLEX)
-#define GM_LPA_10 (LPA_10FULL | LPA_10HALF)
-#define GM_LPA_100 LPA_100
-#define GM_LPA_1000 (GM_LPA_1000FULL | GM_LPA_1000HALF)
-#define GM_LPA_10000 (GM_LPA_10000FULL | GM_LPA_10000HALF)
-
-/* Retrieve GMII autonegotiation advertised abilities
- *
- * The MII advertisment register (MII_ADVERTISE) is logically extended
- * to include advertisement bits ADVERTISE_1000FULL and
- * ADVERTISE_1000HALF from MII_CTRL1000. The result can be tested
- * against the GM_ADVERTISE_xxx constants.
- */
-static inline unsigned int gmii_advertised(struct mii_if_info *gmii)
-{
- unsigned int advertise;
- unsigned int ctrl1000;
-
- advertise = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_ADVERTISE);
- ctrl1000 = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_CTRL1000);
- return (((ctrl1000 << 8) & GM_ADVERTISE_1000) | advertise);
-}
-
-/* Retrieve GMII autonegotiation link partner abilities
- *
- * The MII link partner ability register (MII_LPA) is logically
- * extended by adding bits LPA_1000HALF and LPA_1000FULL from
- * MII_STAT1000. The result can be tested against the GM_LPA_xxx
- * constants.
- */
-static inline unsigned int gmii_lpa(struct mii_if_info *gmii)
-{
- unsigned int lpa;
- unsigned int stat1000;
-
- lpa = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_LPA);
- stat1000 = gmii->mdio_read(gmii->dev, gmii->phy_id, MII_STAT1000);
- return (((stat1000 << 6) & GM_LPA_1000) | lpa);
-}
-
-/* Calculate GMII autonegotiated link technology
- *
- * "negotiated" should be the result of gmii_advertised() logically
- * ANDed with the result of gmii_lpa().
- *
- * "tech" will be negotiated with the unused bits masked out. For
- * example, if both ends of the link are capable of both
- * GM_LPA_1000FULL and GM_LPA_100FULL, GM_LPA_100FULL will be masked
- * out.
- */
-static inline unsigned int gmii_nway_result(unsigned int negotiated)
-{
- unsigned int other_bits;
-
- /* Mask out the speed and duplexity bits */
- other_bits = negotiated & ~(GM_LPA_10 | GM_LPA_100 | GM_LPA_1000);
-
- if (negotiated & GM_LPA_1000FULL)
- return (other_bits | GM_LPA_1000FULL);
- else if (negotiated & GM_LPA_1000HALF)
- return (other_bits | GM_LPA_1000HALF);
- else
- return (other_bits | mii_nway_result(negotiated));
-}
-
-/* Calculate GMII non-autonegotiated link technology
- *
- * This provides an equivalent to gmii_nway_result for the case when
- * autonegotiation is disabled.
- */
-static inline unsigned int gmii_forced_result(unsigned int bmcr)
-{
- unsigned int result;
- int full_duplex;
-
- full_duplex = bmcr & BMCR_FULLDPLX;
- if (bmcr & BMCR_SPEED1000)
- result = full_duplex ? GM_LPA_1000FULL : GM_LPA_1000HALF;
- else if (bmcr & BMCR_SPEED100)
- result = full_duplex ? GM_LPA_100FULL : GM_LPA_100HALF;
- else
- result = full_duplex ? GM_LPA_10FULL : GM_LPA_10HALF;
- return result;
-}
-
#endif /* EFX_GMII_H */
diff --git a/drivers/net/sfc/mac.h b/drivers/net/sfc/mac.h
index a31571c69137..4e7074278fe1 100644
--- a/drivers/net/sfc/mac.h
+++ b/drivers/net/sfc/mac.h
@@ -1,7 +1,7 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
* Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2007 Solarflare Communications Inc.
+ * Copyright 2006-2008 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@@ -13,17 +13,7 @@
#include "net_driver.h"
-extern int falcon_init_xmac(struct efx_nic *efx);
-extern void falcon_reconfigure_xmac(struct efx_nic *efx);
-extern void falcon_update_stats_xmac(struct efx_nic *efx);
-extern void falcon_fini_xmac(struct efx_nic *efx);
-extern int falcon_check_xmac(struct efx_nic *efx);
-extern void falcon_xmac_sim_phy_event(struct efx_nic *efx);
-extern int falcon_xmac_get_settings(struct efx_nic *efx,
- struct ethtool_cmd *ecmd);
-extern int falcon_xmac_set_settings(struct efx_nic *efx,
- struct ethtool_cmd *ecmd);
-extern int falcon_xmac_set_pause(struct efx_nic *efx,
- enum efx_fc_type pause_params);
+extern struct efx_mac_operations falcon_gmac_operations;
+extern struct efx_mac_operations falcon_xmac_operations;
#endif
diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c
index 003e48dcb2f3..f6a16428113d 100644
--- a/drivers/net/sfc/mdio_10g.c
+++ b/drivers/net/sfc/mdio_10g.c
@@ -47,13 +47,16 @@ static int mdio_clause45_check_mmd(struct efx_nic *efx, int mmd,
if (LOOPBACK_INTERNAL(efx))
return 0;
- /* Read MMD STATUS2 to check it is responding. */
- status = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_STAT2);
- if (((status >> MDIO_MMDREG_STAT2_PRESENT_LBN) &
- ((1 << MDIO_MMDREG_STAT2_PRESENT_WIDTH) - 1)) !=
- MDIO_MMDREG_STAT2_PRESENT_VAL) {
- EFX_ERR(efx, "PHY MMD %d not responding.\n", mmd);
- return -EIO;
+ if (mmd != MDIO_MMD_AN) {
+ /* Read MMD STATUS2 to check it is responding. */
+ status = mdio_clause45_read(efx, phy_id, mmd,
+ MDIO_MMDREG_STAT2);
+ if (((status >> MDIO_MMDREG_STAT2_PRESENT_LBN) &
+ ((1 << MDIO_MMDREG_STAT2_PRESENT_WIDTH) - 1)) !=
+ MDIO_MMDREG_STAT2_PRESENT_VAL) {
+ EFX_ERR(efx, "PHY MMD %d not responding.\n", mmd);
+ return -EIO;
+ }
}
/* Read MMD STATUS 1 to check for fault. */
@@ -121,16 +124,18 @@ int mdio_clause45_wait_reset_mmds(struct efx_nic *efx,
int mdio_clause45_check_mmds(struct efx_nic *efx,
unsigned int mmd_mask, unsigned int fatal_mask)
{
- int devices, mmd = 0;
- int probe_mmd;
+ u32 devices;
+ int mmd = 0, probe_mmd;
/* Historically we have probed the PHYXS to find out what devices are
* present,but that doesn't work so well if the PHYXS isn't expected
* to exist, if so just find the first item in the list supplied. */
- probe_mmd = (mmd_mask & MDIO_MMDREG_DEVS0_PHYXS) ? MDIO_MMD_PHYXS :
+ probe_mmd = (mmd_mask & MDIO_MMDREG_DEVS_PHYXS) ? MDIO_MMD_PHYXS :
__ffs(mmd_mask);
- devices = mdio_clause45_read(efx, efx->mii.phy_id,
- probe_mmd, MDIO_MMDREG_DEVS0);
+ devices = (mdio_clause45_read(efx, efx->mii.phy_id,
+ probe_mmd, MDIO_MMDREG_DEVS0) |
+ mdio_clause45_read(efx, efx->mii.phy_id,
+ probe_mmd, MDIO_MMDREG_DEVS1) << 16);
/* Check all the expected MMDs are present */
if (devices < 0) {
@@ -162,7 +167,7 @@ int mdio_clause45_check_mmds(struct efx_nic *efx,
bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
{
int phy_id = efx->mii.phy_id;
- int status;
+ u32 reg;
bool ok = true;
int mmd = 0;
@@ -174,26 +179,33 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
return false;
else if (efx_phy_mode_disabled(efx->phy_mode))
return false;
- else if (efx->loopback_mode == LOOPBACK_PHYXS)
- mmd_mask &= ~(MDIO_MMDREG_DEVS0_PHYXS |
- MDIO_MMDREG_DEVS0_PCS |
- MDIO_MMDREG_DEVS0_PMAPMD);
- else if (efx->loopback_mode == LOOPBACK_PCS)
- mmd_mask &= ~(MDIO_MMDREG_DEVS0_PCS |
- MDIO_MMDREG_DEVS0_PMAPMD);
+ else if (efx->loopback_mode == LOOPBACK_PHYXS) {
+ mmd_mask &= ~(MDIO_MMDREG_DEVS_PHYXS |
+ MDIO_MMDREG_DEVS_PCS |
+ MDIO_MMDREG_DEVS_PMAPMD |
+ MDIO_MMDREG_DEVS_AN);
+ if (!mmd_mask) {
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS,
+ MDIO_PHYXS_STATUS2);
+ return !(reg & (1 << MDIO_PHYXS_STATUS2_RX_FAULT_LBN));
+ }
+ } else if (efx->loopback_mode == LOOPBACK_PCS)
+ mmd_mask &= ~(MDIO_MMDREG_DEVS_PCS |
+ MDIO_MMDREG_DEVS_PMAPMD |
+ MDIO_MMDREG_DEVS_AN);
else if (efx->loopback_mode == LOOPBACK_PMAPMD)
- mmd_mask &= ~MDIO_MMDREG_DEVS0_PMAPMD;
+ mmd_mask &= ~(MDIO_MMDREG_DEVS_PMAPMD |
+ MDIO_MMDREG_DEVS_AN);
while (mmd_mask) {
if (mmd_mask & 1) {
/* Double reads because link state is latched, and a
* read moves the current state into the register */
- status = mdio_clause45_read(efx, phy_id,
- mmd, MDIO_MMDREG_STAT1);
- status = mdio_clause45_read(efx, phy_id,
- mmd, MDIO_MMDREG_STAT1);
-
- ok = ok && (status & (1 << MDIO_MMDREG_STAT1_LINK_LBN));
+ reg = mdio_clause45_read(efx, phy_id,
+ mmd, MDIO_MMDREG_STAT1);
+ reg = mdio_clause45_read(efx, phy_id,
+ mmd, MDIO_MMDREG_STAT1);
+ ok = ok && (reg & (1 << MDIO_MMDREG_STAT1_LINK_LBN));
}
mmd_mask = (mmd_mask >> 1);
mmd++;
@@ -203,61 +215,73 @@ bool mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask)
void mdio_clause45_transmit_disable(struct efx_nic *efx)
{
- int phy_id = efx->mii.phy_id;
- int ctrl1, ctrl2;
-
- ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
- MDIO_MMDREG_TXDIS);
- if (efx->phy_mode & PHY_MODE_TX_DISABLED)
- ctrl2 |= (1 << MDIO_MMDREG_TXDIS_GLOBAL_LBN);
- else
- ctrl1 &= ~(1 << MDIO_MMDREG_TXDIS_GLOBAL_LBN);
- if (ctrl1 != ctrl2)
- mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
- MDIO_MMDREG_TXDIS, ctrl2);
+ mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
+ MDIO_MMDREG_TXDIS, MDIO_MMDREG_TXDIS_GLOBAL_LBN,
+ efx->phy_mode & PHY_MODE_TX_DISABLED);
}
void mdio_clause45_phy_reconfigure(struct efx_nic *efx)
{
int phy_id = efx->mii.phy_id;
- int ctrl1, ctrl2;
- /* Handle (with debouncing) PMA/PMD loopback */
- ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
- MDIO_MMDREG_CTRL1);
-
- if (efx->loopback_mode == LOOPBACK_PMAPMD)
- ctrl2 |= (1 << MDIO_PMAPMD_CTRL1_LBACK_LBN);
- else
- ctrl2 &= ~(1 << MDIO_PMAPMD_CTRL1_LBACK_LBN);
+ mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PMAPMD,
+ MDIO_MMDREG_CTRL1, MDIO_PMAPMD_CTRL1_LBACK_LBN,
+ efx->loopback_mode == LOOPBACK_PMAPMD);
+ mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PCS,
+ MDIO_MMDREG_CTRL1, MDIO_MMDREG_CTRL1_LBACK_LBN,
+ efx->loopback_mode == LOOPBACK_PCS);
+ mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PHYXS,
+ MDIO_MMDREG_CTRL1, MDIO_MMDREG_CTRL1_LBACK_LBN,
+ efx->loopback_mode == LOOPBACK_NETWORK);
+}
- if (ctrl1 != ctrl2)
- mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
- MDIO_MMDREG_CTRL1, ctrl2);
+static void mdio_clause45_set_mmd_lpower(struct efx_nic *efx,
+ int lpower, int mmd)
+{
+ int phy = efx->mii.phy_id;
+ int stat = mdio_clause45_read(efx, phy, mmd, MDIO_MMDREG_STAT1);
- /* Handle (with debouncing) PCS loopback */
- ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS,
- MDIO_MMDREG_CTRL1);
- if (efx->loopback_mode == LOOPBACK_PCS)
- ctrl2 |= (1 << MDIO_MMDREG_CTRL1_LBACK_LBN);
- else
- ctrl2 &= ~(1 << MDIO_MMDREG_CTRL1_LBACK_LBN);
+ EFX_TRACE(efx, "Setting low power mode for MMD %d to %d\n",
+ mmd, lpower);
- if (ctrl1 != ctrl2)
- mdio_clause45_write(efx, phy_id, MDIO_MMD_PCS,
- MDIO_MMDREG_CTRL1, ctrl2);
+ if (stat & (1 << MDIO_MMDREG_STAT1_LPABLE_LBN)) {
+ mdio_clause45_set_flag(efx, phy, mmd, MDIO_MMDREG_CTRL1,
+ MDIO_MMDREG_CTRL1_LPOWER_LBN, lpower);
+ }
+}
- /* Handle (with debouncing) PHYXS network loopback */
- ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS,
- MDIO_MMDREG_CTRL1);
- if (efx->loopback_mode == LOOPBACK_NETWORK)
- ctrl2 |= (1 << MDIO_MMDREG_CTRL1_LBACK_LBN);
- else
- ctrl2 &= ~(1 << MDIO_MMDREG_CTRL1_LBACK_LBN);
+void mdio_clause45_set_mmds_lpower(struct efx_nic *efx,
+ int low_power, unsigned int mmd_mask)
+{
+ int mmd = 0;
+ mmd_mask &= ~MDIO_MMDREG_DEVS_AN;
+ while (mmd_mask) {
+ if (mmd_mask & 1)
+ mdio_clause45_set_mmd_lpower(efx, low_power, mmd);
+ mmd_mask = (mmd_mask >> 1);
+ mmd++;
+ }
+}
- if (ctrl1 != ctrl2)
- mdio_clause45_write(efx, phy_id, MDIO_MMD_PHYXS,
- MDIO_MMDREG_CTRL1, ctrl2);
+static u32 mdio_clause45_get_an(struct efx_nic *efx, u16 addr, u32 xnp)
+{
+ int phy_id = efx->mii.phy_id;
+ u32 result = 0;
+ int reg;
+
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, addr);
+ if (reg & ADVERTISE_10HALF)
+ result |= ADVERTISED_10baseT_Half;
+ if (reg & ADVERTISE_10FULL)
+ result |= ADVERTISED_10baseT_Full;
+ if (reg & ADVERTISE_100HALF)
+ result |= ADVERTISED_100baseT_Half;
+ if (reg & ADVERTISE_100FULL)
+ result |= ADVERTISED_100baseT_Full;
+ if (reg & LPA_RESV)
+ result |= xnp;
+
+ return result;
}
/**
@@ -266,95 +290,290 @@ void mdio_clause45_phy_reconfigure(struct efx_nic *efx)
* @ecmd: Buffer for settings
*
* On return the 'port', 'speed', 'supported' and 'advertising' fields of
- * ecmd have been filled out based on the PMA type.
+ * ecmd have been filled out.
*/
void mdio_clause45_get_settings(struct efx_nic *efx,
struct ethtool_cmd *ecmd)
{
- int pma_type;
+ mdio_clause45_get_settings_ext(efx, ecmd, 0, 0);
+}
- /* If no PMA is present we are presumably talking something XAUI-ish
- * like CX4. Which we report as FIBRE (see below) */
- if ((efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_PMAPMD)) == 0) {
- ecmd->speed = SPEED_10000;
- ecmd->port = PORT_FIBRE;
- ecmd->supported = SUPPORTED_FIBRE;
- ecmd->advertising = ADVERTISED_FIBRE;
- return;
- }
+/**
+ * mdio_clause45_get_settings_ext - Read (some of) the PHY settings over MDIO.
+ * @efx: Efx NIC
+ * @ecmd: Buffer for settings
+ * @xnp: Advertised Extended Next Page state
+ * @xnp_lpa: Link Partner's advertised XNP state
+ *
+ * On return the 'port', 'speed', 'supported' and 'advertising' fields of
+ * ecmd have been filled out.
+ */
+void mdio_clause45_get_settings_ext(struct efx_nic *efx,
+ struct ethtool_cmd *ecmd,
+ u32 xnp, u32 xnp_lpa)
+{
+ int phy_id = efx->mii.phy_id;
+ int reg;
- pma_type = mdio_clause45_read(efx, efx->mii.phy_id,
- MDIO_MMD_PMAPMD, MDIO_MMDREG_CTRL2);
- pma_type &= MDIO_PMAPMD_CTRL2_TYPE_MASK;
+ ecmd->transceiver = XCVR_INTERNAL;
+ ecmd->phy_address = phy_id;
- switch (pma_type) {
- /* We represent CX4 as fibre in the absence of anything
- better. */
- case MDIO_PMAPMD_CTRL2_10G_CX4:
- ecmd->speed = SPEED_10000;
- ecmd->port = PORT_FIBRE;
- ecmd->supported = SUPPORTED_FIBRE;
- ecmd->advertising = ADVERTISED_FIBRE;
- break;
- /* 10G Base-T */
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
+ MDIO_MMDREG_CTRL2);
+ switch (reg & MDIO_PMAPMD_CTRL2_TYPE_MASK) {
case MDIO_PMAPMD_CTRL2_10G_BT:
- ecmd->speed = SPEED_10000;
- ecmd->port = PORT_TP;
- ecmd->supported = SUPPORTED_TP | SUPPORTED_10000baseT_Full;
- ecmd->advertising = (ADVERTISED_FIBRE
- | ADVERTISED_10000baseT_Full);
- break;
case MDIO_PMAPMD_CTRL2_1G_BT:
- ecmd->speed = SPEED_1000;
- ecmd->port = PORT_TP;
- ecmd->supported = SUPPORTED_TP | SUPPORTED_1000baseT_Full;
- ecmd->advertising = (ADVERTISED_FIBRE
- | ADVERTISED_1000baseT_Full);
- break;
case MDIO_PMAPMD_CTRL2_100_BT:
- ecmd->speed = SPEED_100;
- ecmd->port = PORT_TP;
- ecmd->supported = SUPPORTED_TP | SUPPORTED_100baseT_Full;
- ecmd->advertising = (ADVERTISED_FIBRE
- | ADVERTISED_100baseT_Full);
- break;
case MDIO_PMAPMD_CTRL2_10_BT:
- ecmd->speed = SPEED_10;
ecmd->port = PORT_TP;
- ecmd->supported = SUPPORTED_TP | SUPPORTED_10baseT_Full;
- ecmd->advertising = ADVERTISED_FIBRE | ADVERTISED_10baseT_Full;
+ ecmd->supported = SUPPORTED_TP;
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
+ MDIO_MMDREG_SPEED);
+ if (reg & (1 << MDIO_MMDREG_SPEED_10G_LBN))
+ ecmd->supported |= SUPPORTED_10000baseT_Full;
+ if (reg & (1 << MDIO_MMDREG_SPEED_1000M_LBN))
+ ecmd->supported |= (SUPPORTED_1000baseT_Full |
+ SUPPORTED_1000baseT_Half);
+ if (reg & (1 << MDIO_MMDREG_SPEED_100M_LBN))
+ ecmd->supported |= (SUPPORTED_100baseT_Full |
+ SUPPORTED_100baseT_Half);
+ if (reg & (1 << MDIO_MMDREG_SPEED_10M_LBN))
+ ecmd->supported |= (SUPPORTED_10baseT_Full |
+ SUPPORTED_10baseT_Half);
+ ecmd->advertising = ADVERTISED_TP;
break;
- /* All the other defined modes are flavours of
- * 10G optical */
+
+ /* We represent CX4 as fibre in the absence of anything better */
+ case MDIO_PMAPMD_CTRL2_10G_CX4:
+ /* All the other defined modes are flavours of optical */
default:
- ecmd->speed = SPEED_10000;
ecmd->port = PORT_FIBRE;
ecmd->supported = SUPPORTED_FIBRE;
ecmd->advertising = ADVERTISED_FIBRE;
break;
}
+
+ if (efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) {
+ ecmd->supported |= SUPPORTED_Autoneg;
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
+ MDIO_MMDREG_CTRL1);
+ if (reg & BMCR_ANENABLE) {
+ ecmd->autoneg = AUTONEG_ENABLE;
+ ecmd->advertising |=
+ ADVERTISED_Autoneg |
+ mdio_clause45_get_an(efx,
+ MDIO_AN_ADVERTISE, xnp);
+ } else
+ ecmd->autoneg = AUTONEG_DISABLE;
+ } else
+ ecmd->autoneg = AUTONEG_DISABLE;
+
+ if (ecmd->autoneg) {
+ /* If AN is complete, report best common mode,
+ * otherwise report best advertised mode. */
+ u32 common = ecmd->advertising;
+ if (mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
+ MDIO_MMDREG_STAT1) &
+ (1 << MDIO_AN_STATUS_AN_DONE_LBN)) {
+ common &= mdio_clause45_get_an(efx, MDIO_AN_LPA,
+ xnp_lpa);
+ }
+ if (common & ADVERTISED_10000baseT_Full) {
+ ecmd->speed = SPEED_10000;
+ ecmd->duplex = DUPLEX_FULL;
+ } else if (common & (ADVERTISED_1000baseT_Full |
+ ADVERTISED_1000baseT_Half)) {
+ ecmd->speed = SPEED_1000;
+ ecmd->duplex = !!(common & ADVERTISED_1000baseT_Full);
+ } else if (common & (ADVERTISED_100baseT_Full |
+ ADVERTISED_100baseT_Half)) {
+ ecmd->speed = SPEED_100;
+ ecmd->duplex = !!(common & ADVERTISED_100baseT_Full);
+ } else {
+ ecmd->speed = SPEED_10;
+ ecmd->duplex = !!(common & ADVERTISED_10baseT_Full);
+ }
+ } else {
+ /* Report forced settings */
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
+ MDIO_MMDREG_CTRL1);
+ ecmd->speed = (((reg & BMCR_SPEED1000) ? 100 : 1) *
+ ((reg & BMCR_SPEED100) ? 100 : 10));
+ ecmd->duplex = (reg & BMCR_FULLDPLX ||
+ ecmd->speed == SPEED_10000);
+ }
}
/**
* mdio_clause45_set_settings - Set (some of) the PHY settings over MDIO.
* @efx: Efx NIC
* @ecmd: New settings
- *
- * Currently this just enforces that we are _not_ changing the
- * 'port', 'speed', 'supported' or 'advertising' settings as these
- * cannot be changed on any currently supported PHY.
*/
int mdio_clause45_set_settings(struct efx_nic *efx,
struct ethtool_cmd *ecmd)
{
- struct ethtool_cmd tmpcmd;
- mdio_clause45_get_settings(efx, &tmpcmd);
- /* None of the current PHYs support more than one mode
- * of operation (and only 10GBT ever will), so keep things
- * simple for now */
- if ((ecmd->speed == tmpcmd.speed) && (ecmd->port == tmpcmd.port) &&
- (ecmd->supported == tmpcmd.supported) &&
- (ecmd->advertising == tmpcmd.advertising))
+ int phy_id = efx->mii.phy_id;
+ struct ethtool_cmd prev;
+ u32 required;
+ int ctrl1_bits, reg;
+
+ efx->phy_op->get_settings(efx, &prev);
+
+ if (ecmd->advertising == prev.advertising &&
+ ecmd->speed == prev.speed &&
+ ecmd->duplex == prev.duplex &&
+ ecmd->port == prev.port &&
+ ecmd->autoneg == prev.autoneg)
return 0;
- return -EOPNOTSUPP;
+
+ /* We can only change these settings for -T PHYs */
+ if (prev.port != PORT_TP || ecmd->port != PORT_TP)
+ return -EINVAL;
+
+ /* Check that PHY supports these settings and work out the
+ * basic control bits */
+ if (ecmd->duplex) {
+ switch (ecmd->speed) {
+ case SPEED_10:
+ ctrl1_bits = BMCR_FULLDPLX;
+ required = SUPPORTED_10baseT_Full;
+ break;
+ case SPEED_100:
+ ctrl1_bits = BMCR_SPEED100 | BMCR_FULLDPLX;
+ required = SUPPORTED_100baseT_Full;
+ break;
+ case SPEED_1000:
+ ctrl1_bits = BMCR_SPEED1000 | BMCR_FULLDPLX;
+ required = SUPPORTED_1000baseT_Full;
+ break;
+ case SPEED_10000:
+ ctrl1_bits = (BMCR_SPEED1000 | BMCR_SPEED100 |
+ BMCR_FULLDPLX);
+ required = SUPPORTED_10000baseT_Full;
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else {
+ switch (ecmd->speed) {
+ case SPEED_10:
+ ctrl1_bits = 0;
+ required = SUPPORTED_10baseT_Half;
+ break;
+ case SPEED_100:
+ ctrl1_bits = BMCR_SPEED100;
+ required = SUPPORTED_100baseT_Half;
+ break;
+ case SPEED_1000:
+ ctrl1_bits = BMCR_SPEED1000;
+ required = SUPPORTED_1000baseT_Half;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ if (ecmd->autoneg)
+ required |= SUPPORTED_Autoneg;
+ required |= ecmd->advertising;
+ if (required & ~prev.supported)
+ return -EINVAL;
+
+ /* Set the basic control bits */
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
+ MDIO_MMDREG_CTRL1);
+ reg &= ~(BMCR_SPEED1000 | BMCR_SPEED100 | BMCR_FULLDPLX | 0x003c);
+ reg |= ctrl1_bits;
+ mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, MDIO_MMDREG_CTRL1,
+ reg);
+
+ /* Set the AN registers */
+ if (ecmd->autoneg != prev.autoneg ||
+ ecmd->advertising != prev.advertising) {
+ bool xnp = false;
+
+ if (efx->phy_op->set_xnp_advertise)
+ xnp = efx->phy_op->set_xnp_advertise(efx,
+ ecmd->advertising);
+
+ if (ecmd->autoneg) {
+ reg = 0;
+ if (ecmd->advertising & ADVERTISED_10baseT_Half)
+ reg |= ADVERTISE_10HALF;
+ if (ecmd->advertising & ADVERTISED_10baseT_Full)
+ reg |= ADVERTISE_10FULL;
+ if (ecmd->advertising & ADVERTISED_100baseT_Half)
+ reg |= ADVERTISE_100HALF;
+ if (ecmd->advertising & ADVERTISED_100baseT_Full)
+ reg |= ADVERTISE_100FULL;
+ if (xnp)
+ reg |= ADVERTISE_RESV;
+ mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
+ MDIO_AN_ADVERTISE, reg);
+ }
+
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
+ MDIO_MMDREG_CTRL1);
+ if (ecmd->autoneg)
+ reg |= BMCR_ANENABLE | BMCR_ANRESTART;
+ else
+ reg &= ~BMCR_ANENABLE;
+ if (xnp)
+ reg |= 1 << MDIO_AN_CTRL_XNP_LBN;
+ else
+ reg &= ~(1 << MDIO_AN_CTRL_XNP_LBN);
+ mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
+ MDIO_MMDREG_CTRL1, reg);
+ }
+
+ return 0;
+}
+
+void mdio_clause45_set_pause(struct efx_nic *efx)
+{
+ int phy_id = efx->mii.phy_id;
+ int reg;
+
+ if (efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)) {
+ /* Set pause capability advertising */
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
+ MDIO_AN_ADVERTISE);
+ reg &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
+ reg |= efx_fc_advertise(efx->wanted_fc);
+ mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
+ MDIO_AN_ADVERTISE, reg);
+
+ /* Restart auto-negotiation */
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
+ MDIO_MMDREG_CTRL1);
+ if (reg & BMCR_ANENABLE) {
+ reg |= BMCR_ANRESTART;
+ mdio_clause45_write(efx, phy_id, MDIO_MMD_AN,
+ MDIO_MMDREG_CTRL1, reg);
+ }
+ }
+}
+
+enum efx_fc_type mdio_clause45_get_pause(struct efx_nic *efx)
+{
+ int phy_id = efx->mii.phy_id;
+ int lpa;
+
+ if (!(efx->phy_op->mmds & DEV_PRESENT_BIT(MDIO_MMD_AN)))
+ return efx->wanted_fc;
+ lpa = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN, MDIO_AN_LPA);
+ return efx_fc_resolve(efx->wanted_fc, lpa);
+}
+
+void mdio_clause45_set_flag(struct efx_nic *efx, u8 prt, u8 dev,
+ u16 addr, int bit, bool sense)
+{
+ int old_val = mdio_clause45_read(efx, prt, dev, addr);
+ int new_val;
+
+ if (sense)
+ new_val = old_val | (1 << bit);
+ else
+ new_val = old_val & ~(1 << bit);
+ if (old_val != new_val)
+ mdio_clause45_write(efx, prt, dev, addr, new_val);
}
diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h
index 19c42eaf7fb4..09bf801d0569 100644
--- a/drivers/net/sfc/mdio_10g.h
+++ b/drivers/net/sfc/mdio_10g.h
@@ -33,6 +33,8 @@
#define MDIO_MMD_TC (6)
/* Auto negotiation */
#define MDIO_MMD_AN (7)
+/* Clause 22 extension */
+#define MDIO_MMD_C22EXT 29
/* Generic register locations */
#define MDIO_MMDREG_CTRL1 (0)
@@ -54,6 +56,9 @@
/* Loopback bit for WIS, PCS, PHYSX and DTEXS */
#define MDIO_MMDREG_CTRL1_LBACK_LBN (14)
#define MDIO_MMDREG_CTRL1_LBACK_WIDTH (1)
+/* Low power */
+#define MDIO_MMDREG_CTRL1_LPOWER_LBN (11)
+#define MDIO_MMDREG_CTRL1_LPOWER_WIDTH (1)
/* Bits in MMDREG_STAT1 */
#define MDIO_MMDREG_STAT1_FAULT_LBN (7)
@@ -70,14 +75,26 @@
#define MDIO_ID_MODEL(_id32) ((_id32 >> 4) & 0x3f)
#define MDIO_ID_OUI(_id32) (_id32 >> 10)
-/* Bits in MMDREG_DEVS0. Someone thoughtfully layed things out
+/* Bits in MMDREG_DEVS0/1. Someone thoughtfully layed things out
* so the 'bit present' bit number of an MMD is the number of
* that MMD */
#define DEV_PRESENT_BIT(_b) (1 << _b)
-#define MDIO_MMDREG_DEVS0_PHYXS DEV_PRESENT_BIT(MDIO_MMD_PHYXS)
-#define MDIO_MMDREG_DEVS0_PCS DEV_PRESENT_BIT(MDIO_MMD_PCS)
-#define MDIO_MMDREG_DEVS0_PMAPMD DEV_PRESENT_BIT(MDIO_MMD_PMAPMD)
+#define MDIO_MMDREG_DEVS_PHYXS DEV_PRESENT_BIT(MDIO_MMD_PHYXS)
+#define MDIO_MMDREG_DEVS_PCS DEV_PRESENT_BIT(MDIO_MMD_PCS)
+#define MDIO_MMDREG_DEVS_PMAPMD DEV_PRESENT_BIT(MDIO_MMD_PMAPMD)
+#define MDIO_MMDREG_DEVS_AN DEV_PRESENT_BIT(MDIO_MMD_AN)
+#define MDIO_MMDREG_DEVS_C22EXT DEV_PRESENT_BIT(MDIO_MMD_C22EXT)
+
+/* Bits in MMDREG_SPEED */
+#define MDIO_MMDREG_SPEED_10G_LBN 0
+#define MDIO_MMDREG_SPEED_10G_WIDTH 1
+#define MDIO_MMDREG_SPEED_1000M_LBN 4
+#define MDIO_MMDREG_SPEED_1000M_WIDTH 1
+#define MDIO_MMDREG_SPEED_100M_LBN 5
+#define MDIO_MMDREG_SPEED_100M_WIDTH 1
+#define MDIO_MMDREG_SPEED_10M_LBN 6
+#define MDIO_MMDREG_SPEED_10M_WIDTH 1
/* Bits in MMDREG_STAT2 */
#define MDIO_MMDREG_STAT2_PRESENT_VAL (2)
@@ -111,17 +128,34 @@
#define MDIO_PMAPMD_CTRL2_10_BT (0xf)
#define MDIO_PMAPMD_CTRL2_TYPE_MASK (0xf)
+/* PMA 10GBT registers */
+#define MDIO_PMAPMD_10GBT_TXPWR (131)
+#define MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN (0)
+#define MDIO_PMAPMD_10GBT_TXPWR_SHORT_WIDTH (1)
+
+/* PHY XGXS Status 2 */
+#define MDIO_PHYXS_STATUS2 (8)
+#define MDIO_PHYXS_STATUS2_RX_FAULT_LBN 10
+
/* PHY XGXS lane state */
#define MDIO_PHYXS_LANE_STATE (0x18)
#define MDIO_PHYXS_LANE_ALIGNED_LBN (12)
/* AN registers */
+#define MDIO_AN_CTRL_XNP_LBN 13
#define MDIO_AN_STATUS (1)
#define MDIO_AN_STATUS_XNP_LBN (7)
#define MDIO_AN_STATUS_PAGE_LBN (6)
#define MDIO_AN_STATUS_AN_DONE_LBN (5)
#define MDIO_AN_STATUS_LP_AN_CAP_LBN (0)
+#define MDIO_AN_ADVERTISE 16
+#define MDIO_AN_ADVERTISE_XNP_LBN 12
+#define MDIO_AN_LPA 19
+#define MDIO_AN_XNP 22
+#define MDIO_AN_LPA_XNP 25
+
+#define MDIO_AN_10GBT_ADVERTISE 32
#define MDIO_AN_10GBT_STATUS (33)
#define MDIO_AN_10GBT_STATUS_MS_FLT_LBN (15) /* MASTER/SLAVE config fault */
#define MDIO_AN_10GBT_STATUS_MS_LBN (14) /* MASTER/SLAVE config */
@@ -240,16 +274,37 @@ extern void mdio_clause45_transmit_disable(struct efx_nic *efx);
/* Generic part of reconfigure: set/clear loopback bits */
extern void mdio_clause45_phy_reconfigure(struct efx_nic *efx);
+/* Set the power state of the specified MMDs */
+extern void mdio_clause45_set_mmds_lpower(struct efx_nic *efx,
+ int low_power, unsigned int mmd_mask);
+
/* Read (some of) the PHY settings over MDIO */
extern void mdio_clause45_get_settings(struct efx_nic *efx,
struct ethtool_cmd *ecmd);
+/* Read (some of) the PHY settings over MDIO */
+extern void
+mdio_clause45_get_settings_ext(struct efx_nic *efx, struct ethtool_cmd *ecmd,
+ u32 xnp, u32 xnp_lpa);
+
/* Set (some of) the PHY settings over MDIO */
extern int mdio_clause45_set_settings(struct efx_nic *efx,
struct ethtool_cmd *ecmd);
+/* Set pause parameters to be advertised through AN (if available) */
+extern void mdio_clause45_set_pause(struct efx_nic *efx);
+
+/* Get pause parameters from AN if available (otherwise return
+ * requested pause parameters)
+ */
+enum efx_fc_type mdio_clause45_get_pause(struct efx_nic *efx);
+
/* Wait for specified MMDs to exit reset within a timeout */
extern int mdio_clause45_wait_reset_mmds(struct efx_nic *efx,
unsigned int mmd_mask);
+/* Set or clear flag, debouncing */
+extern void mdio_clause45_set_flag(struct efx_nic *efx, u8 prt, u8 dev,
+ u16 addr, int bit, bool sense);
+
#endif /* EFX_MDIO_10G_H */
diff --git a/drivers/net/sfc/mtd.c b/drivers/net/sfc/mtd.c
new file mode 100644
index 000000000000..665cafb88d6a
--- /dev/null
+++ b/drivers/net/sfc/mtd.c
@@ -0,0 +1,268 @@
+/****************************************************************************
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2005-2006 Fen Systems Ltd.
+ * Copyright 2006-2008 Solarflare Communications Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation, incorporated herein by reference.
+ */
+
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/delay.h>
+
+#define EFX_DRIVER_NAME "sfc_mtd"
+#include "net_driver.h"
+#include "spi.h"
+
+#define EFX_SPI_VERIFY_BUF_LEN 16
+
+struct efx_mtd {
+ const struct efx_spi_device *spi;
+ struct mtd_info mtd;
+ char name[IFNAMSIZ + 20];
+};
+
+/* SPI utilities */
+
+static int efx_spi_slow_wait(struct efx_mtd *efx_mtd, bool uninterruptible)
+{
+ const struct efx_spi_device *spi = efx_mtd->spi;
+ struct efx_nic *efx = spi->efx;
+ u8 status;
+ int rc, i;
+
+ /* Wait up to 4s for flash/EEPROM to finish a slow operation. */
+ for (i = 0; i < 40; i++) {
+ __set_current_state(uninterruptible ?
+ TASK_UNINTERRUPTIBLE : TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ / 10);
+ rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL,
+ &status, sizeof(status));
+ if (rc)
+ return rc;
+ if (!(status & SPI_STATUS_NRDY))
+ return 0;
+ if (signal_pending(current))
+ return -EINTR;
+ }
+ EFX_ERR(efx, "timed out waiting for %s\n", efx_mtd->name);
+ return -ETIMEDOUT;
+}
+
+static int efx_spi_unlock(const struct efx_spi_device *spi)
+{
+ const u8 unlock_mask = (SPI_STATUS_BP2 | SPI_STATUS_BP1 |
+ SPI_STATUS_BP0);
+ u8 status;
+ int rc;
+
+ rc = falcon_spi_cmd(spi, SPI_RDSR, -1, NULL, &status, sizeof(status));
+ if (rc)
+ return rc;
+
+ if (!(status & unlock_mask))
+ return 0; /* already unlocked */
+
+ rc = falcon_spi_cmd(spi, SPI_WREN, -1, NULL, NULL, 0);
+ if (rc)
+ return rc;
+ rc = falcon_spi_cmd(spi, SPI_SST_EWSR, -1, NULL, NULL, 0);
+ if (rc)
+ return rc;
+
+ status &= ~unlock_mask;
+ rc = falcon_spi_cmd(spi, SPI_WRSR, -1, &status, NULL, sizeof(status));
+ if (rc)
+ return rc;
+ rc = falcon_spi_wait_write(spi);
+ if (rc)
+ return rc;
+
+ return 0;
+}
+
+static int efx_spi_erase(struct efx_mtd *efx_mtd, loff_t start, size_t len)
+{
+ const struct efx_spi_device *spi = efx_mtd->spi;
+ unsigned pos, block_len;
+ u8 empty[EFX_SPI_VERIFY_BUF_LEN];
+ u8 buffer[EFX_SPI_VERIFY_BUF_LEN];
+ int rc;
+
+ if (len != spi->erase_size)
+ return -EINVAL;
+
+ if (spi->erase_command == 0)
+ return -EOPNOTSUPP;
+
+ rc = efx_spi_unlock(spi);
+ if (rc)
+ return rc;
+ rc = falcon_spi_cmd(spi, SPI_WREN, -1, NULL, NULL, 0);
+ if (rc)
+ return rc;
+ rc = falcon_spi_cmd(spi, spi->erase_command, start, NULL, NULL, 0);
+ if (rc)
+ return rc;
+ rc = efx_spi_slow_wait(efx_mtd, false);
+
+ /* Verify the entire region has been wiped */
+ memset(empty, 0xff, sizeof(empty));
+ for (pos = 0; pos < len; pos += block_len) {
+ block_len = min(len - pos, sizeof(buffer));
+ rc = falcon_spi_read(spi, start + pos, block_len, NULL, buffer);
+ if (rc)
+ return rc;
+ if (memcmp(empty, buffer, block_len))
+ return -EIO;
+
+ /* Avoid locking up the system */
+ cond_resched();
+ if (signal_pending(current))
+ return -EINTR;
+ }
+
+ return rc;
+}
+
+/* MTD interface */
+
+static int efx_mtd_read(struct mtd_info *mtd, loff_t start, size_t len,
+ size_t *retlen, u8 *buffer)
+{
+ struct efx_mtd *efx_mtd = mtd->priv;
+ const struct efx_spi_device *spi = efx_mtd->spi;
+ struct efx_nic *efx = spi->efx;
+ int rc;
+
+ rc = mutex_lock_interruptible(&efx->spi_lock);
+ if (rc)
+ return rc;
+ rc = falcon_spi_read(spi, FALCON_FLASH_BOOTCODE_START + start,
+ len, retlen, buffer);
+ mutex_unlock(&efx->spi_lock);
+ return rc;
+}
+
+static int efx_mtd_erase(struct mtd_info *mtd, struct erase_info *erase)
+{
+ struct efx_mtd *efx_mtd = mtd->priv;
+ struct efx_nic *efx = efx_mtd->spi->efx;
+ int rc;
+
+ rc = mutex_lock_interruptible(&efx->spi_lock);
+ if (rc)
+ return rc;
+ rc = efx_spi_erase(efx_mtd, FALCON_FLASH_BOOTCODE_START + erase->addr,
+ erase->len);
+ mutex_unlock(&efx->spi_lock);
+
+ if (rc == 0) {
+ erase->state = MTD_ERASE_DONE;
+ } else {
+ erase->state = MTD_ERASE_FAILED;
+ erase->fail_addr = 0xffffffff;
+ }
+ mtd_erase_callback(erase);
+ return rc;
+}
+
+static int efx_mtd_write(struct mtd_info *mtd, loff_t start,
+ size_t len, size_t *retlen, const u8 *buffer)
+{
+ struct efx_mtd *efx_mtd = mtd->priv;
+ const struct efx_spi_device *spi = efx_mtd->spi;
+ struct efx_nic *efx = spi->efx;
+ int rc;
+
+ rc = mutex_lock_interruptible(&efx->spi_lock);
+ if (rc)
+ return rc;
+ rc = falcon_spi_write(spi, FALCON_FLASH_BOOTCODE_START + start,
+ len, retlen, buffer);
+ mutex_unlock(&efx->spi_lock);
+ return rc;
+}
+
+static void efx_mtd_sync(struct mtd_info *mtd)
+{
+ struct efx_mtd *efx_mtd = mtd->priv;
+ struct efx_nic *efx = efx_mtd->spi->efx;
+ int rc;
+
+ mutex_lock(&efx->spi_lock);
+ rc = efx_spi_slow_wait(efx_mtd, true);
+ mutex_unlock(&efx->spi_lock);
+
+ if (rc)
+ EFX_ERR(efx, "%s sync failed (%d)\n", efx_mtd->name, rc);
+ return;
+}
+
+void efx_mtd_remove(struct efx_nic *efx)
+{
+ if (efx->spi_flash && efx->spi_flash->mtd) {
+ struct efx_mtd *efx_mtd = efx->spi_flash->mtd;
+ int rc;
+
+ for (;;) {
+ rc = del_mtd_device(&efx_mtd->mtd);
+ if (rc != -EBUSY)
+ break;
+ ssleep(1);
+ }
+ WARN_ON(rc);
+ kfree(efx_mtd);
+ }
+}
+
+void efx_mtd_rename(struct efx_nic *efx)
+{
+ if (efx->spi_flash && efx->spi_flash->mtd) {
+ struct efx_mtd *efx_mtd = efx->spi_flash->mtd;
+ snprintf(efx_mtd->name, sizeof(efx_mtd->name),
+ "%s sfc_flash_bootrom", efx->name);
+ }
+}
+
+int efx_mtd_probe(struct efx_nic *efx)
+{
+ struct efx_spi_device *spi = efx->spi_flash;
+ struct efx_mtd *efx_mtd;
+
+ if (!spi || spi->size <= FALCON_FLASH_BOOTCODE_START)
+ return -ENODEV;
+
+ efx_mtd = kzalloc(sizeof(*efx_mtd), GFP_KERNEL);
+ if (!efx_mtd)
+ return -ENOMEM;
+
+ efx_mtd->spi = spi;
+ spi->mtd = efx_mtd;
+
+ efx_mtd->mtd.type = MTD_NORFLASH;
+ efx_mtd->mtd.flags = MTD_CAP_NORFLASH;
+ efx_mtd->mtd.size = spi->size - FALCON_FLASH_BOOTCODE_START;
+ efx_mtd->mtd.erasesize = spi->erase_size;
+ efx_mtd->mtd.writesize = 1;
+ efx_mtd_rename(efx);
+
+ efx_mtd->mtd.owner = THIS_MODULE;
+ efx_mtd->mtd.priv = efx_mtd;
+ efx_mtd->mtd.name = efx_mtd->name;
+ efx_mtd->mtd.erase = efx_mtd_erase;
+ efx_mtd->mtd.read = efx_mtd_read;
+ efx_mtd->mtd.write = efx_mtd_write;
+ efx_mtd->mtd.sync = efx_mtd_sync;
+
+ if (add_mtd_device(&efx_mtd->mtd)) {
+ kfree(efx_mtd);
+ spi->mtd = NULL;
+ /* add_mtd_device() returns 1 if the MTD table is full */
+ return -ENOMEM;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index cdb11fad6050..5f255f75754e 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -42,7 +42,7 @@
#ifndef EFX_DRIVER_NAME
#define EFX_DRIVER_NAME "sfc"
#endif
-#define EFX_DRIVER_VERSION "2.2"
+#define EFX_DRIVER_VERSION "2.3"
#ifdef EFX_ENABLE_DEBUG
#define EFX_BUG_ON_PARANOID(x) BUG_ON(x)
@@ -327,6 +327,7 @@ enum efx_rx_alloc_method {
*
* @efx: Associated Efx NIC
* @channel: Channel instance number
+ * @name: Name for channel and IRQ
* @used_flags: Channel is used by net driver
* @enabled: Channel enabled indicator
* @irq: IRQ number (MSI and MSI-X only)
@@ -357,6 +358,7 @@ enum efx_rx_alloc_method {
struct efx_channel {
struct efx_nic *efx;
int channel;
+ char name[IFNAMSIZ + 6];
int used_flags;
bool enabled;
int irq;
@@ -414,6 +416,7 @@ struct efx_blinker {
* @init_leds: Sets up board LEDs
* @set_fault_led: Turns the fault LED on or off
* @blink: Starts/stops blinking
+ * @monitor: Board-specific health check function
* @fini: Cleanup function
* @blinker: used to blink LEDs in software
* @hwmon_client: I2C client for hardware monitor
@@ -428,6 +431,7 @@ struct efx_board {
* have a separate init callback that happens later than
* board init. */
int (*init_leds)(struct efx_nic *efx);
+ int (*monitor) (struct efx_nic *nic);
void (*set_fault_led) (struct efx_nic *efx, bool state);
void (*blink) (struct efx_nic *efx, bool start);
void (*fini) (struct efx_nic *nic);
@@ -449,16 +453,20 @@ enum efx_int_mode {
enum phy_type {
PHY_TYPE_NONE = 0,
- PHY_TYPE_CX4_RTMR = 1,
- PHY_TYPE_1G_ALASKA = 2,
- PHY_TYPE_10XPRESS = 3,
- PHY_TYPE_XFP = 4,
+ PHY_TYPE_TXC43128 = 1,
+ PHY_TYPE_88E1111 = 2,
+ PHY_TYPE_SFX7101 = 3,
+ PHY_TYPE_QT2022C2 = 4,
PHY_TYPE_PM8358 = 6,
+ PHY_TYPE_SFT9001A = 8,
+ PHY_TYPE_SFT9001B = 10,
PHY_TYPE_MAX /* Insert any new items before this */
};
#define PHY_ADDR_INVALID 0xff
+#define EFX_IS10G(efx) ((efx)->link_speed == 10000)
+
enum nic_state {
STATE_INIT = 0,
STATE_RUNNING = 1,
@@ -499,6 +507,55 @@ enum efx_fc_type {
EFX_FC_AUTO = 4,
};
+/* Supported MAC bit-mask */
+enum efx_mac_type {
+ EFX_GMAC = 1,
+ EFX_XMAC = 2,
+};
+
+static inline unsigned int efx_fc_advertise(enum efx_fc_type wanted_fc)
+{
+ unsigned int adv = 0;
+ if (wanted_fc & EFX_FC_RX)
+ adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
+ if (wanted_fc & EFX_FC_TX)
+ adv ^= ADVERTISE_PAUSE_ASYM;
+ return adv;
+}
+
+static inline enum efx_fc_type efx_fc_resolve(enum efx_fc_type wanted_fc,
+ unsigned int lpa)
+{
+ unsigned int adv = efx_fc_advertise(wanted_fc);
+
+ if (!(wanted_fc & EFX_FC_AUTO))
+ return wanted_fc;
+
+ if (adv & lpa & ADVERTISE_PAUSE_CAP)
+ return EFX_FC_RX | EFX_FC_TX;
+ if (adv & lpa & ADVERTISE_PAUSE_ASYM) {
+ if (adv & ADVERTISE_PAUSE_CAP)
+ return EFX_FC_RX;
+ if (lpa & ADVERTISE_PAUSE_CAP)
+ return EFX_FC_TX;
+ }
+ return 0;
+}
+
+/**
+ * struct efx_mac_operations - Efx MAC operations table
+ * @reconfigure: Reconfigure MAC. Serialised by the mac_lock
+ * @update_stats: Update statistics
+ * @irq: Hardware MAC event callback. Serialised by the mac_lock
+ * @poll: Poll for hardware state. Serialised by the mac_lock
+ */
+struct efx_mac_operations {
+ void (*reconfigure) (struct efx_nic *efx);
+ void (*update_stats) (struct efx_nic *efx);
+ void (*irq) (struct efx_nic *efx);
+ void (*poll) (struct efx_nic *efx);
+};
+
/**
* struct efx_phy_operations - Efx PHY operations table
* @init: Initialise PHY
@@ -506,17 +563,33 @@ enum efx_fc_type {
* @reconfigure: Reconfigure PHY (e.g. for new link parameters)
* @clear_interrupt: Clear down interrupt
* @blink: Blink LEDs
- * @check_hw: Check hardware
+ * @poll: Poll for hardware state. Serialised by the mac_lock.
+ * @get_settings: Get ethtool settings. Serialised by the mac_lock.
+ * @set_settings: Set ethtool settings. Serialised by the mac_lock.
+ * @set_xnp_advertise: Set abilities advertised in Extended Next Page
+ * (only needed where AN bit is set in mmds)
+ * @num_tests: Number of PHY-specific tests/results
+ * @test_names: Names of the tests/results
+ * @run_tests: Run tests and record results as appropriate.
+ * Flags are the ethtool tests flags.
* @mmds: MMD presence mask
* @loopbacks: Supported loopback modes mask
*/
struct efx_phy_operations {
+ enum efx_mac_type macs;
int (*init) (struct efx_nic *efx);
void (*fini) (struct efx_nic *efx);
void (*reconfigure) (struct efx_nic *efx);
void (*clear_interrupt) (struct efx_nic *efx);
- int (*check_hw) (struct efx_nic *efx);
- int (*test) (struct efx_nic *efx);
+ void (*poll) (struct efx_nic *efx);
+ void (*get_settings) (struct efx_nic *efx,
+ struct ethtool_cmd *ecmd);
+ int (*set_settings) (struct efx_nic *efx,
+ struct ethtool_cmd *ecmd);
+ bool (*set_xnp_advertise) (struct efx_nic *efx, u32);
+ u32 num_tests;
+ const char *const *test_names;
+ int (*run_tests) (struct efx_nic *efx, int *results, unsigned flags);
int mmds;
unsigned loopbacks;
};
@@ -525,11 +598,15 @@ struct efx_phy_operations {
* @enum efx_phy_mode - PHY operating mode flags
* @PHY_MODE_NORMAL: on and should pass traffic
* @PHY_MODE_TX_DISABLED: on with TX disabled
+ * @PHY_MODE_LOW_POWER: set to low power through MDIO
+ * @PHY_MODE_OFF: switched off through external control
* @PHY_MODE_SPECIAL: on but will not pass traffic
*/
enum efx_phy_mode {
PHY_MODE_NORMAL = 0,
PHY_MODE_TX_DISABLED = 1,
+ PHY_MODE_LOW_POWER = 2,
+ PHY_MODE_OFF = 4,
PHY_MODE_SPECIAL = 8,
};
@@ -629,7 +706,7 @@ union efx_multicast_hash {
* @legacy_irq: IRQ number
* @workqueue: Workqueue for port reconfigures and the HW monitor.
* Work items do not hold and must not acquire RTNL.
- * @reset_workqueue: Workqueue for resets. Work item will acquire RTNL.
+ * @workqueue_name: Name of workqueue
* @reset_work: Scheduled reset workitem
* @monitor_work: Hardware monitor workitem
* @membase_phys: Memory BAR value as physical address
@@ -644,6 +721,7 @@ union efx_multicast_hash {
* @rx_queue: RX DMA queues
* @channel: Channels
* @n_rx_queues: Number of RX queues
+ * @n_channels: Number of channels in use
* @rx_buffer_len: RX buffer length
* @rx_buffer_order: Order (log2) of number of pages for each RX buffer
* @irq_status: Interrupt status buffer
@@ -655,15 +733,16 @@ union efx_multicast_hash {
* This field will be %NULL if no flash device is present.
* @spi_eeprom: SPI EEPROM device
* This field will be %NULL if no EEPROM device is present.
+ * @spi_lock: SPI bus lock
* @n_rx_nodesc_drop_cnt: RX no descriptor drop count
* @nic_data: Hardware dependant state
* @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode,
* @port_inhibited, efx_monitor() and efx_reconfigure_port()
* @port_enabled: Port enabled indicator.
- * Serialises efx_stop_all(), efx_start_all() and efx_monitor() and
- * efx_reconfigure_work with kernel interfaces. Safe to read under any
- * one of the rtnl_lock, mac_lock, or netif_tx_lock, but all three must
- * be held to modify it.
+ * Serialises efx_stop_all(), efx_start_all(), efx_monitor(),
+ * efx_phy_work(), and efx_mac_work() with kernel interfaces. Safe to read
+ * under any one of the rtnl_lock, mac_lock, or netif_tx_lock, but all
+ * three must be held to modify it.
* @port_inhibited: If set, the netif_carrier is always off. Hold the mac_lock
* @port_initialized: Port initialized?
* @net_dev: Operating system network device. Consider holding the rtnl lock
@@ -677,6 +756,7 @@ union efx_multicast_hash {
* @stats_lock: Statistics update lock. Serialises statistics fetches
* @stats_enabled: Temporarily disable statistics fetches.
* Serialised by @stats_lock
+ * @mac_op: MAC interface
* @mac_address: Permanent MAC address
* @phy_type: PHY type
* @phy_lock: PHY access lock
@@ -684,13 +764,17 @@ union efx_multicast_hash {
* @phy_data: PHY private data (including PHY-specific stats)
* @mii: PHY interface
* @phy_mode: PHY operating mode. Serialised by @mac_lock.
+ * @mac_up: MAC link state
* @link_up: Link status
- * @link_options: Link options (MII/GMII format)
+ * @link_fd: Link is full duplex
+ * @link_fc: Actualy flow control flags
+ * @link_speed: Link speed (Mbps)
* @n_link_state_changes: Number of times the link has changed state
* @promiscuous: Promiscuous flag. Protected by netif_tx_lock.
* @multicast_hash: Multicast hash table
- * @flow_control: Flow control flags - separate RX/TX so can't use link_options
- * @reconfigure_work: work item for dealing with PHY events
+ * @wanted_fc: Wanted flow control flags
+ * @phy_work: work item for dealing with PHY events
+ * @mac_work: work item for dealing with MAC events
* @loopback_mode: Loopback status
* @loopback_modes: Supported loopback mode bitmask
* @loopback_selftest: Offline self-test private state
@@ -704,7 +788,7 @@ struct efx_nic {
const struct efx_nic_type *type;
int legacy_irq;
struct workqueue_struct *workqueue;
- struct workqueue_struct *reset_workqueue;
+ char workqueue_name[16];
struct work_struct reset_work;
struct delayed_work monitor_work;
resource_size_t membase_phys;
@@ -723,6 +807,7 @@ struct efx_nic {
struct efx_channel channel[EFX_MAX_CHANNELS];
int n_rx_queues;
+ int n_channels;
unsigned int rx_buffer_len;
unsigned int rx_buffer_order;
@@ -731,12 +816,14 @@ struct efx_nic {
struct efx_spi_device *spi_flash;
struct efx_spi_device *spi_eeprom;
+ struct mutex spi_lock;
unsigned n_rx_nodesc_drop_cnt;
struct falcon_nic_data *nic_data;
struct mutex mac_lock;
+ struct work_struct mac_work;
bool port_enabled;
bool port_inhibited;
@@ -752,23 +839,27 @@ struct efx_nic {
spinlock_t stats_lock;
bool stats_enabled;
+ struct efx_mac_operations *mac_op;
unsigned char mac_address[ETH_ALEN];
enum phy_type phy_type;
spinlock_t phy_lock;
+ struct work_struct phy_work;
struct efx_phy_operations *phy_op;
void *phy_data;
struct mii_if_info mii;
enum efx_phy_mode phy_mode;
+ bool mac_up;
bool link_up;
- unsigned int link_options;
+ bool link_fd;
+ enum efx_fc_type link_fc;
+ unsigned int link_speed;
unsigned int n_link_state_changes;
bool promiscuous;
union efx_multicast_hash multicast_hash;
- enum efx_fc_type flow_control;
- struct work_struct reconfigure_work;
+ enum efx_fc_type wanted_fc;
atomic_t rx_reset;
enum efx_loopback_mode loopback_mode;
diff --git a/drivers/net/sfc/phy.h b/drivers/net/sfc/phy.h
index f746536f4ffa..58c493ef81bb 100644
--- a/drivers/net/sfc/phy.h
+++ b/drivers/net/sfc/phy.h
@@ -1,6 +1,6 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2007 Solarflare Communications Inc.
+ * Copyright 2007-2008 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@@ -11,9 +11,10 @@
#define EFX_PHY_H
/****************************************************************************
- * 10Xpress (SFX7101) PHY
+ * 10Xpress (SFX7101 and SFT9001) PHYs
*/
-extern struct efx_phy_operations falcon_tenxpress_phy_ops;
+extern struct efx_phy_operations falcon_sfx7101_phy_ops;
+extern struct efx_phy_operations falcon_sft9001_phy_ops;
extern void tenxpress_phy_blink(struct efx_nic *efx, bool blink);
extern void tenxpress_crc_err(struct efx_nic *efx);
diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c
index 0f805da4ce55..b8ba4bbad889 100644
--- a/drivers/net/sfc/rx.c
+++ b/drivers/net/sfc/rx.c
@@ -752,7 +752,7 @@ void __efx_rx_packet(struct efx_channel *channel,
channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB;
done:
- efx->net_dev->last_rx = jiffies;
+ ;
}
void efx_rx_strategy(struct efx_channel *channel)
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c
index 362956e3fe17..dba0d64d50cd 100644
--- a/drivers/net/sfc/selftest.c
+++ b/drivers/net/sfc/selftest.c
@@ -26,7 +26,6 @@
#include "selftest.h"
#include "boards.h"
#include "workarounds.h"
-#include "mac.h"
#include "spi.h"
#include "falcon_io.h"
#include "mdio_10g.h"
@@ -105,9 +104,11 @@ static int efx_test_mii(struct efx_nic *efx, struct efx_self_tests *tests)
goto out;
}
- rc = mdio_clause45_check_mmds(efx, efx->phy_op->mmds, 0);
- if (rc)
- goto out;
+ if (EFX_IS10G(efx)) {
+ rc = mdio_clause45_check_mmds(efx, efx->phy_op->mmds, 0);
+ if (rc)
+ goto out;
+ }
out:
mutex_unlock(&efx->mac_lock);
@@ -246,17 +247,20 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
return 0;
}
-static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests)
+static int efx_test_phy(struct efx_nic *efx, struct efx_self_tests *tests,
+ unsigned flags)
{
int rc;
- if (!efx->phy_op->test)
+ if (!efx->phy_op->run_tests)
return 0;
+ EFX_BUG_ON_PARANOID(efx->phy_op->num_tests == 0 ||
+ efx->phy_op->num_tests > EFX_MAX_PHY_TESTS);
+
mutex_lock(&efx->mac_lock);
- rc = efx->phy_op->test(efx);
+ rc = efx->phy_op->run_tests(efx, tests->phy, flags);
mutex_unlock(&efx->mac_lock);
- tests->phy = rc ? -1 : 1;
return rc;
}
@@ -563,8 +567,7 @@ efx_test_loopback(struct efx_tx_queue *tx_queue,
return 0;
}
-static int efx_test_loopbacks(struct efx_nic *efx, struct ethtool_cmd ecmd,
- struct efx_self_tests *tests,
+static int efx_test_loopbacks(struct efx_nic *efx, struct efx_self_tests *tests,
unsigned int loopback_modes)
{
enum efx_loopback_mode mode;
@@ -593,12 +596,14 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct ethtool_cmd ecmd,
efx->loopback_mode = mode;
efx_reconfigure_port(efx);
- /* Wait for the PHY to signal the link is up */
+ /* Wait for the PHY to signal the link is up. Interrupts
+ * are enabled for PHY's using LASI, otherwise we poll()
+ * quickly */
count = 0;
do {
struct efx_channel *channel = &efx->channel[0];
- falcon_check_xmac(efx);
+ efx->phy_op->poll(efx);
schedule_timeout_uninterruptible(HZ / 10);
if (channel->work_pending)
efx_process_channel_now(channel);
@@ -606,13 +611,12 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct ethtool_cmd ecmd,
flush_workqueue(efx->workqueue);
rmb();
- /* efx->link_up can be 1 even if the XAUI link is down,
- * (bug5762). Usually, it's not worth bothering with the
- * difference, but for selftests, we need that extra
- * guarantee that the link is really, really, up.
- */
+ /* We need both the phy and xaui links to be ok.
+ * rather than relying on the falcon_xmac irq/poll
+ * regime, just poll xaui directly */
link_up = efx->link_up;
- if (!falcon_xaui_link_ok(efx))
+ if (link_up && EFX_IS10G(efx) &&
+ !falcon_xaui_link_ok(efx))
link_up = false;
} while ((++count < 20) && !link_up);
@@ -652,47 +656,48 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct ethtool_cmd ecmd,
/**************************************************************************
*
- * Entry points
+ * Entry point
*
*************************************************************************/
-/* Online (i.e. non-disruptive) testing
- * This checks interrupt generation, event delivery and PHY presence. */
-int efx_online_test(struct efx_nic *efx, struct efx_self_tests *tests)
+int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
+ unsigned flags)
{
+ enum efx_loopback_mode loopback_mode = efx->loopback_mode;
+ int phy_mode = efx->phy_mode;
+ struct ethtool_cmd ecmd;
struct efx_channel *channel;
- int rc, rc2 = 0;
+ int rc_test = 0, rc_reset = 0, rc;
+
+ /* Online (i.e. non-disruptive) testing
+ * This checks interrupt generation, event delivery and PHY presence. */
rc = efx_test_mii(efx, tests);
- if (rc && !rc2)
- rc2 = rc;
+ if (rc && !rc_test)
+ rc_test = rc;
rc = efx_test_nvram(efx, tests);
- if (rc && !rc2)
- rc2 = rc;
+ if (rc && !rc_test)
+ rc_test = rc;
rc = efx_test_interrupts(efx, tests);
- if (rc && !rc2)
- rc2 = rc;
+ if (rc && !rc_test)
+ rc_test = rc;
efx_for_each_channel(channel, efx) {
rc = efx_test_eventq_irq(channel, tests);
- if (rc && !rc2)
- rc2 = rc;
+ if (rc && !rc_test)
+ rc_test = rc;
}
- return rc2;
-}
+ if (rc_test)
+ return rc_test;
-/* Offline (i.e. disruptive) testing
- * This checks MAC and PHY loopback on the specified port. */
-int efx_offline_test(struct efx_nic *efx,
- struct efx_self_tests *tests, unsigned int loopback_modes)
-{
- enum efx_loopback_mode loopback_mode = efx->loopback_mode;
- int phy_mode = efx->phy_mode;
- struct ethtool_cmd ecmd, ecmd_test;
- int rc, rc2 = 0;
+ if (!(flags & ETH_TEST_FL_OFFLINE))
+ return efx_test_phy(efx, tests, flags);
+
+ /* Offline (i.e. disruptive) testing
+ * This checks MAC and PHY loopback on the specified port. */
/* force the carrier state off so the kernel doesn't transmit during
* the loopback test, and the watchdog timeout doesn't fire. Also put
@@ -700,8 +705,15 @@ int efx_offline_test(struct efx_nic *efx,
*/
mutex_lock(&efx->mac_lock);
efx->port_inhibited = true;
- if (efx->loopback_modes)
- efx->loopback_mode = __ffs(efx->loopback_modes);
+ if (efx->loopback_modes) {
+ /* We need the 312 clock from the PHY to test the XMAC
+ * registers, so move into XGMII loopback if available */
+ if (efx->loopback_modes & (1 << LOOPBACK_XGMII))
+ efx->loopback_mode = LOOPBACK_XGMII;
+ else
+ efx->loopback_mode = __ffs(efx->loopback_modes);
+ }
+
__efx_reconfigure_port(efx);
mutex_unlock(&efx->mac_lock);
@@ -709,39 +721,34 @@ int efx_offline_test(struct efx_nic *efx,
efx_reset_down(efx, &ecmd);
rc = efx_test_chip(efx, tests);
- if (rc && !rc2)
- rc2 = rc;
+ if (rc && !rc_test)
+ rc_test = rc;
/* reset the chip to recover from the register test */
- rc = falcon_reset_hw(efx, RESET_TYPE_ALL);
-
- /* Modify the saved ecmd so that when efx_reset_up() restores the phy
- * state, AN is disabled, and the phy is powered, and out of loopback */
- memcpy(&ecmd_test, &ecmd, sizeof(ecmd_test));
- if (ecmd_test.autoneg == AUTONEG_ENABLE) {
- ecmd_test.autoneg = AUTONEG_DISABLE;
- ecmd_test.duplex = DUPLEX_FULL;
- ecmd_test.speed = SPEED_10000;
- }
+ rc_reset = falcon_reset_hw(efx, RESET_TYPE_ALL);
+
+ /* Ensure that the phy is powered and out of loopback
+ * for the bist and loopback tests */
+ efx->phy_mode &= ~PHY_MODE_LOW_POWER;
efx->loopback_mode = LOOPBACK_NONE;
- rc = efx_reset_up(efx, &ecmd_test, rc == 0);
- if (rc) {
+ rc = efx_reset_up(efx, &ecmd, rc_reset == 0);
+ if (rc && !rc_reset)
+ rc_reset = rc;
+
+ if (rc_reset) {
EFX_ERR(efx, "Unable to recover from chip test\n");
efx_schedule_reset(efx, RESET_TYPE_DISABLE);
- return rc;
+ return rc_reset;
}
- tests->loopback_speed = ecmd_test.speed;
- tests->loopback_full_duplex = ecmd_test.duplex;
-
- rc = efx_test_phy(efx, tests);
- if (rc && !rc2)
- rc2 = rc;
+ rc = efx_test_phy(efx, tests, flags);
+ if (rc && !rc_test)
+ rc_test = rc;
- rc = efx_test_loopbacks(efx, ecmd_test, tests, loopback_modes);
- if (rc && !rc2)
- rc2 = rc;
+ rc = efx_test_loopbacks(efx, tests, efx->loopback_modes);
+ if (rc && !rc_test)
+ rc_test = rc;
/* restore the PHY to the previous state */
efx->loopback_mode = loopback_mode;
@@ -749,6 +756,6 @@ int efx_offline_test(struct efx_nic *efx,
efx->port_inhibited = false;
efx_ethtool_set_settings(efx->net_dev, &ecmd);
- return rc2;
+ return rc_test;
}
diff --git a/drivers/net/sfc/selftest.h b/drivers/net/sfc/selftest.h
index fc15df15d766..39451cf938cf 100644
--- a/drivers/net/sfc/selftest.h
+++ b/drivers/net/sfc/selftest.h
@@ -24,6 +24,8 @@ struct efx_loopback_self_tests {
int rx_bad;
};
+#define EFX_MAX_PHY_TESTS 20
+
/* Efx self test results
* For fields which are not counters, 1 indicates success and -1
* indicates failure.
@@ -38,18 +40,14 @@ struct efx_self_tests {
int eventq_poll[EFX_MAX_CHANNELS];
/* offline tests */
int registers;
- int phy;
- int loopback_speed;
- int loopback_full_duplex;
+ int phy[EFX_MAX_PHY_TESTS];
struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX + 1];
};
extern void efx_loopback_rx_packet(struct efx_nic *efx,
const char *buf_ptr, int pkt_len);
-extern int efx_online_test(struct efx_nic *efx,
- struct efx_self_tests *tests);
-extern int efx_offline_test(struct efx_nic *efx,
- struct efx_self_tests *tests,
- unsigned int loopback_modes);
+extern int efx_selftest(struct efx_nic *efx,
+ struct efx_self_tests *tests,
+ unsigned flags);
#endif /* EFX_SELFTEST_H */
diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c
index fe4e3fd22330..16b80acb9992 100644
--- a/drivers/net/sfc/sfe4001.c
+++ b/drivers/net/sfc/sfe4001.c
@@ -1,6 +1,6 @@
/****************************************************************************
* Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2007 Solarflare Communications Inc.
+ * Copyright 2007-2008 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@@ -8,10 +8,21 @@
*/
/*****************************************************************************
- * Support for the SFE4001 NIC: driver code for the PCA9539 I/O expander that
- * controls the PHY power rails, and for the MAX6647 temp. sensor used to check
- * the PHY
+ * Support for the SFE4001 and SFN4111T NICs.
+ *
+ * The SFE4001 does not power-up fully at reset due to its high power
+ * consumption. We control its power via a PCA9539 I/O expander.
+ * Both boards have a MAX6647 temperature monitor which we expose to
+ * the lm90 driver.
+ *
+ * This also provides minimal support for reflashing the PHY, which is
+ * initiated by resetting it with the FLASH_CFG_1 pin pulled down.
+ * On SFE4001 rev A2 and later this is connected to the 3V3X output of
+ * the IO-expander; on the SFN4111T it is connected to Falcon's GPIO3.
+ * We represent reflash mode as PHY_MODE_SPECIAL and make it mutually
+ * exclusive with the network device being open.
*/
+
#include <linux/delay.h>
#include "net_driver.h"
#include "efx.h"
@@ -21,6 +32,7 @@
#include "falcon_hwdefs.h"
#include "falcon_io.h"
#include "mac.h"
+#include "workarounds.h"
/**************************************************************************
*
@@ -65,48 +77,9 @@
#define P1_SPARE_LBN 4
#define P1_SPARE_WIDTH 4
-
-/**************************************************************************
- *
- * Temperature Sensor
- *
- **************************************************************************/
-#define MAX6647 0x4e
-
-#define RLTS 0x00
-#define RLTE 0x01
-#define RSL 0x02
-#define RCL 0x03
-#define RCRA 0x04
-#define RLHN 0x05
-#define RLLI 0x06
-#define RRHI 0x07
-#define RRLS 0x08
-#define WCRW 0x0a
-#define WLHO 0x0b
-#define WRHA 0x0c
-#define WRLN 0x0e
-#define OSHT 0x0f
-#define REET 0x10
-#define RIET 0x11
-#define RWOE 0x19
-#define RWOI 0x20
-#define HYS 0x21
-#define QUEUE 0x22
-#define MFID 0xfe
-#define REVID 0xff
-
-/* Status bits */
-#define MAX6647_BUSY (1 << 7) /* ADC is converting */
-#define MAX6647_LHIGH (1 << 6) /* Local high temp. alarm */
-#define MAX6647_LLOW (1 << 5) /* Local low temp. alarm */
-#define MAX6647_RHIGH (1 << 4) /* Remote high temp. alarm */
-#define MAX6647_RLOW (1 << 3) /* Remote low temp. alarm */
-#define MAX6647_FAULT (1 << 2) /* DXN/DXP short/open circuit */
-#define MAX6647_EOT (1 << 1) /* Remote junction overtemp. */
-#define MAX6647_IOT (1 << 0) /* Local junction overtemp. */
-
-static const u8 xgphy_max_temperature = 90;
+/* Temperature Sensor */
+#define MAX664X_REG_RSL 0x02
+#define MAX664X_REG_WLHO 0x0B
static void sfe4001_poweroff(struct efx_nic *efx)
{
@@ -119,7 +92,7 @@ static void sfe4001_poweroff(struct efx_nic *efx)
i2c_smbus_write_byte_data(ioexp_client, P0_CONFIG, 0xff);
/* Clear any over-temperature alert */
- i2c_smbus_read_byte_data(hwmon_client, RSL);
+ i2c_smbus_read_byte_data(hwmon_client, MAX664X_REG_RSL);
}
static int sfe4001_poweron(struct efx_nic *efx)
@@ -131,7 +104,7 @@ static int sfe4001_poweron(struct efx_nic *efx)
u8 out;
/* Clear any previous over-temperature alert */
- rc = i2c_smbus_read_byte_data(hwmon_client, RSL);
+ rc = i2c_smbus_read_byte_data(hwmon_client, MAX664X_REG_RSL);
if (rc < 0)
return rc;
@@ -209,10 +182,29 @@ fail_on:
return rc;
}
-/* On SFE4001 rev A2 and later, we can control the FLASH_CFG_1 pin
- * using the 3V3X output of the IO-expander. Allow the user to set
- * this when the device is stopped, and keep it stopped then.
- */
+static int sfn4111t_reset(struct efx_nic *efx)
+{
+ efx_oword_t reg;
+
+ /* GPIO pins are also used for I2C, so block that temporarily */
+ mutex_lock(&efx->i2c_adap.bus_lock);
+
+ falcon_read(efx, &reg, GPIO_CTL_REG_KER);
+ EFX_SET_OWORD_FIELD(reg, GPIO2_OEN, true);
+ EFX_SET_OWORD_FIELD(reg, GPIO2_OUT, false);
+ falcon_write(efx, &reg, GPIO_CTL_REG_KER);
+ msleep(1000);
+ EFX_SET_OWORD_FIELD(reg, GPIO2_OUT, true);
+ EFX_SET_OWORD_FIELD(reg, GPIO3_OEN, true);
+ EFX_SET_OWORD_FIELD(reg, GPIO3_OUT,
+ !(efx->phy_mode & PHY_MODE_SPECIAL));
+ falcon_write(efx, &reg, GPIO_CTL_REG_KER);
+
+ mutex_unlock(&efx->i2c_adap.bus_lock);
+
+ ssleep(1);
+ return 0;
+}
static ssize_t show_phy_flash_cfg(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -241,7 +233,10 @@ static ssize_t set_phy_flash_cfg(struct device *dev,
err = -EBUSY;
} else {
efx->phy_mode = new_mode;
- err = sfe4001_poweron(efx);
+ if (efx->board_info.type == EFX_BOARD_SFE4001)
+ err = sfe4001_poweron(efx);
+ else
+ err = sfn4111t_reset(efx);
efx_reconfigure_port(efx);
}
rtnl_unlock();
@@ -261,35 +256,62 @@ static void sfe4001_fini(struct efx_nic *efx)
i2c_unregister_device(efx->board_info.hwmon_client);
}
+static int sfe4001_check_hw(struct efx_nic *efx)
+{
+ s32 status;
+
+ /* If XAUI link is up then do not monitor */
+ if (EFX_WORKAROUND_7884(efx) && efx->mac_up)
+ return 0;
+
+ /* Check the powered status of the PHY. Lack of power implies that
+ * the MAX6647 has shut down power to it, probably due to a temp.
+ * alarm. Reading the power status rather than the MAX6647 status
+ * directly because the later is read-to-clear and would thus
+ * start to power up the PHY again when polled, causing us to blip
+ * the power undesirably.
+ * We know we can read from the IO expander because we did
+ * it during power-on. Assume failure now is bad news. */
+ status = i2c_smbus_read_byte_data(efx->board_info.ioexp_client, P1_IN);
+ if (status >= 0 &&
+ (status & ((1 << P1_AFE_PWD_LBN) | (1 << P1_DSP_PWD25_LBN))) != 0)
+ return 0;
+
+ /* Use board power control, not PHY power control */
+ sfe4001_poweroff(efx);
+ efx->phy_mode = PHY_MODE_OFF;
+
+ return (status < 0) ? -EIO : -ERANGE;
+}
+
+static struct i2c_board_info sfe4001_hwmon_info = {
+ I2C_BOARD_INFO("max6647", 0x4e),
+ .irq = -1,
+};
+
/* This board uses an I2C expander to provider power to the PHY, which needs to
* be turned on before the PHY can be used.
* Context: Process context, rtnl lock held
*/
int sfe4001_init(struct efx_nic *efx)
{
- struct i2c_client *hwmon_client;
int rc;
- hwmon_client = i2c_new_dummy(&efx->i2c_adap, MAX6647);
- if (!hwmon_client)
+#if defined(CONFIG_SENSORS_LM90) || defined(CONFIG_SENSORS_LM90_MODULE)
+ efx->board_info.hwmon_client =
+ i2c_new_device(&efx->i2c_adap, &sfe4001_hwmon_info);
+#else
+ efx->board_info.hwmon_client =
+ i2c_new_dummy(&efx->i2c_adap, sfe4001_hwmon_info.addr);
+#endif
+ if (!efx->board_info.hwmon_client)
return -EIO;
- efx->board_info.hwmon_client = hwmon_client;
- /* Set DSP over-temperature alert threshold */
- EFX_INFO(efx, "DSP cut-out at %dC\n", xgphy_max_temperature);
- rc = i2c_smbus_write_byte_data(hwmon_client, WLHO,
- xgphy_max_temperature);
+ /* Raise board/PHY high limit from 85 to 90 degrees Celsius */
+ rc = i2c_smbus_write_byte_data(efx->board_info.hwmon_client,
+ MAX664X_REG_WLHO, 90);
if (rc)
- goto fail_ioexp;
-
- /* Read it back and verify */
- rc = i2c_smbus_read_byte_data(hwmon_client, RLHN);
- if (rc < 0)
- goto fail_ioexp;
- if (rc != xgphy_max_temperature) {
- rc = -EFAULT;
- goto fail_ioexp;
- }
+ goto fail_hwmon;
efx->board_info.ioexp_client = i2c_new_dummy(&efx->i2c_adap, PCA9539);
if (!efx->board_info.ioexp_client) {
@@ -301,6 +323,7 @@ int sfe4001_init(struct efx_nic *efx)
* blink code. */
efx->board_info.blink = tenxpress_phy_blink;
+ efx->board_info.monitor = sfe4001_check_hw;
efx->board_info.fini = sfe4001_fini;
rc = sfe4001_poweron(efx);
@@ -319,6 +342,64 @@ fail_on:
fail_ioexp:
i2c_unregister_device(efx->board_info.ioexp_client);
fail_hwmon:
- i2c_unregister_device(hwmon_client);
+ i2c_unregister_device(efx->board_info.hwmon_client);
+ return rc;
+}
+
+static int sfn4111t_check_hw(struct efx_nic *efx)
+{
+ s32 status;
+
+ /* If XAUI link is up then do not monitor */
+ if (EFX_WORKAROUND_7884(efx) && efx->mac_up)
+ return 0;
+
+ /* Test LHIGH, RHIGH, FAULT, EOT and IOT alarms */
+ status = i2c_smbus_read_byte_data(efx->board_info.hwmon_client,
+ MAX664X_REG_RSL);
+ if (status < 0)
+ return -EIO;
+ if (status & 0x57)
+ return -ERANGE;
+ return 0;
+}
+
+static void sfn4111t_fini(struct efx_nic *efx)
+{
+ EFX_INFO(efx, "%s\n", __func__);
+
+ device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg);
+ i2c_unregister_device(efx->board_info.hwmon_client);
+}
+
+static struct i2c_board_info sfn4111t_hwmon_info = {
+ I2C_BOARD_INFO("max6647", 0x4e),
+ .irq = -1,
+};
+
+int sfn4111t_init(struct efx_nic *efx)
+{
+ int rc;
+
+ efx->board_info.hwmon_client =
+ i2c_new_device(&efx->i2c_adap, &sfn4111t_hwmon_info);
+ if (!efx->board_info.hwmon_client)
+ return -EIO;
+
+ efx->board_info.blink = tenxpress_phy_blink;
+ efx->board_info.monitor = sfn4111t_check_hw;
+ efx->board_info.fini = sfn4111t_fini;
+
+ rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg);
+ if (rc)
+ goto fail_hwmon;
+
+ if (efx->phy_mode & PHY_MODE_SPECIAL)
+ sfn4111t_reset(efx);
+
+ return 0;
+
+fail_hwmon:
+ i2c_unregister_device(efx->board_info.hwmon_client);
return rc;
}
diff --git a/drivers/net/sfc/spi.h b/drivers/net/sfc/spi.h
index feef61942377..1b1ceb411671 100644
--- a/drivers/net/sfc/spi.h
+++ b/drivers/net/sfc/spi.h
@@ -25,6 +25,7 @@
#define SPI_WRDI 0x04 /* Reset write enable latch */
#define SPI_RDSR 0x05 /* Read status register */
#define SPI_WREN 0x06 /* Set write enable latch */
+#define SPI_SST_EWSR 0x50 /* SST: Enable write to status register */
#define SPI_STATUS_WPEN 0x80 /* Write-protect pin enabled */
#define SPI_STATUS_BP2 0x10 /* Block protection bit 2 */
@@ -36,6 +37,7 @@
/**
* struct efx_spi_device - an Efx SPI (Serial Peripheral Interface) device
* @efx: The Efx controller that owns this device
+ * @mtd: MTD state
* @device_id: Controller's id for the device
* @size: Size (in bytes)
* @addr_len: Number of address bytes in read/write commands
@@ -44,23 +46,51 @@
* use bit 3 of the command byte as address bit A8, rather
* than having a two-byte address. If this flag is set, then
* commands should be munged in this way.
+ * @erase_command: Erase command (or 0 if sector erase not needed).
+ * @erase_size: Erase sector size (in bytes)
+ * Erase commands affect sectors with this size and alignment.
+ * This must be a power of two.
* @block_size: Write block size (in bytes).
* Write commands are limited to blocks with this size and alignment.
- * @read: Read function for the device
- * @write: Write function for the device
*/
struct efx_spi_device {
struct efx_nic *efx;
+#ifdef CONFIG_SFC_MTD
+ void *mtd;
+#endif
int device_id;
unsigned int size;
unsigned int addr_len;
unsigned int munge_address:1;
+ u8 erase_command;
+ unsigned int erase_size;
unsigned int block_size;
};
+int falcon_spi_cmd(const struct efx_spi_device *spi, unsigned int command,
+ int address, const void* in, void *out, size_t len);
+int falcon_spi_wait_write(const struct efx_spi_device *spi);
int falcon_spi_read(const struct efx_spi_device *spi, loff_t start,
size_t len, size_t *retlen, u8 *buffer);
int falcon_spi_write(const struct efx_spi_device *spi, loff_t start,
size_t len, size_t *retlen, const u8 *buffer);
+/*
+ * SFC4000 flash is partitioned into:
+ * 0-0x400 chip and board config (see falcon_hwdefs.h)
+ * 0x400-0x8000 unused (or may contain VPD if EEPROM not present)
+ * 0x8000-end boot code (mapped to PCI expansion ROM)
+ * SFC4000 small EEPROM (size < 0x400) is used for VPD only.
+ * SFC4000 large EEPROM (size >= 0x400) is partitioned into:
+ * 0-0x400 chip and board config
+ * configurable VPD
+ * 0x800-0x1800 boot config
+ * Aside from the chip and board config, all of these are optional and may
+ * be absent or truncated depending on the devices used.
+ */
+#define FALCON_NVCONFIG_END 0x400U
+#define FALCON_FLASH_BOOTCODE_START 0x8000U
+#define EFX_EEPROM_BOOTCONFIG_START 0x800U
+#define EFX_EEPROM_BOOTCONFIG_END 0x1800U
+
#endif /* EFX_SPI_H */
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index d507c93d666e..b9768760fae7 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -1,6 +1,6 @@
/****************************************************************************
- * Driver for Solarflare 802.3an compliant PHY
- * Copyright 2007 Solarflare Communications Inc.
+ * Driver for Solarflare Solarstorm network controllers and boards
+ * Copyright 2007-2008 Solarflare Communications Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
@@ -10,45 +10,76 @@
#include <linux/delay.h>
#include <linux/seq_file.h>
#include "efx.h"
-#include "gmii.h"
#include "mdio_10g.h"
#include "falcon.h"
#include "phy.h"
#include "falcon_hwdefs.h"
#include "boards.h"
-#include "mac.h"
+#include "workarounds.h"
+#include "selftest.h"
-/* We expect these MMDs to be in the package */
-/* AN not here as mdio_check_mmds() requires STAT2 support */
-#define TENXPRESS_REQUIRED_DEVS (MDIO_MMDREG_DEVS0_PMAPMD | \
- MDIO_MMDREG_DEVS0_PCS | \
- MDIO_MMDREG_DEVS0_PHYXS)
-
-#define TENXPRESS_LOOPBACKS ((1 << LOOPBACK_PHYXS) | \
- (1 << LOOPBACK_PCS) | \
- (1 << LOOPBACK_PMAPMD) | \
- (1 << LOOPBACK_NETWORK))
+/* We expect these MMDs to be in the package. SFT9001 also has a
+ * clause 22 extension MMD, but since it doesn't have all the generic
+ * MMD registers it is pointless to include it here.
+ */
+#define TENXPRESS_REQUIRED_DEVS (MDIO_MMDREG_DEVS_PMAPMD | \
+ MDIO_MMDREG_DEVS_PCS | \
+ MDIO_MMDREG_DEVS_PHYXS | \
+ MDIO_MMDREG_DEVS_AN)
+
+#define SFX7101_LOOPBACKS ((1 << LOOPBACK_PHYXS) | \
+ (1 << LOOPBACK_PCS) | \
+ (1 << LOOPBACK_PMAPMD) | \
+ (1 << LOOPBACK_NETWORK))
+
+#define SFT9001_LOOPBACKS ((1 << LOOPBACK_GPHY) | \
+ (1 << LOOPBACK_PHYXS) | \
+ (1 << LOOPBACK_PCS) | \
+ (1 << LOOPBACK_PMAPMD) | \
+ (1 << LOOPBACK_NETWORK))
/* We complain if we fail to see the link partner as 10G capable this many
* times in a row (must be > 1 as sampling the autoneg. registers is racy)
*/
#define MAX_BAD_LP_TRIES (5)
+/* LASI Control */
+#define PMA_PMD_LASI_CTRL 36866
+#define PMA_PMD_LASI_STATUS 36869
+#define PMA_PMD_LS_ALARM_LBN 0
+#define PMA_PMD_LS_ALARM_WIDTH 1
+#define PMA_PMD_TX_ALARM_LBN 1
+#define PMA_PMD_TX_ALARM_WIDTH 1
+#define PMA_PMD_RX_ALARM_LBN 2
+#define PMA_PMD_RX_ALARM_WIDTH 1
+#define PMA_PMD_AN_ALARM_LBN 3
+#define PMA_PMD_AN_ALARM_WIDTH 1
+
/* Extended control register */
-#define PMA_PMD_XCONTROL_REG 0xc000
-#define PMA_PMD_LNPGA_POWERDOWN_LBN 8
-#define PMA_PMD_LNPGA_POWERDOWN_WIDTH 1
+#define PMA_PMD_XCONTROL_REG 49152
+#define PMA_PMD_EXT_GMII_EN_LBN 1
+#define PMA_PMD_EXT_GMII_EN_WIDTH 1
+#define PMA_PMD_EXT_CLK_OUT_LBN 2
+#define PMA_PMD_EXT_CLK_OUT_WIDTH 1
+#define PMA_PMD_LNPGA_POWERDOWN_LBN 8 /* SFX7101 only */
+#define PMA_PMD_LNPGA_POWERDOWN_WIDTH 1
+#define PMA_PMD_EXT_CLK312_LBN 8 /* SFT9001 only */
+#define PMA_PMD_EXT_CLK312_WIDTH 1
+#define PMA_PMD_EXT_LPOWER_LBN 12
+#define PMA_PMD_EXT_LPOWER_WIDTH 1
+#define PMA_PMD_EXT_SSR_LBN 15
+#define PMA_PMD_EXT_SSR_WIDTH 1
/* extended status register */
-#define PMA_PMD_XSTATUS_REG 0xc001
+#define PMA_PMD_XSTATUS_REG 49153
#define PMA_PMD_XSTAT_FLP_LBN (12)
/* LED control register */
-#define PMA_PMD_LED_CTRL_REG (0xc007)
+#define PMA_PMD_LED_CTRL_REG 49159
#define PMA_PMA_LED_ACTIVITY_LBN (3)
/* LED function override register */
-#define PMA_PMD_LED_OVERR_REG (0xc009)
+#define PMA_PMD_LED_OVERR_REG 49161
/* Bit positions for different LEDs (there are more but not wired on SFE4001)*/
#define PMA_PMD_LED_LINK_LBN (0)
#define PMA_PMD_LED_SPEED_LBN (2)
@@ -59,41 +90,99 @@
#define PMA_PMD_LED_ON (1)
#define PMA_PMD_LED_OFF (2)
#define PMA_PMD_LED_FLASH (3)
+#define PMA_PMD_LED_MASK 3
/* All LEDs under hardware control */
#define PMA_PMD_LED_FULL_AUTO (0)
/* Green and Amber under hardware control, Red off */
#define PMA_PMD_LED_DEFAULT (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN)
-
-/* Special Software reset register */
-#define PMA_PMD_EXT_CTRL_REG 49152
-#define PMA_PMD_EXT_SSR_LBN 15
-
-/* Misc register defines */
-#define PCS_CLOCK_CTRL_REG 0xd801
+#define PMA_PMD_SPEED_ENABLE_REG 49192
+#define PMA_PMD_100TX_ADV_LBN 1
+#define PMA_PMD_100TX_ADV_WIDTH 1
+#define PMA_PMD_1000T_ADV_LBN 2
+#define PMA_PMD_1000T_ADV_WIDTH 1
+#define PMA_PMD_10000T_ADV_LBN 3
+#define PMA_PMD_10000T_ADV_WIDTH 1
+#define PMA_PMD_SPEED_LBN 4
+#define PMA_PMD_SPEED_WIDTH 4
+
+/* Cable diagnostics - SFT9001 only */
+#define PMA_PMD_CDIAG_CTRL_REG 49213
+#define CDIAG_CTRL_IMMED_LBN 15
+#define CDIAG_CTRL_BRK_LINK_LBN 12
+#define CDIAG_CTRL_IN_PROG_LBN 11
+#define CDIAG_CTRL_LEN_UNIT_LBN 10
+#define CDIAG_CTRL_LEN_METRES 1
+#define PMA_PMD_CDIAG_RES_REG 49174
+#define CDIAG_RES_A_LBN 12
+#define CDIAG_RES_B_LBN 8
+#define CDIAG_RES_C_LBN 4
+#define CDIAG_RES_D_LBN 0
+#define CDIAG_RES_WIDTH 4
+#define CDIAG_RES_OPEN 2
+#define CDIAG_RES_OK 1
+#define CDIAG_RES_INVALID 0
+/* Set of 4 registers for pairs A-D */
+#define PMA_PMD_CDIAG_LEN_REG 49175
+
+/* Serdes control registers - SFT9001 only */
+#define PMA_PMD_CSERDES_CTRL_REG 64258
+/* Set the 156.25 MHz output to 312.5 MHz to drive Falcon's XMAC */
+#define PMA_PMD_CSERDES_DEFAULT 0x000f
+
+/* Misc register defines - SFX7101 only */
+#define PCS_CLOCK_CTRL_REG 55297
#define PLL312_RST_N_LBN 2
-#define PCS_SOFT_RST2_REG 0xd806
+#define PCS_SOFT_RST2_REG 55302
#define SERDES_RST_N_LBN 13
#define XGXS_RST_N_LBN 12
-#define PCS_TEST_SELECT_REG 0xd807 /* PRM 10.5.8 */
+#define PCS_TEST_SELECT_REG 55303 /* PRM 10.5.8 */
#define CLK312_EN_LBN 3
/* PHYXS registers */
+#define PHYXS_XCONTROL_REG 49152
+#define PHYXS_RESET_LBN 15
+#define PHYXS_RESET_WIDTH 1
+
#define PHYXS_TEST1 (49162)
#define LOOPBACK_NEAR_LBN (8)
#define LOOPBACK_NEAR_WIDTH (1)
+#define PCS_10GBASET_STAT1 32
+#define PCS_10GBASET_BLKLK_LBN 0
+#define PCS_10GBASET_BLKLK_WIDTH 1
+
/* Boot status register */
-#define PCS_BOOT_STATUS_REG (0xd000)
+#define PCS_BOOT_STATUS_REG 53248
#define PCS_BOOT_FATAL_ERR_LBN (0)
#define PCS_BOOT_PROGRESS_LBN (1)
#define PCS_BOOT_PROGRESS_WIDTH (2)
#define PCS_BOOT_COMPLETE_LBN (3)
+
#define PCS_BOOT_MAX_DELAY (100)
#define PCS_BOOT_POLL_DELAY (10)
+/* 100M/1G PHY registers */
+#define GPHY_XCONTROL_REG 49152
+#define GPHY_ISOLATE_LBN 10
+#define GPHY_ISOLATE_WIDTH 1
+#define GPHY_DUPLEX_LBN 8
+#define GPHY_DUPLEX_WIDTH 1
+#define GPHY_LOOPBACK_NEAR_LBN 14
+#define GPHY_LOOPBACK_NEAR_WIDTH 1
+
+#define C22EXT_STATUS_REG 49153
+#define C22EXT_STATUS_LINK_LBN 2
+#define C22EXT_STATUS_LINK_WIDTH 1
+
+#define C22EXT_MSTSLV_REG 49162
+#define C22EXT_MSTSLV_1000_HD_LBN 10
+#define C22EXT_MSTSLV_1000_HD_WIDTH 1
+#define C22EXT_MSTSLV_1000_FD_LBN 11
+#define C22EXT_MSTSLV_1000_FD_WIDTH 1
+
/* Time to wait between powering down the LNPGA and turning off the power
* rails */
#define LNPGA_PDOWN_WAIT (HZ / 5)
@@ -117,6 +206,38 @@ void tenxpress_crc_err(struct efx_nic *efx)
atomic_inc(&phy_data->bad_crc_count);
}
+static ssize_t show_phy_short_reach(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
+ int reg;
+
+ reg = mdio_clause45_read(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
+ MDIO_PMAPMD_10GBT_TXPWR);
+ return sprintf(buf, "%d\n",
+ !!(reg & (1 << MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN)));
+}
+
+static ssize_t set_phy_short_reach(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
+
+ rtnl_lock();
+ mdio_clause45_set_flag(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
+ MDIO_PMAPMD_10GBT_TXPWR,
+ MDIO_PMAPMD_10GBT_TXPWR_SHORT_LBN,
+ count != 0 && *buf != '0');
+ efx_reconfigure_port(efx);
+ rtnl_unlock();
+
+ return count;
+}
+
+static DEVICE_ATTR(phy_short_reach, 0644, show_phy_short_reach,
+ set_phy_short_reach);
+
/* Check that the C166 has booted successfully */
static int tenxpress_phy_check(struct efx_nic *efx)
{
@@ -148,27 +269,42 @@ static int tenxpress_phy_check(struct efx_nic *efx)
static int tenxpress_init(struct efx_nic *efx)
{
- int rc, reg;
+ int phy_id = efx->mii.phy_id;
+ int reg;
+ int rc;
- /* Turn on the clock */
- reg = (1 << CLK312_EN_LBN);
- mdio_clause45_write(efx, efx->mii.phy_id,
- MDIO_MMD_PCS, PCS_TEST_SELECT_REG, reg);
+ if (efx->phy_type == PHY_TYPE_SFX7101) {
+ /* Enable 312.5 MHz clock */
+ mdio_clause45_write(efx, phy_id,
+ MDIO_MMD_PCS, PCS_TEST_SELECT_REG,
+ 1 << CLK312_EN_LBN);
+ } else {
+ /* Enable 312.5 MHz clock and GMII */
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
+ PMA_PMD_XCONTROL_REG);
+ reg |= ((1 << PMA_PMD_EXT_GMII_EN_LBN) |
+ (1 << PMA_PMD_EXT_CLK_OUT_LBN) |
+ (1 << PMA_PMD_EXT_CLK312_LBN));
+ mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
+ PMA_PMD_XCONTROL_REG, reg);
+ mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT,
+ GPHY_XCONTROL_REG, GPHY_ISOLATE_LBN,
+ false);
+ }
rc = tenxpress_phy_check(efx);
if (rc < 0)
return rc;
/* Set the LEDs up as: Green = Link, Amber = Link/Act, Red = Off */
- reg = mdio_clause45_read(efx, efx->mii.phy_id,
- MDIO_MMD_PMAPMD, PMA_PMD_LED_CTRL_REG);
- reg |= (1 << PMA_PMA_LED_ACTIVITY_LBN);
- mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
- PMA_PMD_LED_CTRL_REG, reg);
-
- reg = PMA_PMD_LED_DEFAULT;
- mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
- PMA_PMD_LED_OVERR_REG, reg);
+ if (efx->phy_type == PHY_TYPE_SFX7101) {
+ mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PMAPMD,
+ PMA_PMD_LED_CTRL_REG,
+ PMA_PMA_LED_ACTIVITY_LBN,
+ true);
+ mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
+ PMA_PMD_LED_OVERR_REG, PMA_PMD_LED_DEFAULT);
+ }
return rc;
}
@@ -184,22 +320,43 @@ static int tenxpress_phy_init(struct efx_nic *efx)
efx->phy_data = phy_data;
phy_data->phy_mode = efx->phy_mode;
- rc = mdio_clause45_wait_reset_mmds(efx,
- TENXPRESS_REQUIRED_DEVS);
- if (rc < 0)
- goto fail;
+ if (!(efx->phy_mode & PHY_MODE_SPECIAL)) {
+ if (efx->phy_type == PHY_TYPE_SFT9001A) {
+ int reg;
+ reg = mdio_clause45_read(efx, efx->mii.phy_id,
+ MDIO_MMD_PMAPMD,
+ PMA_PMD_XCONTROL_REG);
+ reg |= (1 << PMA_PMD_EXT_SSR_LBN);
+ mdio_clause45_write(efx, efx->mii.phy_id,
+ MDIO_MMD_PMAPMD,
+ PMA_PMD_XCONTROL_REG, reg);
+ mdelay(200);
+ }
- rc = mdio_clause45_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0);
- if (rc < 0)
- goto fail;
+ rc = mdio_clause45_wait_reset_mmds(efx,
+ TENXPRESS_REQUIRED_DEVS);
+ if (rc < 0)
+ goto fail;
+
+ rc = mdio_clause45_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0);
+ if (rc < 0)
+ goto fail;
+ }
rc = tenxpress_init(efx);
if (rc < 0)
goto fail;
+ if (efx->phy_type == PHY_TYPE_SFT9001B) {
+ rc = device_create_file(&efx->pci_dev->dev,
+ &dev_attr_phy_short_reach);
+ if (rc)
+ goto fail;
+ }
+
schedule_timeout_uninterruptible(HZ / 5); /* 200ms */
- /* Let XGXS and SerDes out of reset and resets 10XPress */
+ /* Let XGXS and SerDes out of reset */
falcon_reset_xaui(efx);
return 0;
@@ -210,21 +367,24 @@ static int tenxpress_phy_init(struct efx_nic *efx)
return rc;
}
+/* Perform a "special software reset" on the PHY. The caller is
+ * responsible for saving and restoring the PHY hardware registers
+ * properly, and masking/unmasking LASI */
static int tenxpress_special_reset(struct efx_nic *efx)
{
int rc, reg;
/* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so
* a special software reset can glitch the XGMAC sufficiently for stats
- * requests to fail. Since we don't ofen special_reset, just lock. */
+ * requests to fail. Since we don't often special_reset, just lock. */
spin_lock(&efx->stats_lock);
/* Initiate reset */
reg = mdio_clause45_read(efx, efx->mii.phy_id,
- MDIO_MMD_PMAPMD, PMA_PMD_EXT_CTRL_REG);
+ MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG);
reg |= (1 << PMA_PMD_EXT_SSR_LBN);
mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
- PMA_PMD_EXT_CTRL_REG, reg);
+ PMA_PMD_XCONTROL_REG, reg);
mdelay(200);
@@ -239,174 +399,257 @@ static int tenxpress_special_reset(struct efx_nic *efx)
if (rc < 0)
goto unlock;
+ /* Wait for the XGXS state machine to churn */
+ mdelay(10);
unlock:
spin_unlock(&efx->stats_lock);
return rc;
}
-static void tenxpress_set_bad_lp(struct efx_nic *efx, bool bad_lp)
+static void sfx7101_check_bad_lp(struct efx_nic *efx, bool link_ok)
{
struct tenxpress_phy_data *pd = efx->phy_data;
+ int phy_id = efx->mii.phy_id;
+ bool bad_lp;
int reg;
+ if (link_ok) {
+ bad_lp = false;
+ } else {
+ /* Check that AN has started but not completed. */
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
+ MDIO_AN_STATUS);
+ if (!(reg & (1 << MDIO_AN_STATUS_LP_AN_CAP_LBN)))
+ return; /* LP status is unknown */
+ bad_lp = !(reg & (1 << MDIO_AN_STATUS_AN_DONE_LBN));
+ if (bad_lp)
+ pd->bad_lp_tries++;
+ }
+
/* Nothing to do if all is well and was previously so. */
- if (!(bad_lp || pd->bad_lp_tries))
+ if (!pd->bad_lp_tries)
return;
- reg = mdio_clause45_read(efx, efx->mii.phy_id,
- MDIO_MMD_PMAPMD, PMA_PMD_LED_OVERR_REG);
+ /* Use the RX (red) LED as an error indicator once we've seen AN
+ * failure several times in a row, and also log a message. */
+ if (!bad_lp || pd->bad_lp_tries == MAX_BAD_LP_TRIES) {
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
+ PMA_PMD_LED_OVERR_REG);
+ reg &= ~(PMA_PMD_LED_MASK << PMA_PMD_LED_RX_LBN);
+ if (!bad_lp) {
+ reg |= PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN;
+ } else {
+ reg |= PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN;
+ EFX_ERR(efx, "appears to be plugged into a port"
+ " that is not 10GBASE-T capable. The PHY"
+ " supports 10GBASE-T ONLY, so no link can"
+ " be established\n");
+ }
+ mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
+ PMA_PMD_LED_OVERR_REG, reg);
+ pd->bad_lp_tries = bad_lp;
+ }
+}
- if (bad_lp)
- pd->bad_lp_tries++;
- else
- pd->bad_lp_tries = 0;
-
- if (pd->bad_lp_tries == MAX_BAD_LP_TRIES) {
- pd->bad_lp_tries = 0; /* Restart count */
- reg &= ~(PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN);
- reg |= (PMA_PMD_LED_FLASH << PMA_PMD_LED_RX_LBN);
- EFX_ERR(efx, "This NIC appears to be plugged into"
- " a port that is not 10GBASE-T capable.\n"
- " This PHY is 10GBASE-T ONLY, so no link can"
- " be established.\n");
+static bool sfx7101_link_ok(struct efx_nic *efx)
+{
+ return mdio_clause45_links_ok(efx,
+ MDIO_MMDREG_DEVS_PMAPMD |
+ MDIO_MMDREG_DEVS_PCS |
+ MDIO_MMDREG_DEVS_PHYXS);
+}
+
+static bool sft9001_link_ok(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+{
+ int phy_id = efx->mii.phy_id;
+ u32 reg;
+
+ if (efx_phy_mode_disabled(efx->phy_mode))
+ return false;
+ else if (efx->loopback_mode == LOOPBACK_GPHY)
+ return true;
+ else if (efx->loopback_mode)
+ return mdio_clause45_links_ok(efx,
+ MDIO_MMDREG_DEVS_PMAPMD |
+ MDIO_MMDREG_DEVS_PHYXS);
+
+ /* We must use the same definition of link state as LASI,
+ * otherwise we can miss a link state transition
+ */
+ if (ecmd->speed == 10000) {
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS,
+ PCS_10GBASET_STAT1);
+ return reg & (1 << PCS_10GBASET_BLKLK_LBN);
} else {
- reg |= (PMA_PMD_LED_OFF << PMA_PMD_LED_RX_LBN);
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT,
+ C22EXT_STATUS_REG);
+ return reg & (1 << C22EXT_STATUS_LINK_LBN);
}
- mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
- PMA_PMD_LED_OVERR_REG, reg);
}
-/* Check link status and return a boolean OK value. If the link is NOT
- * OK we have a quick rummage round to see if we appear to be plugged
- * into a non-10GBT port and if so warn the user that they won't get
- * link any time soon as we are 10GBT only, unless caller specified
- * not to do this check (it isn't useful in loopback) */
-static bool tenxpress_link_ok(struct efx_nic *efx, bool check_lp)
+static void tenxpress_ext_loopback(struct efx_nic *efx)
{
- bool ok = mdio_clause45_links_ok(efx, TENXPRESS_REQUIRED_DEVS);
-
- if (ok) {
- tenxpress_set_bad_lp(efx, false);
- } else if (check_lp) {
- /* Are we plugged into the wrong sort of link? */
- bool bad_lp = false;
- int phy_id = efx->mii.phy_id;
- int an_stat = mdio_clause45_read(efx, phy_id, MDIO_MMD_AN,
- MDIO_AN_STATUS);
- int xphy_stat = mdio_clause45_read(efx, phy_id,
- MDIO_MMD_PMAPMD,
- PMA_PMD_XSTATUS_REG);
- /* Are we plugged into anything that sends FLPs? If
- * not we can't distinguish between not being plugged
- * in and being plugged into a non-AN antique. The FLP
- * bit has the advantage of not clearing when autoneg
- * restarts. */
- if (!(xphy_stat & (1 << PMA_PMD_XSTAT_FLP_LBN))) {
- tenxpress_set_bad_lp(efx, false);
- return ok;
- }
+ int phy_id = efx->mii.phy_id;
- /* If it can do 10GBT it must be XNP capable */
- bad_lp = !(an_stat & (1 << MDIO_AN_STATUS_XNP_LBN));
- if (!bad_lp && (an_stat & (1 << MDIO_AN_STATUS_PAGE_LBN))) {
- bad_lp = !(mdio_clause45_read(efx, phy_id,
- MDIO_MMD_AN, MDIO_AN_10GBT_STATUS) &
- (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN));
- }
- tenxpress_set_bad_lp(efx, bad_lp);
- }
- return ok;
+ mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_PHYXS,
+ PHYXS_TEST1, LOOPBACK_NEAR_LBN,
+ efx->loopback_mode == LOOPBACK_PHYXS);
+ if (efx->phy_type != PHY_TYPE_SFX7101)
+ mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT,
+ GPHY_XCONTROL_REG,
+ GPHY_LOOPBACK_NEAR_LBN,
+ efx->loopback_mode == LOOPBACK_GPHY);
}
-static void tenxpress_phyxs_loopback(struct efx_nic *efx)
+static void tenxpress_low_power(struct efx_nic *efx)
{
int phy_id = efx->mii.phy_id;
- int ctrl1, ctrl2;
- ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS,
- PHYXS_TEST1);
- if (efx->loopback_mode == LOOPBACK_PHYXS)
- ctrl2 |= (1 << LOOPBACK_NEAR_LBN);
+ if (efx->phy_type == PHY_TYPE_SFX7101)
+ mdio_clause45_set_mmds_lpower(
+ efx, !!(efx->phy_mode & PHY_MODE_LOW_POWER),
+ TENXPRESS_REQUIRED_DEVS);
else
- ctrl2 &= ~(1 << LOOPBACK_NEAR_LBN);
- if (ctrl1 != ctrl2)
- mdio_clause45_write(efx, phy_id, MDIO_MMD_PHYXS,
- PHYXS_TEST1, ctrl2);
+ mdio_clause45_set_flag(
+ efx, phy_id, MDIO_MMD_PMAPMD,
+ PMA_PMD_XCONTROL_REG, PMA_PMD_EXT_LPOWER_LBN,
+ !!(efx->phy_mode & PHY_MODE_LOW_POWER));
}
static void tenxpress_phy_reconfigure(struct efx_nic *efx)
{
struct tenxpress_phy_data *phy_data = efx->phy_data;
- bool loop_change = LOOPBACK_OUT_OF(phy_data, efx,
- TENXPRESS_LOOPBACKS);
+ struct ethtool_cmd ecmd;
+ bool phy_mode_change, loop_reset, loop_toggle, loopback;
- if (efx->phy_mode & PHY_MODE_SPECIAL) {
+ if (efx->phy_mode & (PHY_MODE_OFF | PHY_MODE_SPECIAL)) {
phy_data->phy_mode = efx->phy_mode;
return;
}
- /* When coming out of transmit disable, coming out of low power
- * mode, or moving out of any PHY internal loopback mode,
- * perform a special software reset */
- if ((efx->phy_mode == PHY_MODE_NORMAL &&
- phy_data->phy_mode != PHY_MODE_NORMAL) ||
- loop_change) {
- tenxpress_special_reset(efx);
- falcon_reset_xaui(efx);
+ tenxpress_low_power(efx);
+
+ phy_mode_change = (efx->phy_mode == PHY_MODE_NORMAL &&
+ phy_data->phy_mode != PHY_MODE_NORMAL);
+ loopback = LOOPBACK_MASK(efx) & efx->phy_op->loopbacks;
+ loop_toggle = LOOPBACK_CHANGED(phy_data, efx, efx->phy_op->loopbacks);
+ loop_reset = (LOOPBACK_OUT_OF(phy_data, efx, efx->phy_op->loopbacks) ||
+ LOOPBACK_CHANGED(phy_data, efx, 1 << LOOPBACK_GPHY));
+
+ if (loop_reset || loop_toggle || loopback || phy_mode_change) {
+ int rc;
+
+ efx->phy_op->get_settings(efx, &ecmd);
+
+ if (loop_reset || phy_mode_change) {
+ tenxpress_special_reset(efx);
+
+ /* Reset XAUI if we were in 10G, and are staying
+ * in 10G. If we're moving into and out of 10G
+ * then xaui will be reset anyway */
+ if (EFX_IS10G(efx))
+ falcon_reset_xaui(efx);
+ }
+
+ if (efx->phy_type != PHY_TYPE_SFX7101) {
+ /* Only change autoneg once, on coming out or
+ * going into loopback */
+ if (loop_toggle)
+ ecmd.autoneg = !loopback;
+ if (loopback) {
+ ecmd.duplex = DUPLEX_FULL;
+ if (efx->loopback_mode == LOOPBACK_GPHY)
+ ecmd.speed = SPEED_1000;
+ else
+ ecmd.speed = SPEED_10000;
+ }
+ }
+
+ rc = efx->phy_op->set_settings(efx, &ecmd);
+ WARN_ON(rc);
}
mdio_clause45_transmit_disable(efx);
mdio_clause45_phy_reconfigure(efx);
- tenxpress_phyxs_loopback(efx);
+ tenxpress_ext_loopback(efx);
phy_data->loopback_mode = efx->loopback_mode;
phy_data->phy_mode = efx->phy_mode;
- efx->link_up = tenxpress_link_ok(efx, false);
- efx->link_options = GM_LPA_10000FULL;
-}
-static void tenxpress_phy_clear_interrupt(struct efx_nic *efx)
-{
- /* Nothing done here - LASI interrupts aren't reliable so poll */
+ if (efx->phy_type == PHY_TYPE_SFX7101) {
+ efx->link_speed = 10000;
+ efx->link_fd = true;
+ efx->link_up = sfx7101_link_ok(efx);
+ } else {
+ efx->phy_op->get_settings(efx, &ecmd);
+ efx->link_speed = ecmd.speed;
+ efx->link_fd = ecmd.duplex == DUPLEX_FULL;
+ efx->link_up = sft9001_link_ok(efx, &ecmd);
+ }
+ efx->link_fc = mdio_clause45_get_pause(efx);
}
-
/* Poll PHY for interrupt */
-static int tenxpress_phy_check_hw(struct efx_nic *efx)
+static void tenxpress_phy_poll(struct efx_nic *efx)
{
struct tenxpress_phy_data *phy_data = efx->phy_data;
- bool link_ok;
-
- link_ok = tenxpress_link_ok(efx, true);
+ bool change = false, link_ok;
+ unsigned link_fc;
+
+ if (efx->phy_type == PHY_TYPE_SFX7101) {
+ link_ok = sfx7101_link_ok(efx);
+ if (link_ok != efx->link_up) {
+ change = true;
+ } else {
+ link_fc = mdio_clause45_get_pause(efx);
+ if (link_fc != efx->link_fc)
+ change = true;
+ }
+ sfx7101_check_bad_lp(efx, link_ok);
+ } else if (efx->loopback_mode) {
+ bool link_ok = sft9001_link_ok(efx, NULL);
+ if (link_ok != efx->link_up)
+ change = true;
+ } else {
+ u32 status = mdio_clause45_read(efx, efx->mii.phy_id,
+ MDIO_MMD_PMAPMD,
+ PMA_PMD_LASI_STATUS);
+ if (status & (1 << PMA_PMD_LS_ALARM_LBN))
+ change = true;
+ }
- if (link_ok != efx->link_up)
- falcon_xmac_sim_phy_event(efx);
+ if (change)
+ falcon_sim_phy_event(efx);
if (phy_data->phy_mode != PHY_MODE_NORMAL)
- return 0;
+ return;
- if (atomic_read(&phy_data->bad_crc_count) > crc_error_reset_threshold) {
+ if (EFX_WORKAROUND_10750(efx) &&
+ atomic_read(&phy_data->bad_crc_count) > crc_error_reset_threshold) {
EFX_ERR(efx, "Resetting XAUI due to too many CRC errors\n");
falcon_reset_xaui(efx);
atomic_set(&phy_data->bad_crc_count, 0);
}
-
- return 0;
}
static void tenxpress_phy_fini(struct efx_nic *efx)
{
int reg;
- /* Power down the LNPGA */
- reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN);
- mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
- PMA_PMD_XCONTROL_REG, reg);
-
- /* Waiting here ensures that the board fini, which can turn off the
- * power to the PHY, won't get run until the LNPGA powerdown has been
- * given long enough to complete. */
- schedule_timeout_uninterruptible(LNPGA_PDOWN_WAIT); /* 200 ms */
+ if (efx->phy_type == PHY_TYPE_SFT9001B) {
+ device_remove_file(&efx->pci_dev->dev,
+ &dev_attr_phy_short_reach);
+ } else {
+ /* Power down the LNPGA */
+ reg = (1 << PMA_PMD_LNPGA_POWERDOWN_LBN);
+ mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
+ PMA_PMD_XCONTROL_REG, reg);
+
+ /* Waiting here ensures that the board fini, which can turn
+ * off the power to the PHY, won't get run until the LNPGA
+ * powerdown has been given long enough to complete. */
+ schedule_timeout_uninterruptible(LNPGA_PDOWN_WAIT); /* 200 ms */
+ }
kfree(efx->phy_data);
efx->phy_data = NULL;
@@ -430,19 +673,236 @@ void tenxpress_phy_blink(struct efx_nic *efx, bool blink)
PMA_PMD_LED_OVERR_REG, reg);
}
-static int tenxpress_phy_test(struct efx_nic *efx)
+static const char *const sfx7101_test_names[] = {
+ "bist"
+};
+
+static int
+sfx7101_run_tests(struct efx_nic *efx, int *results, unsigned flags)
{
+ int rc;
+
+ if (!(flags & ETH_TEST_FL_OFFLINE))
+ return 0;
+
/* BIST is automatically run after a special software reset */
- return tenxpress_special_reset(efx);
+ rc = tenxpress_special_reset(efx);
+ results[0] = rc ? -1 : 1;
+ return rc;
}
-struct efx_phy_operations falcon_tenxpress_phy_ops = {
+static const char *const sft9001_test_names[] = {
+ "bist",
+ "cable.pairA.status",
+ "cable.pairB.status",
+ "cable.pairC.status",
+ "cable.pairD.status",
+ "cable.pairA.length",
+ "cable.pairB.length",
+ "cable.pairC.length",
+ "cable.pairD.length",
+};
+
+static int sft9001_run_tests(struct efx_nic *efx, int *results, unsigned flags)
+{
+ struct ethtool_cmd ecmd;
+ int phy_id = efx->mii.phy_id;
+ int rc = 0, rc2, i, res_reg;
+
+ if (!(flags & ETH_TEST_FL_OFFLINE))
+ return 0;
+
+ efx->phy_op->get_settings(efx, &ecmd);
+
+ /* Initialise cable diagnostic results to unknown failure */
+ for (i = 1; i < 9; ++i)
+ results[i] = -1;
+
+ /* Run cable diagnostics; wait up to 5 seconds for them to complete.
+ * A cable fault is not a self-test failure, but a timeout is. */
+ mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD,
+ PMA_PMD_CDIAG_CTRL_REG,
+ (1 << CDIAG_CTRL_IMMED_LBN) |
+ (1 << CDIAG_CTRL_BRK_LINK_LBN) |
+ (CDIAG_CTRL_LEN_METRES << CDIAG_CTRL_LEN_UNIT_LBN));
+ i = 0;
+ while (mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
+ PMA_PMD_CDIAG_CTRL_REG) &
+ (1 << CDIAG_CTRL_IN_PROG_LBN)) {
+ if (++i == 50) {
+ rc = -ETIMEDOUT;
+ goto reset;
+ }
+ msleep(100);
+ }
+ res_reg = mdio_clause45_read(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD,
+ PMA_PMD_CDIAG_RES_REG);
+ for (i = 0; i < 4; i++) {
+ int pair_res =
+ (res_reg >> (CDIAG_RES_A_LBN - i * CDIAG_RES_WIDTH))
+ & ((1 << CDIAG_RES_WIDTH) - 1);
+ int len_reg = mdio_clause45_read(efx, efx->mii.phy_id,
+ MDIO_MMD_PMAPMD,
+ PMA_PMD_CDIAG_LEN_REG + i);
+ if (pair_res == CDIAG_RES_OK)
+ results[1 + i] = 1;
+ else if (pair_res == CDIAG_RES_INVALID)
+ results[1 + i] = -1;
+ else
+ results[1 + i] = -pair_res;
+ if (pair_res != CDIAG_RES_INVALID &&
+ pair_res != CDIAG_RES_OPEN &&
+ len_reg != 0xffff)
+ results[5 + i] = len_reg;
+ }
+
+ /* We must reset to exit cable diagnostic mode. The BIST will
+ * also run when we do this. */
+reset:
+ rc2 = tenxpress_special_reset(efx);
+ results[0] = rc2 ? -1 : 1;
+ if (!rc)
+ rc = rc2;
+
+ rc2 = efx->phy_op->set_settings(efx, &ecmd);
+ if (!rc)
+ rc = rc2;
+
+ return rc;
+}
+
+static u32 tenxpress_get_xnp_lpa(struct efx_nic *efx)
+{
+ int phy = efx->mii.phy_id;
+ u32 lpa = 0;
+ int reg;
+
+ if (efx->phy_type != PHY_TYPE_SFX7101) {
+ reg = mdio_clause45_read(efx, phy, MDIO_MMD_C22EXT,
+ C22EXT_MSTSLV_REG);
+ if (reg & (1 << C22EXT_MSTSLV_1000_HD_LBN))
+ lpa |= ADVERTISED_1000baseT_Half;
+ if (reg & (1 << C22EXT_MSTSLV_1000_FD_LBN))
+ lpa |= ADVERTISED_1000baseT_Full;
+ }
+ reg = mdio_clause45_read(efx, phy, MDIO_MMD_AN, MDIO_AN_10GBT_STATUS);
+ if (reg & (1 << MDIO_AN_10GBT_STATUS_LP_10G_LBN))
+ lpa |= ADVERTISED_10000baseT_Full;
+ return lpa;
+}
+
+static void sfx7101_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+{
+ mdio_clause45_get_settings_ext(efx, ecmd, ADVERTISED_10000baseT_Full,
+ tenxpress_get_xnp_lpa(efx));
+ ecmd->supported |= SUPPORTED_10000baseT_Full;
+ ecmd->advertising |= ADVERTISED_10000baseT_Full;
+}
+
+static void sft9001_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+{
+ int phy_id = efx->mii.phy_id;
+ u32 xnp_adv = 0;
+ int reg;
+
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD,
+ PMA_PMD_SPEED_ENABLE_REG);
+ if (EFX_WORKAROUND_13204(efx) && (reg & (1 << PMA_PMD_100TX_ADV_LBN)))
+ xnp_adv |= ADVERTISED_100baseT_Full;
+ if (reg & (1 << PMA_PMD_1000T_ADV_LBN))
+ xnp_adv |= ADVERTISED_1000baseT_Full;
+ if (reg & (1 << PMA_PMD_10000T_ADV_LBN))
+ xnp_adv |= ADVERTISED_10000baseT_Full;
+
+ mdio_clause45_get_settings_ext(efx, ecmd, xnp_adv,
+ tenxpress_get_xnp_lpa(efx));
+
+ ecmd->supported |= (SUPPORTED_100baseT_Half |
+ SUPPORTED_100baseT_Full |
+ SUPPORTED_1000baseT_Full);
+
+ /* Use the vendor defined C22ext register for duplex settings */
+ if (ecmd->speed != SPEED_10000 && !ecmd->autoneg) {
+ reg = mdio_clause45_read(efx, phy_id, MDIO_MMD_C22EXT,
+ GPHY_XCONTROL_REG);
+ ecmd->duplex = (reg & (1 << GPHY_DUPLEX_LBN) ?
+ DUPLEX_FULL : DUPLEX_HALF);
+ }
+}
+
+static int sft9001_set_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd)
+{
+ int phy_id = efx->mii.phy_id;
+ int rc;
+
+ rc = mdio_clause45_set_settings(efx, ecmd);
+ if (rc)
+ return rc;
+
+ if (ecmd->speed != SPEED_10000 && !ecmd->autoneg)
+ mdio_clause45_set_flag(efx, phy_id, MDIO_MMD_C22EXT,
+ GPHY_XCONTROL_REG, GPHY_DUPLEX_LBN,
+ ecmd->duplex == DUPLEX_FULL);
+
+ return rc;
+}
+
+static bool sft9001_set_xnp_advertise(struct efx_nic *efx, u32 advertising)
+{
+ int phy = efx->mii.phy_id;
+ int reg = mdio_clause45_read(efx, phy, MDIO_MMD_PMAPMD,
+ PMA_PMD_SPEED_ENABLE_REG);
+ bool enabled;
+
+ reg &= ~((1 << 2) | (1 << 3));
+ if (EFX_WORKAROUND_13204(efx) &&
+ (advertising & ADVERTISED_100baseT_Full))
+ reg |= 1 << PMA_PMD_100TX_ADV_LBN;
+ if (advertising & ADVERTISED_1000baseT_Full)
+ reg |= 1 << PMA_PMD_1000T_ADV_LBN;
+ if (advertising & ADVERTISED_10000baseT_Full)
+ reg |= 1 << PMA_PMD_10000T_ADV_LBN;
+ mdio_clause45_write(efx, phy, MDIO_MMD_PMAPMD,
+ PMA_PMD_SPEED_ENABLE_REG, reg);
+
+ enabled = (advertising &
+ (ADVERTISED_1000baseT_Half |
+ ADVERTISED_1000baseT_Full |
+ ADVERTISED_10000baseT_Full));
+ if (EFX_WORKAROUND_13204(efx))
+ enabled |= (advertising & ADVERTISED_100baseT_Full);
+ return enabled;
+}
+
+struct efx_phy_operations falcon_sfx7101_phy_ops = {
+ .macs = EFX_XMAC,
+ .init = tenxpress_phy_init,
+ .reconfigure = tenxpress_phy_reconfigure,
+ .poll = tenxpress_phy_poll,
+ .fini = tenxpress_phy_fini,
+ .clear_interrupt = efx_port_dummy_op_void,
+ .get_settings = sfx7101_get_settings,
+ .set_settings = mdio_clause45_set_settings,
+ .num_tests = ARRAY_SIZE(sfx7101_test_names),
+ .test_names = sfx7101_test_names,
+ .run_tests = sfx7101_run_tests,
+ .mmds = TENXPRESS_REQUIRED_DEVS,
+ .loopbacks = SFX7101_LOOPBACKS,
+};
+
+struct efx_phy_operations falcon_sft9001_phy_ops = {
+ .macs = EFX_GMAC | EFX_XMAC,
.init = tenxpress_phy_init,
.reconfigure = tenxpress_phy_reconfigure,
- .check_hw = tenxpress_phy_check_hw,
+ .poll = tenxpress_phy_poll,
.fini = tenxpress_phy_fini,
- .clear_interrupt = tenxpress_phy_clear_interrupt,
- .test = tenxpress_phy_test,
+ .clear_interrupt = efx_port_dummy_op_void,
+ .get_settings = sft9001_get_settings,
+ .set_settings = sft9001_set_settings,
+ .set_xnp_advertise = sft9001_set_xnp_advertise,
+ .num_tests = ARRAY_SIZE(sft9001_test_names),
+ .test_names = sft9001_test_names,
+ .run_tests = sft9001_run_tests,
.mmds = TENXPRESS_REQUIRED_DEVS,
- .loopbacks = TENXPRESS_LOOPBACKS,
+ .loopbacks = SFT9001_LOOPBACKS,
};
diff --git a/drivers/net/sfc/workarounds.h b/drivers/net/sfc/workarounds.h
index fa7b49d69288..82e03e1d7371 100644
--- a/drivers/net/sfc/workarounds.h
+++ b/drivers/net/sfc/workarounds.h
@@ -17,15 +17,20 @@
#define EFX_WORKAROUND_ALWAYS(efx) 1
#define EFX_WORKAROUND_FALCON_A(efx) (falcon_rev(efx) <= FALCON_REV_A1)
+#define EFX_WORKAROUND_10G(efx) EFX_IS10G(efx)
+#define EFX_WORKAROUND_SFX7101(efx) ((efx)->phy_type == PHY_TYPE_SFX7101)
+#define EFX_WORKAROUND_SFT9001A(efx) ((efx)->phy_type == PHY_TYPE_SFT9001A)
/* XAUI resets if link not detected */
#define EFX_WORKAROUND_5147 EFX_WORKAROUND_ALWAYS
/* RX PCIe double split performance issue */
#define EFX_WORKAROUND_7575 EFX_WORKAROUND_ALWAYS
+/* Bit-bashed I2C reads cause performance drop */
+#define EFX_WORKAROUND_7884 EFX_WORKAROUND_10G
/* TX pkt parser problem with <= 16 byte TXes */
#define EFX_WORKAROUND_9141 EFX_WORKAROUND_ALWAYS
/* Low rate CRC errors require XAUI reset */
-#define EFX_WORKAROUND_10750 EFX_WORKAROUND_ALWAYS
+#define EFX_WORKAROUND_10750 EFX_WORKAROUND_SFX7101
/* TX_EV_PKT_ERR can be caused by a dangling TX descriptor
* or a PCIe error (bug 11028) */
#define EFX_WORKAROUND_10727 EFX_WORKAROUND_ALWAYS
@@ -49,4 +54,9 @@
/* Leak overlength packets rather than free */
#define EFX_WORKAROUND_8071 EFX_WORKAROUND_FALCON_A
+/* Need to send XNP pages for 100BaseT */
+#define EFX_WORKAROUND_13204 EFX_WORKAROUND_SFT9001A
+/* Need to keep AN enabled */
+#define EFX_WORKAROUND_13963 EFX_WORKAROUND_SFT9001A
+
#endif /* EFX_WORKAROUNDS_H */
diff --git a/drivers/net/sfc/xfp_phy.c b/drivers/net/sfc/xfp_phy.c
index 276151df3a70..2d50b6ecf5f9 100644
--- a/drivers/net/sfc/xfp_phy.c
+++ b/drivers/net/sfc/xfp_phy.c
@@ -7,22 +7,21 @@
* by the Free Software Foundation, incorporated herein by reference.
*/
/*
- * Driver for XFP optical PHYs (plus some support specific to the Quake 2032)
+ * Driver for XFP optical PHYs (plus some support specific to the Quake 2022/32)
* See www.amcc.com for details (search for qt2032)
*/
#include <linux/timer.h>
#include <linux/delay.h>
#include "efx.h"
-#include "gmii.h"
#include "mdio_10g.h"
#include "xenpack.h"
#include "phy.h"
-#include "mac.h"
+#include "falcon.h"
-#define XFP_REQUIRED_DEVS (MDIO_MMDREG_DEVS0_PCS | \
- MDIO_MMDREG_DEVS0_PMAPMD | \
- MDIO_MMDREG_DEVS0_PHYXS)
+#define XFP_REQUIRED_DEVS (MDIO_MMDREG_DEVS_PCS | \
+ MDIO_MMDREG_DEVS_PMAPMD | \
+ MDIO_MMDREG_DEVS_PHYXS)
#define XFP_LOOPBACKS ((1 << LOOPBACK_PCS) | \
(1 << LOOPBACK_PMAPMD) | \
@@ -65,7 +64,7 @@ static int xfp_reset_phy(struct efx_nic *efx)
/* Check that all the MMDs we expect are present and responding. We
* expect faults on some if the link is down, but not on the PHY XS */
rc = mdio_clause45_check_mmds(efx, XFP_REQUIRED_DEVS,
- MDIO_MMDREG_DEVS0_PHYXS);
+ MDIO_MMDREG_DEVS_PHYXS);
if (rc < 0)
goto fail;
@@ -120,15 +119,12 @@ static int xfp_link_ok(struct efx_nic *efx)
return mdio_clause45_links_ok(efx, XFP_REQUIRED_DEVS);
}
-static int xfp_phy_check_hw(struct efx_nic *efx)
+static void xfp_phy_poll(struct efx_nic *efx)
{
- int rc = 0;
int link_up = xfp_link_ok(efx);
/* Simulate a PHY event if link state has changed */
if (link_up != efx->link_up)
- falcon_xmac_sim_phy_event(efx);
-
- return rc;
+ falcon_sim_phy_event(efx);
}
static void xfp_phy_reconfigure(struct efx_nic *efx)
@@ -145,7 +141,9 @@ static void xfp_phy_reconfigure(struct efx_nic *efx)
phy_data->phy_mode = efx->phy_mode;
efx->link_up = xfp_link_ok(efx);
- efx->link_options = GM_LPA_10000FULL;
+ efx->link_speed = 10000;
+ efx->link_fd = true;
+ efx->link_fc = efx->wanted_fc;
}
@@ -160,11 +158,14 @@ static void xfp_phy_fini(struct efx_nic *efx)
}
struct efx_phy_operations falcon_xfp_phy_ops = {
+ .macs = EFX_XMAC,
.init = xfp_phy_init,
.reconfigure = xfp_phy_reconfigure,
- .check_hw = xfp_phy_check_hw,
+ .poll = xfp_phy_poll,
.fini = xfp_phy_fini,
.clear_interrupt = xfp_phy_clear_interrupt,
+ .get_settings = mdio_clause45_get_settings,
+ .set_settings = mdio_clause45_set_settings,
.mmds = XFP_REQUIRED_DEVS,
.loopbacks = XFP_LOOPBACKS,
};
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
index 6261201403cd..97d68560067d 100644
--- a/drivers/net/sgiseeq.c
+++ b/drivers/net/sgiseeq.c
@@ -377,7 +377,6 @@ memory_squeeze:
skb_put(skb, len);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
} else {
@@ -657,7 +656,7 @@ static void timeout(struct net_device *dev)
static void sgiseeq_set_multicast(struct net_device *dev)
{
- struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
+ struct sgiseeq_private *sp = netdev_priv(dev);
unsigned char oldmode = sp->mode;
if(dev->flags & IFF_PROMISC)
@@ -719,7 +718,6 @@ static int __init sgiseeq_probe(struct platform_device *pdev)
struct sgiseeq_private *sp;
struct net_device *dev;
int err;
- DECLARE_MAC_BUF(mac);
dev = alloc_etherdev(sizeof (struct sgiseeq_private));
if (!dev) {
@@ -793,8 +791,7 @@ static int __init sgiseeq_probe(struct platform_device *pdev)
goto err_out_free_page;
}
- printk(KERN_INFO "%s: %s %s\n",
- dev->name, sgiseeqstr, print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "%s: %s %pM\n", dev->name, sgiseeqstr, dev->dev_addr);
return 0;
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index 59f242a67714..7f8e514eb5e9 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -540,7 +540,6 @@ static int sh_eth_rx(struct net_device *ndev)
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, ndev);
netif_rx(skb);
- ndev->last_rx = jiffies;
mdp->stats.rx_packets++;
mdp->stats.rx_bytes += pkt_len;
}
@@ -800,7 +799,7 @@ static int sh_eth_phy_init(struct net_device *ndev)
char phy_id[BUS_ID_SIZE];
struct phy_device *phydev = NULL;
- snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT,
+ snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
mdp->mii_bus->id , mdp->phy_id);
mdp->link = PHY_DOWN;
diff --git a/drivers/net/sis190.c b/drivers/net/sis190.c
index e6e3bf58a569..83cc3c5f7946 100644
--- a/drivers/net/sis190.c
+++ b/drivers/net/sis190.c
@@ -627,7 +627,6 @@ static int sis190_rx_interrupt(struct net_device *dev,
sis190_rx_skb(skb);
- dev->last_rx = jiffies;
stats->rx_packets++;
stats->rx_bytes += pkt_size;
if ((status & BCAST) == MCAST)
@@ -1791,7 +1790,6 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
struct net_device *dev;
void __iomem *ioaddr;
int rc;
- DECLARE_MAC_BUF(mac);
if (!printed_version) {
net_drv(&debug, KERN_INFO SIS190_DRIVER_NAME " loaded.\n");
@@ -1841,10 +1839,9 @@ static int __devinit sis190_init_one(struct pci_dev *pdev,
if (rc < 0)
goto err_remove_mii;
- net_probe(tp, KERN_INFO "%s: %s at %p (IRQ: %d), "
- "%s\n",
+ net_probe(tp, KERN_INFO "%s: %s at %p (IRQ: %d), %pM\n",
pci_name(pdev), sis_chip_info[ent->driver_data].name,
- ioaddr, dev->irq, print_mac(mac, dev->dev_addr));
+ ioaddr, dev->irq, dev->dev_addr);
net_probe(tp, KERN_INFO "%s: %s mode.\n", dev->name,
(tp->features & F_HAS_RGMII) ? "RGMII" : "GMII");
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index 8e8337e8b072..4acd41a093ad 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -381,6 +381,21 @@ static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev,
return 0;
}
+static const struct net_device_ops sis900_netdev_ops = {
+ .ndo_open = sis900_open,
+ .ndo_stop = sis900_close,
+ .ndo_start_xmit = sis900_start_xmit,
+ .ndo_set_config = sis900_set_config,
+ .ndo_set_multicast_list = set_rx_mode,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_do_ioctl = mii_ioctl,
+ .ndo_tx_timeout = sis900_tx_timeout,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = sis900_poll,
+#endif
+};
+
/**
* sis900_probe - Probe for sis900 device
* @pci_dev: the sis900 pci device
@@ -404,7 +419,6 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
int i, ret;
const char *card_name = card_names[pci_id->driver_data];
const char *dev_name = pci_name(pci_dev);
- DECLARE_MAC_BUF(mac);
/* when built into the kernel, we only print version if device is found */
#ifndef MODULE
@@ -437,7 +451,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
if (ret)
goto err_out;
- sis_priv = net_dev->priv;
+ sis_priv = netdev_priv(net_dev);
net_dev->base_addr = ioaddr;
net_dev->irq = pci_dev->irq;
sis_priv->pci_dev = pci_dev;
@@ -462,20 +476,10 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
sis_priv->rx_ring_dma = ring_dma;
/* The SiS900-specific entries in the device structure. */
- net_dev->open = &sis900_open;
- net_dev->hard_start_xmit = &sis900_start_xmit;
- net_dev->stop = &sis900_close;
- net_dev->set_config = &sis900_set_config;
- net_dev->set_multicast_list = &set_rx_mode;
- net_dev->do_ioctl = &mii_ioctl;
- net_dev->tx_timeout = sis900_tx_timeout;
+ net_dev->netdev_ops = &sis900_netdev_ops;
net_dev->watchdog_timeo = TX_TIMEOUT;
net_dev->ethtool_ops = &sis900_ethtool_ops;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- net_dev->poll_controller = &sis900_poll;
-#endif
-
if (sis900_debug > 0)
sis_priv->msg_enable = sis900_debug;
else
@@ -534,9 +538,9 @@ 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, %s\n",
+ printk(KERN_INFO "%s: %s at %#lx, IRQ %d, %pM\n",
net_dev->name, card_name, ioaddr, net_dev->irq,
- print_mac(mac, net_dev->dev_addr));
+ net_dev->dev_addr);
/* Detect Wake on Lan support */
ret = (inl(net_dev->base_addr + CFGPMC) & PMESP) >> 27;
@@ -570,7 +574,7 @@ static int __devinit sis900_probe(struct pci_dev *pci_dev,
static int __devinit sis900_mii_probe(struct net_device * net_dev)
{
- struct sis900_private * sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
const char *dev_name = pci_name(sis_priv->pci_dev);
u16 poll_bit = MII_STAT_LINK, status = 0;
unsigned long timeout = jiffies + 5 * HZ;
@@ -698,7 +702,7 @@ static int __devinit sis900_mii_probe(struct net_device * net_dev)
static u16 sis900_default_phy(struct net_device * net_dev)
{
- struct sis900_private * sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
struct mii_phy *phy = NULL, *phy_home = NULL,
*default_phy = NULL, *phy_lan = NULL;
u16 status;
@@ -999,7 +1003,7 @@ static void sis900_poll(struct net_device *dev)
static int
sis900_open(struct net_device *net_dev)
{
- struct sis900_private *sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
long ioaddr = net_dev->base_addr;
int ret;
@@ -1055,7 +1059,7 @@ sis900_open(struct net_device *net_dev)
static void
sis900_init_rxfilter (struct net_device * net_dev)
{
- struct sis900_private *sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
long ioaddr = net_dev->base_addr;
u32 rfcrSave;
u32 i;
@@ -1093,7 +1097,7 @@ sis900_init_rxfilter (struct net_device * net_dev)
static void
sis900_init_tx_ring(struct net_device *net_dev)
{
- struct sis900_private *sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
long ioaddr = net_dev->base_addr;
int i;
@@ -1127,7 +1131,7 @@ sis900_init_tx_ring(struct net_device *net_dev)
static void
sis900_init_rx_ring(struct net_device *net_dev)
{
- struct sis900_private *sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
long ioaddr = net_dev->base_addr;
int i;
@@ -1198,7 +1202,7 @@ sis900_init_rx_ring(struct net_device *net_dev)
static void sis630_set_eq(struct net_device *net_dev, u8 revision)
{
- struct sis900_private *sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
u16 reg14h, eq_value=0, max_value=0, min_value=0;
int i, maxcount=10;
@@ -1271,13 +1275,13 @@ static void sis630_set_eq(struct net_device *net_dev, u8 revision)
static void sis900_timer(unsigned long data)
{
struct net_device *net_dev = (struct net_device *)data;
- struct sis900_private *sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
struct mii_phy *mii_phy = sis_priv->mii;
static const int next_tick = 5*HZ;
u16 status;
if (!sis_priv->autong_complete){
- int speed, duplex = 0;
+ int uninitialized_var(speed), duplex = 0;
sis900_read_mode(net_dev, &speed, &duplex);
if (duplex){
@@ -1341,7 +1345,7 @@ 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 = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
long ioaddr = net_dev->base_addr;
int speed, duplex;
@@ -1420,7 +1424,7 @@ static void sis900_set_mode (long ioaddr, int speed, int duplex)
static void sis900_auto_negotiate(struct net_device *net_dev, int phy_addr)
{
- struct sis900_private *sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
int i = 0;
u32 status;
@@ -1455,7 +1459,7 @@ static void sis900_auto_negotiate(struct net_device *net_dev, int phy_addr)
static void sis900_read_mode(struct net_device *net_dev, int *speed, int *duplex)
{
- struct sis900_private *sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
struct mii_phy *phy = sis_priv->mii;
int phy_addr = sis_priv->cur_phy;
u32 status;
@@ -1510,7 +1514,7 @@ 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 = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
long ioaddr = net_dev->base_addr;
unsigned long flags;
int i;
@@ -1569,7 +1573,7 @@ static void sis900_tx_timeout(struct net_device *net_dev)
static int
sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
{
- struct sis900_private *sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
long ioaddr = net_dev->base_addr;
unsigned int entry;
unsigned long flags;
@@ -1638,7 +1642,7 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
static irqreturn_t sis900_interrupt(int irq, void *dev_instance)
{
struct net_device *net_dev = dev_instance;
- struct sis900_private *sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
int boguscnt = max_interrupt_work;
long ioaddr = net_dev->base_addr;
u32 status;
@@ -1700,7 +1704,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 = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
long ioaddr = net_dev->base_addr;
unsigned int entry = sis_priv->cur_rx % NUM_RX_DESC;
u32 rx_status = sis_priv->rx_ring[entry].cmdsts;
@@ -1789,7 +1793,6 @@ static int sis900_rx(struct net_device *net_dev)
/* some network statistics */
if ((rx_status & BCAST) == MCAST)
net_dev->stats.multicast++;
- net_dev->last_rx = jiffies;
net_dev->stats.rx_bytes += rx_size;
net_dev->stats.rx_packets++;
sis_priv->dirty_rx++;
@@ -1850,7 +1853,7 @@ refill_rx_ring:
static void sis900_finish_xmit (struct net_device *net_dev)
{
- struct sis900_private *sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
for (; sis_priv->dirty_tx != sis_priv->cur_tx; sis_priv->dirty_tx++) {
struct sk_buff *skb;
@@ -1919,7 +1922,7 @@ 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 = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
struct sk_buff *skb;
int i;
@@ -1974,7 +1977,7 @@ static int sis900_close(struct net_device *net_dev)
static void sis900_get_drvinfo(struct net_device *net_dev,
struct ethtool_drvinfo *info)
{
- struct sis900_private *sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
strcpy (info->driver, SIS900_MODULE_NAME);
strcpy (info->version, SIS900_DRV_VERSION);
@@ -1983,26 +1986,26 @@ static void sis900_get_drvinfo(struct net_device *net_dev,
static u32 sis900_get_msglevel(struct net_device *net_dev)
{
- struct sis900_private *sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
return sis_priv->msg_enable;
}
static void sis900_set_msglevel(struct net_device *net_dev, u32 value)
{
- struct sis900_private *sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
sis_priv->msg_enable = value;
}
static u32 sis900_get_link(struct net_device *net_dev)
{
- struct sis900_private *sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
return mii_link_ok(&sis_priv->mii_info);
}
static int sis900_get_settings(struct net_device *net_dev,
struct ethtool_cmd *cmd)
{
- struct sis900_private *sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
spin_lock_irq(&sis_priv->lock);
mii_ethtool_gset(&sis_priv->mii_info, cmd);
spin_unlock_irq(&sis_priv->lock);
@@ -2012,7 +2015,7 @@ static int sis900_get_settings(struct net_device *net_dev,
static int sis900_set_settings(struct net_device *net_dev,
struct ethtool_cmd *cmd)
{
- struct sis900_private *sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
int rt;
spin_lock_irq(&sis_priv->lock);
rt = mii_ethtool_sset(&sis_priv->mii_info, cmd);
@@ -2022,7 +2025,7 @@ static int sis900_set_settings(struct net_device *net_dev,
static int sis900_nway_reset(struct net_device *net_dev)
{
- struct sis900_private *sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
return mii_nway_restart(&sis_priv->mii_info);
}
@@ -2039,7 +2042,7 @@ 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 = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
long pmctrl_addr = net_dev->base_addr + pmctrl;
u32 cfgpmcsr = 0, pmctrl_bits = 0;
@@ -2110,7 +2113,7 @@ static const struct ethtool_ops sis900_ethtool_ops = {
static int mii_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd)
{
- struct sis900_private *sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
struct mii_ioctl_data *data = if_mii(rq);
switch(cmd) {
@@ -2144,7 +2147,7 @@ static int mii_ioctl(struct net_device *net_dev, struct ifreq *rq, int cmd)
static int sis900_set_config(struct net_device *dev, struct ifmap *map)
{
- struct sis900_private *sis_priv = dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(dev);
struct mii_phy *mii_phy = sis_priv->mii;
u16 status;
@@ -2267,7 +2270,7 @@ 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 = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
u16 mc_filter[16] = {0}; /* 256/128 bits multicast hash table */
int i, table_entries;
u32 rx_mode;
@@ -2342,7 +2345,7 @@ static void set_rx_mode(struct net_device *net_dev)
static void sis900_reset(struct net_device *net_dev)
{
- struct sis900_private * sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
long ioaddr = net_dev->base_addr;
int i = 0;
u32 status = TxRCMP | RxRCMP;
@@ -2375,7 +2378,7 @@ static void sis900_reset(struct net_device *net_dev)
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 = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
struct mii_phy *phy = NULL;
while (sis_priv->first_mii) {
@@ -2419,7 +2422,7 @@ static int sis900_suspend(struct pci_dev *pci_dev, pm_message_t state)
static int sis900_resume(struct pci_dev *pci_dev)
{
struct net_device *net_dev = pci_get_drvdata(pci_dev);
- struct sis900_private *sis_priv = net_dev->priv;
+ struct sis900_private *sis_priv = netdev_priv(net_dev);
long ioaddr = net_dev->base_addr;
if(!netif_running(net_dev))
diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c
index a2b092bb3626..607efeaf0bc5 100644
--- a/drivers/net/skfp/skfddi.c
+++ b/drivers/net/skfp/skfddi.c
@@ -168,6 +168,17 @@ static int num_boards; /* total number of adapters configured */
#define PRINTK(s, args...)
#endif // DRIVERDEBUG
+static const struct net_device_ops skfp_netdev_ops = {
+ .ndo_open = skfp_open,
+ .ndo_stop = skfp_close,
+ .ndo_start_xmit = skfp_send_pkt,
+ .ndo_get_stats = skfp_ctl_get_stats,
+ .ndo_change_mtu = fddi_change_mtu,
+ .ndo_set_multicast_list = skfp_ctl_set_multicast_list,
+ .ndo_set_mac_address = skfp_ctl_set_mac_address,
+ .ndo_do_ioctl = skfp_ioctl,
+};
+
/*
* =================
* = skfp_init_one =
@@ -253,13 +264,7 @@ static int skfp_init_one(struct pci_dev *pdev,
}
dev->irq = pdev->irq;
- dev->get_stats = &skfp_ctl_get_stats;
- dev->open = &skfp_open;
- dev->stop = &skfp_close;
- dev->hard_start_xmit = &skfp_send_pkt;
- dev->set_multicast_list = &skfp_ctl_set_multicast_list;
- dev->set_mac_address = &skfp_ctl_set_mac_address;
- dev->do_ioctl = &skfp_ioctl;
+ dev->netdev_ops = &skfp_netdev_ops;
SET_NETDEV_DEV(dev, &pdev->dev);
@@ -612,7 +617,7 @@ static int skfp_close(struct net_device *dev)
* Interrupts are disabled, then reenabled at the adapter.
*/
-irqreturn_t skfp_interrupt(int irq, void *dev_id)
+static irqreturn_t skfp_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct s_smc *smc; /* private board structure pointer */
@@ -679,7 +684,7 @@ irqreturn_t skfp_interrupt(int irq, void *dev_id)
* independent.
*
*/
-struct net_device_stats *skfp_ctl_get_stats(struct net_device *dev)
+static struct net_device_stats *skfp_ctl_get_stats(struct net_device *dev)
{
struct s_smc *bp = netdev_priv(dev);
@@ -1224,7 +1229,7 @@ static void send_queued_packets(struct s_smc *smc)
* Verify if the source address is set. Insert it if necessary.
*
************************/
-void CheckSourceAddress(unsigned char *frame, unsigned char *hw_addr)
+static void CheckSourceAddress(unsigned char *frame, unsigned char *hw_addr)
{
unsigned char SRBit;
@@ -1680,7 +1685,6 @@ void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd,
skb->protocol = fddi_type_trans(skb, bp->dev);
netif_rx(skb);
- bp->dev->last_rx = jiffies;
HWM_RX_CHECK(smc, RX_LOW_WATERMARK);
return;
@@ -1939,7 +1943,6 @@ int mac_drv_rx_init(struct s_smc *smc, int len, int fc,
// deliver frame to system
skb->protocol = fddi_type_trans(skb, smc->os.dev);
- skb->dev->last_rx = jiffies;
netif_rx(skb);
return (0);
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index 43f4c730be42..c9dbb06f8c94 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -104,6 +104,7 @@ static void yukon_get_stats(struct skge_port *skge, u64 *data);
static void yukon_init(struct skge_hw *hw, int port);
static void genesis_mac_init(struct skge_hw *hw, int port);
static void genesis_link_up(struct skge_port *skge);
+static void skge_set_multicast(struct net_device *dev);
/* Avoid conditionals by using array */
static const int txqaddr[] = { Q_XA1, Q_XA2 };
@@ -149,24 +150,6 @@ static u32 wol_supported(const struct skge_hw *hw)
return WAKE_MAGIC | WAKE_PHY;
}
-static u32 pci_wake_enabled(struct pci_dev *dev)
-{
- int pm = pci_find_capability(dev, PCI_CAP_ID_PM);
- u16 value;
-
- /* If device doesn't support PM Capabilities, but request is to disable
- * wake events, it's a nop; otherwise fail */
- if (!pm)
- return 0;
-
- pci_read_config_word(dev, pm + PCI_PM_PMC, &value);
-
- value &= PCI_PM_CAP_PME_MASK;
- value >>= ffs(PCI_PM_CAP_PME_MASK) - 1; /* First bit of mask */
-
- return value != 0;
-}
-
static void skge_wol_init(struct skge_port *skge)
{
struct skge_hw *hw = skge->hw;
@@ -254,10 +237,14 @@ static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
struct skge_port *skge = netdev_priv(dev);
struct skge_hw *hw = skge->hw;
- if (wol->wolopts & ~wol_supported(hw))
+ if ((wol->wolopts & ~wol_supported(hw))
+ || !device_can_wakeup(&hw->pdev->dev))
return -EOPNOTSUPP;
skge->wol = wol->wolopts;
+
+ device_set_wakeup_enable(&hw->pdev->dev, skge->wol);
+
return 0;
}
@@ -2477,7 +2464,7 @@ static void skge_phy_reset(struct skge_port *skge)
}
spin_unlock_bh(&hw->phy_lock);
- dev->set_multicast_list(dev);
+ skge_set_multicast(dev);
}
/* Basic MII support */
@@ -3045,6 +3032,18 @@ static inline int bad_phy_status(const struct skge_hw *hw, u32 status)
(status & GMR_FS_RX_OK) == 0;
}
+static void skge_set_multicast(struct net_device *dev)
+{
+ struct skge_port *skge = netdev_priv(dev);
+ struct skge_hw *hw = skge->hw;
+
+ if (hw->chip_id == CHIP_ID_GENESIS)
+ genesis_set_multicast(dev);
+ else
+ yukon_set_multicast(dev);
+
+}
+
/* Get receive buffer from descriptor.
* Handles copy of small buffers and reallocation failures
@@ -3200,7 +3199,6 @@ static int skge_poll(struct napi_struct *napi, int to_do)
skb = skge_rx_get(dev, e, control, rd->status, rd->csum2);
if (likely(skb)) {
- dev->last_rx = jiffies;
netif_receive_skb(skb);
++work_done;
@@ -3216,7 +3214,7 @@ static int skge_poll(struct napi_struct *napi, int to_do)
unsigned long flags;
spin_lock_irqsave(&hw->hw_lock, flags);
- __netif_rx_complete(dev, napi);
+ __netif_rx_complete(napi);
hw->intr_mask |= napimask[skge->port];
skge_write32(hw, B0_IMSK, hw->intr_mask);
skge_read32(hw, B0_IMSK);
@@ -3379,7 +3377,7 @@ static irqreturn_t skge_intr(int irq, void *dev_id)
if (status & (IS_XA1_F|IS_R1_F)) {
struct skge_port *skge = netdev_priv(hw->dev[0]);
hw->intr_mask &= ~(IS_XA1_F|IS_R1_F);
- netif_rx_schedule(hw->dev[0], &skge->napi);
+ netif_rx_schedule(&skge->napi);
}
if (status & IS_PA_TO_TX1)
@@ -3399,7 +3397,7 @@ static irqreturn_t skge_intr(int irq, void *dev_id)
if (status & (IS_XA2_F|IS_R2_F)) {
hw->intr_mask &= ~(IS_XA2_F|IS_R2_F);
- netif_rx_schedule(hw->dev[1], &skge->napi);
+ netif_rx_schedule(&skge->napi);
}
if (status & IS_PA_TO_RX2) {
@@ -3730,7 +3728,7 @@ static int skge_device_event(struct notifier_block *unused,
struct skge_port *skge;
struct dentry *d;
- if (dev->open != &skge_up || !skge_debug)
+ if (dev->netdev_ops->ndo_open != &skge_up || !skge_debug)
goto done;
skge = netdev_priv(dev);
@@ -3804,6 +3802,23 @@ static __exit void skge_debug_cleanup(void)
#define skge_debug_cleanup()
#endif
+static const struct net_device_ops skge_netdev_ops = {
+ .ndo_open = skge_up,
+ .ndo_stop = skge_down,
+ .ndo_start_xmit = skge_xmit_frame,
+ .ndo_do_ioctl = skge_ioctl,
+ .ndo_get_stats = skge_get_stats,
+ .ndo_tx_timeout = skge_tx_timeout,
+ .ndo_change_mtu = skge_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_multicast_list = skge_set_multicast,
+ .ndo_set_mac_address = skge_set_mac_address,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = skge_netpoll,
+#endif
+};
+
+
/* Initialize network device */
static struct net_device *skge_devinit(struct skge_hw *hw, int port,
int highmem)
@@ -3817,24 +3832,9 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
}
SET_NETDEV_DEV(dev, &hw->pdev->dev);
- dev->open = skge_up;
- dev->stop = skge_down;
- dev->do_ioctl = skge_ioctl;
- dev->hard_start_xmit = skge_xmit_frame;
- dev->get_stats = skge_get_stats;
- if (hw->chip_id == CHIP_ID_GENESIS)
- dev->set_multicast_list = genesis_set_multicast;
- else
- dev->set_multicast_list = yukon_set_multicast;
-
- dev->set_mac_address = skge_set_mac_address;
- dev->change_mtu = skge_change_mtu;
- SET_ETHTOOL_OPS(dev, &skge_ethtool_ops);
- dev->tx_timeout = skge_tx_timeout;
+ dev->netdev_ops = &skge_netdev_ops;
+ dev->ethtool_ops = &skge_ethtool_ops;
dev->watchdog_timeo = TX_WATCHDOG;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = skge_netpoll;
-#endif
dev->irq = hw->pdev->irq;
if (highmem)
@@ -3856,7 +3856,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
skge->speed = -1;
skge->advertising = skge_supported_modes(hw);
- if (pci_wake_enabled(hw->pdev))
+ if (device_may_wakeup(&hw->pdev->dev))
skge->wol = wol_supported(hw) & WAKE_MAGIC;
hw->dev[port] = dev;
@@ -3885,11 +3885,10 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port,
static void __devinit skge_show_addr(struct net_device *dev)
{
const struct skge_port *skge = netdev_priv(dev);
- DECLARE_MAC_BUF(mac);
if (netif_msg_probe(skge))
- printk(KERN_INFO PFX "%s: addr %s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO PFX "%s: addr %pM\n",
+ dev->name, dev->dev_addr);
}
static int __devinit skge_probe(struct pci_dev *pdev,
@@ -4082,8 +4081,8 @@ static int skge_suspend(struct pci_dev *pdev, pm_message_t state)
}
skge_write32(hw, B0_IMSK, 0);
- pci_enable_wake(pdev, pci_choose_state(pdev, state), wol);
- pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ pci_prepare_to_sleep(pdev);
return 0;
}
@@ -4096,7 +4095,7 @@ static int skge_resume(struct pci_dev *pdev)
if (!hw)
return 0;
- err = pci_set_power_state(pdev, PCI_D0);
+ err = pci_back_from_sleep(pdev);
if (err)
goto out;
@@ -4104,8 +4103,6 @@ static int skge_resume(struct pci_dev *pdev)
if (err)
goto out;
- pci_enable_wake(pdev, PCI_D0, 0);
-
err = skge_reset(hw);
if (err)
goto out;
@@ -4146,8 +4143,8 @@ static void skge_shutdown(struct pci_dev *pdev)
wol |= skge->wol;
}
- pci_enable_wake(pdev, PCI_D3hot, wol);
- pci_enable_wake(pdev, PCI_D3cold, wol);
+ if (pci_enable_wake(pdev, PCI_D3cold, wol))
+ pci_enable_wake(pdev, PCI_D3hot, wol);
pci_disable_device(pdev);
pci_set_power_state(pdev, PCI_D3hot);
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 3813d15e2df7..3668e81e474d 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -3979,7 +3979,7 @@ static int sky2_device_event(struct notifier_block *unused,
struct net_device *dev = ptr;
struct sky2_port *sky2 = netdev_priv(dev);
- if (dev->open != sky2_up || !sky2_debug)
+ if (dev->netdev_ops->ndo_open != sky2_up || !sky2_debug)
return NOTIFY_DONE;
switch(event) {
@@ -4041,6 +4041,41 @@ static __exit void sky2_debug_cleanup(void)
#define sky2_debug_cleanup()
#endif
+/* Two copies of network device operations to handle special case of
+ not allowing netpoll on second port */
+static const struct net_device_ops sky2_netdev_ops[2] = {
+ {
+ .ndo_open = sky2_up,
+ .ndo_stop = sky2_down,
+ .ndo_start_xmit = sky2_xmit_frame,
+ .ndo_do_ioctl = sky2_ioctl,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = sky2_set_mac_address,
+ .ndo_set_multicast_list = sky2_set_multicast,
+ .ndo_change_mtu = sky2_change_mtu,
+ .ndo_tx_timeout = sky2_tx_timeout,
+#ifdef SKY2_VLAN_TAG_USED
+ .ndo_vlan_rx_register = sky2_vlan_rx_register,
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = sky2_netpoll,
+#endif
+ },
+ {
+ .ndo_open = sky2_up,
+ .ndo_stop = sky2_down,
+ .ndo_start_xmit = sky2_xmit_frame,
+ .ndo_do_ioctl = sky2_ioctl,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_mac_address = sky2_set_mac_address,
+ .ndo_set_multicast_list = sky2_set_multicast,
+ .ndo_change_mtu = sky2_change_mtu,
+ .ndo_tx_timeout = sky2_tx_timeout,
+#ifdef SKY2_VLAN_TAG_USED
+ .ndo_vlan_rx_register = sky2_vlan_rx_register,
+#endif
+ },
+};
/* Initialize network device */
static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
@@ -4057,20 +4092,9 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
SET_NETDEV_DEV(dev, &hw->pdev->dev);
dev->irq = hw->pdev->irq;
- dev->open = sky2_up;
- dev->stop = sky2_down;
- dev->do_ioctl = sky2_ioctl;
- dev->hard_start_xmit = sky2_xmit_frame;
- dev->set_multicast_list = sky2_set_multicast;
- dev->set_mac_address = sky2_set_mac_address;
- dev->change_mtu = sky2_change_mtu;
SET_ETHTOOL_OPS(dev, &sky2_ethtool_ops);
- dev->tx_timeout = sky2_tx_timeout;
dev->watchdog_timeo = TX_WATCHDOG;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- if (port == 0)
- dev->poll_controller = sky2_netpoll;
-#endif
+ dev->netdev_ops = &sky2_netdev_ops[port];
sky2 = netdev_priv(dev);
sky2->netdev = dev;
@@ -4104,7 +4128,6 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
if (!(sky2->hw->chip_id == CHIP_ID_YUKON_FE_P &&
sky2->hw->chip_rev == CHIP_REV_YU_FE2_A0)) {
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
- dev->vlan_rx_register = sky2_vlan_rx_register;
}
#endif
@@ -4118,11 +4141,10 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
static void __devinit sky2_show_addr(struct net_device *dev)
{
const struct sky2_port *sky2 = netdev_priv(dev);
- DECLARE_MAC_BUF(mac);
if (netif_msg_probe(sky2))
- printk(KERN_INFO PFX "%s: addr %s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO PFX "%s: addr %pM\n",
+ dev->name, dev->dev_addr);
}
/* Handle software interrupt used during MSI test */
diff --git a/drivers/net/slip.c b/drivers/net/slip.c
index 1d58991d395b..8e1c0baf6958 100644
--- a/drivers/net/slip.c
+++ b/drivers/net/slip.c
@@ -365,7 +365,6 @@ static void sl_bump(struct slip *sl)
skb_reset_mac_header(skb);
skb->protocol = htons(ETH_P_IP);
netif_rx(skb);
- sl->dev->last_rx = jiffies;
sl->rx_packets++;
}
@@ -402,7 +401,7 @@ static void sl_encaps(struct slip *sl, unsigned char *icp, int len)
* if we did not request it before write operation.
* 14 Oct 1994 Dmitry Gorodchanin.
*/
- sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
+ set_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
actual = sl->tty->ops->write(sl->tty, sl->xbuff, count);
#ifdef SL_CHECK_TRANSMIT
sl->dev->trans_start = jiffies;
@@ -432,7 +431,7 @@ static void slip_write_wakeup(struct tty_struct *tty)
/* Now serial buffer is almost free & we can start
* transmission of another packet */
sl->tx_packets++;
- tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+ clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
sl_unlock(sl);
return;
}
@@ -465,7 +464,7 @@ static void sl_tx_timeout(struct net_device *dev)
(tty_chars_in_buffer(sl->tty) || sl->xleft) ?
"bad line quality" : "driver error");
sl->xleft = 0;
- sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+ clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
sl_unlock(sl);
#endif
}
@@ -515,10 +514,9 @@ sl_close(struct net_device *dev)
struct slip *sl = netdev_priv(dev);
spin_lock_bh(&sl->lock);
- if (sl->tty) {
+ if (sl->tty)
/* TTY discipline is running. */
- sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
- }
+ clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
netif_stop_queue(dev);
sl->rcount = 0;
sl->xleft = 0;
diff --git a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
index d6abb68e6e2f..404b80e5ba11 100644
--- a/drivers/net/smc-mca.c
+++ b/drivers/net/smc-mca.c
@@ -182,6 +182,22 @@ static char *smc_mca_adapter_names[] __initdata = {
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_multicast_list = ei_set_multicast_list,
+ .ndo_validate_addr = eth_validate_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;
@@ -196,7 +212,6 @@ static int __init ultramca_probe(struct device *gen_dev)
int tirq = 0;
int base_addr = ultra_io[ultra_found];
int irq = ultra_irq[ultra_found];
- DECLARE_MAC_BUF(mac);
if (base_addr || irq) {
printk(KERN_INFO "Probing for SMC MCA adapter");
@@ -334,8 +349,8 @@ static int __init ultramca_probe(struct device *gen_dev)
for (i = 0; i < 6; i++)
dev->dev_addr[i] = inb(ioaddr + 8 + i);
- printk(KERN_INFO "smc_mca[%d]: Parameters: %#3x, %s",
- slot + 1, ioaddr, print_mac(mac, dev->dev_addr));
+ 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.
@@ -385,11 +400,7 @@ static int __init ultramca_probe(struct device *gen_dev)
ei_status.priv = slot;
- dev->open = &ultramca_open;
- dev->stop = &ultramca_close_card;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = ei_poll;
-#endif
+ dev->netdev_ops = &ultramca_netdev_ops;
NS8390_init(dev, 0);
diff --git a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
index 00d6cf1af484..b3866089a206 100644
--- a/drivers/net/smc-ultra.c
+++ b/drivers/net/smc-ultra.c
@@ -187,6 +187,21 @@ out:
}
#endif
+static const struct net_device_ops ultra_netdev_ops = {
+ .ndo_open = ultra_open,
+ .ndo_stop = ultra_close_card,
+
+ .ndo_start_xmit = ei_start_xmit,
+ .ndo_tx_timeout = ei_tx_timeout,
+ .ndo_get_stats = ei_get_stats,
+ .ndo_set_multicast_list = ei_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = ei_poll,
+#endif
+};
+
static int __init ultra_probe1(struct net_device *dev, int ioaddr)
{
int i, retval;
@@ -198,7 +213,6 @@ static int __init ultra_probe1(struct net_device *dev, int ioaddr)
unsigned char num_pages, irqreg, addr, piomode;
unsigned char idreg = inb(ioaddr + 7);
unsigned char reg4 = inb(ioaddr + 4) & 0x7f;
- DECLARE_MAC_BUF(mac);
if (!request_region(ioaddr, ULTRA_IO_EXTENT, DRV_NAME))
return -EBUSY;
@@ -228,8 +242,8 @@ static int __init ultra_probe1(struct net_device *dev, int ioaddr)
for (i = 0; i < 6; i++)
dev->dev_addr[i] = inb(ioaddr + 8 + i);
- printk("%s: %s at %#3x, %s", dev->name, model_name,
- ioaddr, print_mac(mac, dev->dev_addr));
+ printk("%s: %s at %#3x, %pM", dev->name, model_name,
+ ioaddr, dev->dev_addr);
/* Switch from the station address to the alternate register set and
read the useful registers there. */
@@ -301,11 +315,8 @@ static int __init ultra_probe1(struct net_device *dev, int ioaddr)
ei_status.get_8390_hdr = &ultra_get_8390_hdr;
}
ei_status.reset_8390 = &ultra_reset_8390;
- dev->open = &ultra_open;
- dev->stop = &ultra_close_card;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = ei_poll;
-#endif
+
+ dev->netdev_ops = &ultra_netdev_ops;
NS8390_init(dev, 0);
retval = register_netdev(dev);
diff --git a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c
index a5a91ace28cc..cb6c097a2e0a 100644
--- a/drivers/net/smc-ultra32.c
+++ b/drivers/net/smc-ultra32.c
@@ -163,7 +163,6 @@ static int __init ultra32_probe1(struct net_device *dev, int ioaddr)
unsigned char idreg;
unsigned char reg4;
const char *ifmap[] = {"UTP No Link", "", "UTP/AUI", "UTP/BNC"};
- DECLARE_MAC_BUF(mac);
if (!request_region(ioaddr, ULTRA32_IO_EXTENT, DRV_NAME))
return -EBUSY;
@@ -207,8 +206,8 @@ static int __init ultra32_probe1(struct net_device *dev, int ioaddr)
for (i = 0; i < 6; i++)
dev->dev_addr[i] = inb(ioaddr + 8 + i);
- printk("%s: %s at 0x%X, %s",
- dev->name, model_name, ioaddr, print_mac(mac, dev->dev_addr));
+ printk("%s: %s at 0x%X, %pM",
+ dev->name, model_name, ioaddr, dev->dev_addr);
/* Switch from the station address to the alternate register set and
read the useful registers there. */
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 9a16a79b67d0..bf3aa2a1effe 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -439,7 +439,6 @@ static inline void smc911x_rcv(struct net_device *dev)
DBG(SMC_DEBUG_PKTS, "%s: Received packet\n", dev->name);
PRINT_PKT(data, ((pkt_len - 4) <= 64) ? pkt_len - 4 : 64);
- dev->last_rx = jiffies;
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
dev->stats.rx_packets++;
@@ -1231,7 +1230,6 @@ smc911x_rx_dma_irq(int dma, void *data)
BUG_ON(skb == NULL);
lp->current_rx_skb = NULL;
PRINT_PKT(skb->data, skb->len);
- dev->last_rx = jiffies;
skb->protocol = eth_type_trans(skb, dev);
dev->stats.rx_packets++;
dev->stats.rx_bytes += skb->len;
@@ -2050,9 +2048,6 @@ err_out:
*/
static int __devinit smc911x_drv_probe(struct platform_device *pdev)
{
-#ifdef SMC_DYNAMIC_BUS_CONFIG
- struct smc911x_platdata *pd = pdev->dev.platform_data;
-#endif
struct net_device *ndev;
struct resource *res;
struct smc911x_local *lp;
@@ -2087,11 +2082,14 @@ static int __devinit smc911x_drv_probe(struct platform_device *pdev)
lp = netdev_priv(ndev);
lp->netdev = ndev;
#ifdef SMC_DYNAMIC_BUS_CONFIG
- if (!pd) {
- ret = -EINVAL;
- goto release_both;
+ {
+ struct smc911x_platdata *pd = pdev->dev.platform_data;
+ if (!pd) {
+ ret = -EINVAL;
+ goto release_both;
+ }
+ memcpy(&lp->cfg, pd, sizeof(lp->cfg));
}
- memcpy(&lp->cfg, pd, sizeof(lp->cfg));
#endif
addr = ioremap(res->start, SMC911X_IO_EXTENT);
diff --git a/drivers/net/smc9194.c b/drivers/net/smc9194.c
index de67744c4a2a..18d653bbd4e0 100644
--- a/drivers/net/smc9194.c
+++ b/drivers/net/smc9194.c
@@ -764,7 +764,7 @@ out:
. interrupt, so an auto-detect routine can detect it, and find the IRQ,
------------------------------------------------------------------------
*/
-int __init smc_findirq( int ioaddr )
+static int __init smc_findirq(int ioaddr)
{
#ifndef NO_AUTOPROBE
int timeout = 20;
@@ -876,8 +876,6 @@ static int __init smc_probe(struct net_device *dev, int ioaddr)
word memory_info_register;
word memory_cfg_register;
- DECLARE_MAC_BUF(mac);
-
/* Grab the region so that no one else tries to probe our ioports. */
if (!request_region(ioaddr, SMC_IO_EXTENT, DRV_NAME))
return -EBUSY;
@@ -1033,10 +1031,10 @@ static int __init smc_probe(struct net_device *dev, int ioaddr)
/*
. Print the Ethernet address
*/
- printk("ADDR: %s\n", print_mac(mac, dev->dev_addr));
+ printk("ADDR: %pM\n", dev->dev_addr);
/* set the private data to zero by default */
- memset(dev->priv, 0, sizeof(struct smc_local));
+ memset(netdev_priv(dev), 0, sizeof(struct smc_local));
/* Grab the IRQ */
retval = request_irq(dev->irq, &smc_interrupt, 0, DRV_NAME, dev);
@@ -1110,7 +1108,7 @@ static int smc_open(struct net_device *dev)
int i; /* used to set hw ethernet address */
/* clear out all the junk that was put here before... */
- memset(dev->priv, 0, sizeof(struct smc_local));
+ memset(netdev_priv(dev), 0, sizeof(struct smc_local));
/* reset the hardware */
@@ -1166,7 +1164,7 @@ static void smc_timeout(struct net_device *dev)
smc_enable( dev->base_addr );
dev->trans_start = jiffies;
/* clear anything saved */
- ((struct smc_local *)dev->priv)->saved_skb = NULL;
+ ((struct smc_local *)netdev_priv(dev))->saved_skb = NULL;
netif_wake_queue(dev);
}
@@ -1272,7 +1270,6 @@ static void smc_rcv(struct net_device *dev)
skb->protocol = eth_type_trans(skb, dev );
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += packet_length;
} else {
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c
index 35c56abf4113..b215a8d85e62 100644
--- a/drivers/net/smc91x.c
+++ b/drivers/net/smc91x.c
@@ -90,33 +90,6 @@ static const char version[] =
#include "smc91x.h"
-#ifdef CONFIG_ISA
-/*
- * the LAN91C111 can be at any of the following port addresses. To change,
- * for a slightly different card, you can add it to the array. Keep in
- * mind that the array must end in zero.
- */
-static unsigned int smc_portlist[] __initdata = {
- 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0,
- 0x300, 0x320, 0x340, 0x360, 0x380, 0x3A0, 0x3C0, 0x3E0, 0
-};
-
-#ifndef SMC_IOADDR
-# define SMC_IOADDR -1
-#endif
-static unsigned long io = SMC_IOADDR;
-module_param(io, ulong, 0400);
-MODULE_PARM_DESC(io, "I/O base address");
-
-#ifndef SMC_IRQ
-# define SMC_IRQ -1
-#endif
-static int irq = SMC_IRQ;
-module_param(irq, int, 0400);
-MODULE_PARM_DESC(irq, "IRQ number");
-
-#endif /* CONFIG_ISA */
-
#ifndef SMC_NOWAIT
# define SMC_NOWAIT 0
#endif
@@ -518,7 +491,6 @@ static inline void smc_rcv(struct net_device *dev)
PRINT_PKT(data, packet_len - 4);
- dev->last_rx = jiffies;
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
dev->stats.rx_packets++;
@@ -1778,7 +1750,6 @@ static int __devinit smc_probe(struct net_device *dev, void __iomem *ioaddr,
int retval;
unsigned int val, revision_register;
const char *version_string;
- DECLARE_MAC_BUF(mac);
DBG(2, "%s: %s\n", CARDNAME, __func__);
@@ -1972,8 +1943,8 @@ static int __devinit smc_probe(struct net_device *dev, void __iomem *ioaddr,
"set using ifconfig\n", dev->name);
} else {
/* Print the Ethernet address */
- printk("%s: Ethernet addr: %s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ printk("%s: Ethernet addr: %pM\n",
+ dev->name, dev->dev_addr);
}
if (lp->phy_type == 0) {
@@ -2316,15 +2287,6 @@ static struct platform_driver smc_driver = {
static int __init smc_init(void)
{
-#ifdef MODULE
-#ifdef CONFIG_ISA
- if (io == -1)
- printk(KERN_WARNING
- "%s: You shouldn't use auto-probing with insmod!\n",
- CARDNAME);
-#endif
-#endif
-
return platform_driver_register(&smc_driver);
}
diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
index a07cc9351c6b..3e7c6a3cbc65 100644
--- a/drivers/net/smc91x.h
+++ b/drivers/net/smc91x.h
@@ -87,49 +87,28 @@ static inline void SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#define RPC_LSA_DEFAULT RPC_LED_100_10
#define RPC_LSB_DEFAULT RPC_LED_TX_RX
-# if defined (CONFIG_BFIN561_EZKIT)
#define SMC_CAN_USE_8BIT 0
#define SMC_CAN_USE_16BIT 1
+# if defined(CONFIG_BF561)
#define SMC_CAN_USE_32BIT 1
-#define SMC_IO_SHIFT 0
-#define SMC_NOWAIT 1
-#define SMC_USE_BFIN_DMA 0
-
-
-#define SMC_inw(a, r) readw((a) + (r))
-#define SMC_outw(v, a, r) writew(v, (a) + (r))
-#define SMC_inl(a, r) readl((a) + (r))
-#define SMC_outl(v, a, r) writel(v, (a) + (r))
-#define SMC_outsl(a, r, p, l) outsl((unsigned long *)((a) + (r)), p, l)
-#define SMC_insl(a, r, p, l) insl ((unsigned long *)((a) + (r)), p, l)
# else
-#define SMC_CAN_USE_8BIT 0
-#define SMC_CAN_USE_16BIT 1
#define SMC_CAN_USE_32BIT 0
+# endif
#define SMC_IO_SHIFT 0
#define SMC_NOWAIT 1
#define SMC_USE_BFIN_DMA 0
-
-#define SMC_inw(a, r) readw((a) + (r))
-#define SMC_outw(v, a, r) writew(v, (a) + (r))
-#define SMC_outsw(a, r, p, l) outsw((unsigned long *)((a) + (r)), p, l)
-#define SMC_insw(a, r, p, l) insw ((unsigned long *)((a) + (r)), p, l)
+#define SMC_inw(a, r) readw((a) + (r))
+#define SMC_outw(v, a, r) writew(v, (a) + (r))
+#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l)
+# if SMC_CAN_USE_32BIT
+#define SMC_inl(a, r) readl((a) + (r))
+#define SMC_outl(v, a, r) writel(v, (a) + (r))
+#define SMC_insl(a, r, p, l) readsl((a) + (r), p, l)
+#define SMC_outsl(a, r, p, l) writesl((a) + (r), p, l)
# endif
-/* check if the mac in reg is valid */
-#define SMC_GET_MAC_ADDR(lp, addr) \
- do { \
- unsigned int __v; \
- __v = SMC_inw(ioaddr, ADDR0_REG(lp)); \
- addr[0] = __v; addr[1] = __v >> 8; \
- __v = SMC_inw(ioaddr, ADDR1_REG(lp)); \
- addr[2] = __v; addr[3] = __v >> 8; \
- __v = SMC_inw(ioaddr, ADDR2_REG(lp)); \
- addr[4] = __v; addr[5] = __v >> 8; \
- if (*(u32 *)(&addr[0]) == 0xFFFFFFFF) { \
- random_ether_addr(addr); \
- } \
- } while (0)
+
#elif defined(CONFIG_REDWOOD_5) || defined(CONFIG_REDWOOD_6)
/* We can only do 16-bit reads and writes in the static memory space. */
@@ -286,19 +265,6 @@ SMC_outw(u16 val, void __iomem *ioaddr, int reg)
#define SMC_IRQ_FLAGS (0)
-#elif defined(CONFIG_ISA)
-
-#define SMC_CAN_USE_8BIT 1
-#define SMC_CAN_USE_16BIT 1
-#define SMC_CAN_USE_32BIT 0
-
-#define SMC_inb(a, r) inb((a) + (r))
-#define SMC_inw(a, r) inw((a) + (r))
-#define SMC_outb(v, a, r) outb(v, (a) + (r))
-#define SMC_outw(v, a, r) outw(v, (a) + (r))
-#define SMC_insw(a, r, p, l) insw((a) + (r), p, l)
-#define SMC_outsw(a, r, p, l) outsw((a) + (r), p, l)
-
#elif defined(CONFIG_M32R)
#define SMC_CAN_USE_8BIT 0
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
new file mode 100644
index 000000000000..5e989d884ddd
--- /dev/null
+++ b/drivers/net/smsc911x.c
@@ -0,0 +1,2071 @@
+/***************************************************************************
+ *
+ * Copyright (C) 2004-2008 SMSC
+ * Copyright (C) 2005-2008 ARM
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ ***************************************************************************
+ * Rewritten, heavily based on smsc911x simple driver by SMSC.
+ * Partly uses io macros from smc91x.c by Nicolas Pitre
+ *
+ * Supported devices:
+ * LAN9115, LAN9116, LAN9117, LAN9118
+ * LAN9215, LAN9216, LAN9217, LAN9218
+ * LAN9210, LAN9211
+ * LAN9220, LAN9221
+ *
+ */
+
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/version.h>
+#include <linux/bug.h>
+#include <linux/bitops.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/phy.h>
+#include <linux/smsc911x.h>
+#include "smsc911x.h"
+
+#define SMSC_CHIPNAME "smsc911x"
+#define SMSC_MDIONAME "smsc911x-mdio"
+#define SMSC_DRV_VERSION "2008-10-21"
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION(SMSC_DRV_VERSION);
+
+#if USE_DEBUG > 0
+static int debug = 16;
+#else
+static int debug = 3;
+#endif
+
+module_param(debug, int, 0);
+MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)");
+
+struct smsc911x_data {
+ void __iomem *ioaddr;
+
+ unsigned int idrev;
+
+ /* used to decide which workarounds apply */
+ unsigned int generation;
+
+ /* device configuration (copied from platform_data during probe) */
+ struct smsc911x_platform_config config;
+
+ /* This needs to be acquired before calling any of below:
+ * smsc911x_mac_read(), smsc911x_mac_write()
+ */
+ spinlock_t mac_lock;
+
+ /* spinlock to ensure 16-bit accesses are serialised.
+ * unused with a 32-bit bus */
+ spinlock_t dev_lock;
+
+ struct phy_device *phy_dev;
+ struct mii_bus *mii_bus;
+ int phy_irq[PHY_MAX_ADDR];
+ unsigned int using_extphy;
+ int last_duplex;
+ int last_carrier;
+
+ u32 msg_enable;
+ unsigned int gpio_setting;
+ unsigned int gpio_orig_setting;
+ struct net_device *dev;
+ struct napi_struct napi;
+
+ unsigned int software_irq_signal;
+
+#ifdef USE_PHY_WORK_AROUND
+#define MIN_PACKET_SIZE (64)
+ char loopback_tx_pkt[MIN_PACKET_SIZE];
+ char loopback_rx_pkt[MIN_PACKET_SIZE];
+ unsigned int resetcount;
+#endif
+
+ /* Members for Multicast filter workaround */
+ unsigned int multicast_update_pending;
+ unsigned int set_bits_mask;
+ unsigned int clear_bits_mask;
+ unsigned int hashhi;
+ unsigned int hashlo;
+};
+
+/* The 16-bit access functions are significantly slower, due to the locking
+ * necessary. If your bus hardware can be configured to do this for you
+ * (in response to a single 32-bit operation from software), you should use
+ * the 32-bit access functions instead. */
+
+static inline u32 smsc911x_reg_read(struct smsc911x_data *pdata, u32 reg)
+{
+ if (pdata->config.flags & SMSC911X_USE_32BIT)
+ return readl(pdata->ioaddr + reg);
+
+ if (pdata->config.flags & SMSC911X_USE_16BIT) {
+ u32 data;
+ unsigned long flags;
+
+ /* these two 16-bit reads must be performed consecutively, so
+ * must not be interrupted by our own ISR (which would start
+ * another read operation) */
+ spin_lock_irqsave(&pdata->dev_lock, flags);
+ data = ((readw(pdata->ioaddr + reg) & 0xFFFF) |
+ ((readw(pdata->ioaddr + reg + 2) & 0xFFFF) << 16));
+ spin_unlock_irqrestore(&pdata->dev_lock, flags);
+
+ return data;
+ }
+
+ BUG();
+}
+
+static inline void smsc911x_reg_write(struct smsc911x_data *pdata, u32 reg,
+ u32 val)
+{
+ if (pdata->config.flags & SMSC911X_USE_32BIT) {
+ writel(val, pdata->ioaddr + reg);
+ return;
+ }
+
+ if (pdata->config.flags & SMSC911X_USE_16BIT) {
+ unsigned long flags;
+
+ /* these two 16-bit writes must be performed consecutively, so
+ * must not be interrupted by our own ISR (which would start
+ * another read operation) */
+ spin_lock_irqsave(&pdata->dev_lock, flags);
+ writew(val & 0xFFFF, pdata->ioaddr + reg);
+ writew((val >> 16) & 0xFFFF, pdata->ioaddr + reg + 2);
+ spin_unlock_irqrestore(&pdata->dev_lock, flags);
+ return;
+ }
+
+ BUG();
+}
+
+/* Writes a packet to the TX_DATA_FIFO */
+static inline void
+smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf,
+ unsigned int wordcount)
+{
+ if (pdata->config.flags & SMSC911X_USE_32BIT) {
+ writesl(pdata->ioaddr + TX_DATA_FIFO, buf, wordcount);
+ return;
+ }
+
+ if (pdata->config.flags & SMSC911X_USE_16BIT) {
+ while (wordcount--)
+ smsc911x_reg_write(pdata, TX_DATA_FIFO, *buf++);
+ return;
+ }
+
+ BUG();
+}
+
+/* Reads a packet out of the RX_DATA_FIFO */
+static inline void
+smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf,
+ unsigned int wordcount)
+{
+ if (pdata->config.flags & SMSC911X_USE_32BIT) {
+ readsl(pdata->ioaddr + RX_DATA_FIFO, buf, wordcount);
+ return;
+ }
+
+ if (pdata->config.flags & SMSC911X_USE_16BIT) {
+ while (wordcount--)
+ *buf++ = smsc911x_reg_read(pdata, RX_DATA_FIFO);
+ return;
+ }
+
+ BUG();
+}
+
+/* waits for MAC not busy, with timeout. Only called by smsc911x_mac_read
+ * and smsc911x_mac_write, so assumes mac_lock is held */
+static int smsc911x_mac_complete(struct smsc911x_data *pdata)
+{
+ int i;
+ u32 val;
+
+ SMSC_ASSERT_MAC_LOCK(pdata);
+
+ for (i = 0; i < 40; i++) {
+ val = smsc911x_reg_read(pdata, MAC_CSR_CMD);
+ if (!(val & MAC_CSR_CMD_CSR_BUSY_))
+ return 0;
+ }
+ SMSC_WARNING(HW, "Timed out waiting for MAC not BUSY. "
+ "MAC_CSR_CMD: 0x%08X", val);
+ return -EIO;
+}
+
+/* Fetches a MAC register value. Assumes mac_lock is acquired */
+static u32 smsc911x_mac_read(struct smsc911x_data *pdata, unsigned int offset)
+{
+ unsigned int temp;
+
+ SMSC_ASSERT_MAC_LOCK(pdata);
+
+ temp = smsc911x_reg_read(pdata, MAC_CSR_CMD);
+ if (unlikely(temp & MAC_CSR_CMD_CSR_BUSY_)) {
+ SMSC_WARNING(HW, "MAC busy at entry");
+ return 0xFFFFFFFF;
+ }
+
+ /* Send the MAC cmd */
+ smsc911x_reg_write(pdata, MAC_CSR_CMD, ((offset & 0xFF) |
+ MAC_CSR_CMD_CSR_BUSY_ | MAC_CSR_CMD_R_NOT_W_));
+
+ /* Workaround for hardware read-after-write restriction */
+ temp = smsc911x_reg_read(pdata, BYTE_TEST);
+
+ /* Wait for the read to complete */
+ if (likely(smsc911x_mac_complete(pdata) == 0))
+ return smsc911x_reg_read(pdata, MAC_CSR_DATA);
+
+ SMSC_WARNING(HW, "MAC busy after read");
+ return 0xFFFFFFFF;
+}
+
+/* Set a mac register, mac_lock must be acquired before calling */
+static void smsc911x_mac_write(struct smsc911x_data *pdata,
+ unsigned int offset, u32 val)
+{
+ unsigned int temp;
+
+ SMSC_ASSERT_MAC_LOCK(pdata);
+
+ temp = smsc911x_reg_read(pdata, MAC_CSR_CMD);
+ if (unlikely(temp & MAC_CSR_CMD_CSR_BUSY_)) {
+ SMSC_WARNING(HW,
+ "smsc911x_mac_write failed, MAC busy at entry");
+ return;
+ }
+
+ /* Send data to write */
+ smsc911x_reg_write(pdata, MAC_CSR_DATA, val);
+
+ /* Write the actual data */
+ smsc911x_reg_write(pdata, MAC_CSR_CMD, ((offset & 0xFF) |
+ MAC_CSR_CMD_CSR_BUSY_));
+
+ /* Workaround for hardware read-after-write restriction */
+ temp = smsc911x_reg_read(pdata, BYTE_TEST);
+
+ /* Wait for the write to complete */
+ if (likely(smsc911x_mac_complete(pdata) == 0))
+ return;
+
+ SMSC_WARNING(HW,
+ "smsc911x_mac_write failed, MAC busy after write");
+}
+
+/* Get a phy register */
+static int smsc911x_mii_read(struct mii_bus *bus, int phyaddr, int regidx)
+{
+ struct smsc911x_data *pdata = (struct smsc911x_data *)bus->priv;
+ unsigned long flags;
+ unsigned int addr;
+ int i, reg;
+
+ spin_lock_irqsave(&pdata->mac_lock, flags);
+
+ /* Confirm MII not busy */
+ if (unlikely(smsc911x_mac_read(pdata, MII_ACC) & MII_ACC_MII_BUSY_)) {
+ SMSC_WARNING(HW,
+ "MII is busy in smsc911x_mii_read???");
+ reg = -EIO;
+ goto out;
+ }
+
+ /* Set the address, index & direction (read from PHY) */
+ addr = ((phyaddr & 0x1F) << 11) | ((regidx & 0x1F) << 6);
+ smsc911x_mac_write(pdata, MII_ACC, addr);
+
+ /* Wait for read to complete w/ timeout */
+ for (i = 0; i < 100; i++)
+ if (!(smsc911x_mac_read(pdata, MII_ACC) & MII_ACC_MII_BUSY_)) {
+ reg = smsc911x_mac_read(pdata, MII_DATA);
+ goto out;
+ }
+
+ SMSC_WARNING(HW, "Timed out waiting for MII write to finish");
+ reg = -EIO;
+
+out:
+ spin_unlock_irqrestore(&pdata->mac_lock, flags);
+ return reg;
+}
+
+/* Set a phy register */
+static int smsc911x_mii_write(struct mii_bus *bus, int phyaddr, int regidx,
+ u16 val)
+{
+ struct smsc911x_data *pdata = (struct smsc911x_data *)bus->priv;
+ unsigned long flags;
+ unsigned int addr;
+ int i, reg;
+
+ spin_lock_irqsave(&pdata->mac_lock, flags);
+
+ /* Confirm MII not busy */
+ if (unlikely(smsc911x_mac_read(pdata, MII_ACC) & MII_ACC_MII_BUSY_)) {
+ SMSC_WARNING(HW,
+ "MII is busy in smsc911x_mii_write???");
+ reg = -EIO;
+ goto out;
+ }
+
+ /* Put the data to write in the MAC */
+ smsc911x_mac_write(pdata, MII_DATA, val);
+
+ /* Set the address, index & direction (write to PHY) */
+ addr = ((phyaddr & 0x1F) << 11) | ((regidx & 0x1F) << 6) |
+ MII_ACC_MII_WRITE_;
+ smsc911x_mac_write(pdata, MII_ACC, addr);
+
+ /* Wait for write to complete w/ timeout */
+ for (i = 0; i < 100; i++)
+ if (!(smsc911x_mac_read(pdata, MII_ACC) & MII_ACC_MII_BUSY_)) {
+ reg = 0;
+ goto out;
+ }
+
+ SMSC_WARNING(HW, "Timed out waiting for MII write to finish");
+ reg = -EIO;
+
+out:
+ spin_unlock_irqrestore(&pdata->mac_lock, flags);
+ return reg;
+}
+
+/* Autodetects and initialises external phy for SMSC9115 and SMSC9117 flavors.
+ * If something goes wrong, returns -ENODEV to revert back to internal phy.
+ * Performed at initialisation only, so interrupts are enabled */
+static int smsc911x_phy_initialise_external(struct smsc911x_data *pdata)
+{
+ unsigned int hwcfg = smsc911x_reg_read(pdata, HW_CFG);
+
+ /* External phy is requested, supported, and detected */
+ if (hwcfg & HW_CFG_EXT_PHY_DET_) {
+
+ /* Switch to external phy. Assuming tx and rx are stopped
+ * because smsc911x_phy_initialise is called before
+ * smsc911x_rx_initialise and tx_initialise. */
+
+ /* Disable phy clocks to the MAC */
+ hwcfg &= (~HW_CFG_PHY_CLK_SEL_);
+ hwcfg |= HW_CFG_PHY_CLK_SEL_CLK_DIS_;
+ smsc911x_reg_write(pdata, HW_CFG, hwcfg);
+ udelay(10); /* Enough time for clocks to stop */
+
+ /* Switch to external phy */
+ hwcfg |= HW_CFG_EXT_PHY_EN_;
+ smsc911x_reg_write(pdata, HW_CFG, hwcfg);
+
+ /* Enable phy clocks to the MAC */
+ hwcfg &= (~HW_CFG_PHY_CLK_SEL_);
+ hwcfg |= HW_CFG_PHY_CLK_SEL_EXT_PHY_;
+ smsc911x_reg_write(pdata, HW_CFG, hwcfg);
+ udelay(10); /* Enough time for clocks to restart */
+
+ hwcfg |= HW_CFG_SMI_SEL_;
+ smsc911x_reg_write(pdata, HW_CFG, hwcfg);
+
+ SMSC_TRACE(HW, "Successfully switched to external PHY");
+ pdata->using_extphy = 1;
+ } else {
+ SMSC_WARNING(HW, "No external PHY detected, "
+ "Using internal PHY instead.");
+ /* Use internal phy */
+ return -ENODEV;
+ }
+ return 0;
+}
+
+/* Fetches a tx status out of the status fifo */
+static unsigned int smsc911x_tx_get_txstatus(struct smsc911x_data *pdata)
+{
+ unsigned int result =
+ smsc911x_reg_read(pdata, TX_FIFO_INF) & TX_FIFO_INF_TSUSED_;
+
+ if (result != 0)
+ result = smsc911x_reg_read(pdata, TX_STATUS_FIFO);
+
+ return result;
+}
+
+/* Fetches the next rx status */
+static unsigned int smsc911x_rx_get_rxstatus(struct smsc911x_data *pdata)
+{
+ unsigned int result =
+ smsc911x_reg_read(pdata, RX_FIFO_INF) & RX_FIFO_INF_RXSUSED_;
+
+ if (result != 0)
+ result = smsc911x_reg_read(pdata, RX_STATUS_FIFO);
+
+ return result;
+}
+
+#ifdef USE_PHY_WORK_AROUND
+static int smsc911x_phy_check_loopbackpkt(struct smsc911x_data *pdata)
+{
+ unsigned int tries;
+ u32 wrsz;
+ u32 rdsz;
+ ulong bufp;
+
+ for (tries = 0; tries < 10; tries++) {
+ unsigned int txcmd_a;
+ unsigned int txcmd_b;
+ unsigned int status;
+ unsigned int pktlength;
+ unsigned int i;
+
+ /* Zero-out rx packet memory */
+ memset(pdata->loopback_rx_pkt, 0, MIN_PACKET_SIZE);
+
+ /* Write tx packet to 118 */
+ txcmd_a = (u32)((ulong)pdata->loopback_tx_pkt & 0x03) << 16;
+ txcmd_a |= TX_CMD_A_FIRST_SEG_ | TX_CMD_A_LAST_SEG_;
+ txcmd_a |= MIN_PACKET_SIZE;
+
+ txcmd_b = MIN_PACKET_SIZE << 16 | MIN_PACKET_SIZE;
+
+ smsc911x_reg_write(pdata, TX_DATA_FIFO, txcmd_a);
+ smsc911x_reg_write(pdata, TX_DATA_FIFO, txcmd_b);
+
+ bufp = (ulong)pdata->loopback_tx_pkt & (~0x3);
+ wrsz = MIN_PACKET_SIZE + 3;
+ wrsz += (u32)((ulong)pdata->loopback_tx_pkt & 0x3);
+ wrsz >>= 2;
+
+ smsc911x_tx_writefifo(pdata, (unsigned int *)bufp, wrsz);
+
+ /* Wait till transmit is done */
+ i = 60;
+ do {
+ udelay(5);
+ status = smsc911x_tx_get_txstatus(pdata);
+ } while ((i--) && (!status));
+
+ if (!status) {
+ SMSC_WARNING(HW, "Failed to transmit "
+ "during loopback test");
+ continue;
+ }
+ if (status & TX_STS_ES_) {
+ SMSC_WARNING(HW, "Transmit encountered "
+ "errors during loopback test");
+ continue;
+ }
+
+ /* Wait till receive is done */
+ i = 60;
+ do {
+ udelay(5);
+ status = smsc911x_rx_get_rxstatus(pdata);
+ } while ((i--) && (!status));
+
+ if (!status) {
+ SMSC_WARNING(HW,
+ "Failed to receive during loopback test");
+ continue;
+ }
+ if (status & RX_STS_ES_) {
+ SMSC_WARNING(HW, "Receive encountered "
+ "errors during loopback test");
+ continue;
+ }
+
+ pktlength = ((status & 0x3FFF0000UL) >> 16);
+ bufp = (ulong)pdata->loopback_rx_pkt;
+ rdsz = pktlength + 3;
+ rdsz += (u32)((ulong)pdata->loopback_rx_pkt & 0x3);
+ rdsz >>= 2;
+
+ smsc911x_rx_readfifo(pdata, (unsigned int *)bufp, rdsz);
+
+ if (pktlength != (MIN_PACKET_SIZE + 4)) {
+ SMSC_WARNING(HW, "Unexpected packet size "
+ "during loop back test, size=%d, will retry",
+ pktlength);
+ } else {
+ unsigned int j;
+ int mismatch = 0;
+ for (j = 0; j < MIN_PACKET_SIZE; j++) {
+ if (pdata->loopback_tx_pkt[j]
+ != pdata->loopback_rx_pkt[j]) {
+ mismatch = 1;
+ break;
+ }
+ }
+ if (!mismatch) {
+ SMSC_TRACE(HW, "Successfully verified "
+ "loopback packet");
+ return 0;
+ } else {
+ SMSC_WARNING(HW, "Data mismatch "
+ "during loop back test, will retry");
+ }
+ }
+ }
+
+ return -EIO;
+}
+
+static int smsc911x_phy_reset(struct smsc911x_data *pdata)
+{
+ struct phy_device *phy_dev = pdata->phy_dev;
+ unsigned int temp;
+ unsigned int i = 100000;
+
+ BUG_ON(!phy_dev);
+ BUG_ON(!phy_dev->bus);
+
+ SMSC_TRACE(HW, "Performing PHY BCR Reset");
+ smsc911x_mii_write(phy_dev->bus, phy_dev->addr, MII_BMCR, BMCR_RESET);
+ do {
+ msleep(1);
+ temp = smsc911x_mii_read(phy_dev->bus, phy_dev->addr,
+ MII_BMCR);
+ } while ((i--) && (temp & BMCR_RESET));
+
+ if (temp & BMCR_RESET) {
+ SMSC_WARNING(HW, "PHY reset failed to complete.");
+ return -EIO;
+ }
+ /* Extra delay required because the phy may not be completed with
+ * its reset when BMCR_RESET is cleared. Specs say 256 uS is
+ * enough delay but using 1ms here to be safe */
+ msleep(1);
+
+ return 0;
+}
+
+static int smsc911x_phy_loopbacktest(struct net_device *dev)
+{
+ struct smsc911x_data *pdata = netdev_priv(dev);
+ struct phy_device *phy_dev = pdata->phy_dev;
+ int result = -EIO;
+ unsigned int i, val;
+ unsigned long flags;
+
+ /* Initialise tx packet using broadcast destination address */
+ memset(pdata->loopback_tx_pkt, 0xff, ETH_ALEN);
+
+ /* Use incrementing source address */
+ for (i = 6; i < 12; i++)
+ pdata->loopback_tx_pkt[i] = (char)i;
+
+ /* Set length type field */
+ pdata->loopback_tx_pkt[12] = 0x00;
+ pdata->loopback_tx_pkt[13] = 0x00;
+
+ for (i = 14; i < MIN_PACKET_SIZE; i++)
+ pdata->loopback_tx_pkt[i] = (char)i;
+
+ val = smsc911x_reg_read(pdata, HW_CFG);
+ val &= HW_CFG_TX_FIF_SZ_;
+ val |= HW_CFG_SF_;
+ smsc911x_reg_write(pdata, HW_CFG, val);
+
+ smsc911x_reg_write(pdata, TX_CFG, TX_CFG_TX_ON_);
+ smsc911x_reg_write(pdata, RX_CFG,
+ (u32)((ulong)pdata->loopback_rx_pkt & 0x03) << 8);
+
+ for (i = 0; i < 10; i++) {
+ /* Set PHY to 10/FD, no ANEG, and loopback mode */
+ smsc911x_mii_write(phy_dev->bus, phy_dev->addr, MII_BMCR,
+ BMCR_LOOPBACK | BMCR_FULLDPLX);
+
+ /* Enable MAC tx/rx, FD */
+ spin_lock_irqsave(&pdata->mac_lock, flags);
+ smsc911x_mac_write(pdata, MAC_CR, MAC_CR_FDPX_
+ | MAC_CR_TXEN_ | MAC_CR_RXEN_);
+ spin_unlock_irqrestore(&pdata->mac_lock, flags);
+
+ if (smsc911x_phy_check_loopbackpkt(pdata) == 0) {
+ result = 0;
+ break;
+ }
+ pdata->resetcount++;
+
+ /* Disable MAC rx */
+ spin_lock_irqsave(&pdata->mac_lock, flags);
+ smsc911x_mac_write(pdata, MAC_CR, 0);
+ spin_unlock_irqrestore(&pdata->mac_lock, flags);
+
+ smsc911x_phy_reset(pdata);
+ }
+
+ /* Disable MAC */
+ spin_lock_irqsave(&pdata->mac_lock, flags);
+ smsc911x_mac_write(pdata, MAC_CR, 0);
+ spin_unlock_irqrestore(&pdata->mac_lock, flags);
+
+ /* Cancel PHY loopback mode */
+ smsc911x_mii_write(phy_dev->bus, phy_dev->addr, MII_BMCR, 0);
+
+ smsc911x_reg_write(pdata, TX_CFG, 0);
+ smsc911x_reg_write(pdata, RX_CFG, 0);
+
+ return result;
+}
+#endif /* USE_PHY_WORK_AROUND */
+
+static void smsc911x_phy_update_flowcontrol(struct smsc911x_data *pdata)
+{
+ struct phy_device *phy_dev = pdata->phy_dev;
+ u32 afc = smsc911x_reg_read(pdata, AFC_CFG);
+ u32 flow;
+ unsigned long flags;
+
+ if (phy_dev->duplex == DUPLEX_FULL) {
+ u16 lcladv = phy_read(phy_dev, MII_ADVERTISE);
+ u16 rmtadv = phy_read(phy_dev, MII_LPA);
+ u8 cap = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
+
+ if (cap & FLOW_CTRL_RX)
+ flow = 0xFFFF0002;
+ else
+ flow = 0;
+
+ if (cap & FLOW_CTRL_TX)
+ afc |= 0xF;
+ else
+ afc &= ~0xF;
+
+ SMSC_TRACE(HW, "rx pause %s, tx pause %s",
+ (cap & FLOW_CTRL_RX ? "enabled" : "disabled"),
+ (cap & FLOW_CTRL_TX ? "enabled" : "disabled"));
+ } else {
+ SMSC_TRACE(HW, "half duplex");
+ flow = 0;
+ afc |= 0xF;
+ }
+
+ spin_lock_irqsave(&pdata->mac_lock, flags);
+ smsc911x_mac_write(pdata, FLOW, flow);
+ spin_unlock_irqrestore(&pdata->mac_lock, flags);
+
+ smsc911x_reg_write(pdata, AFC_CFG, afc);
+}
+
+/* Update link mode if anything has changed. Called periodically when the
+ * PHY is in polling mode, even if nothing has changed. */
+static void smsc911x_phy_adjust_link(struct net_device *dev)
+{
+ struct smsc911x_data *pdata = netdev_priv(dev);
+ struct phy_device *phy_dev = pdata->phy_dev;
+ unsigned long flags;
+ int carrier;
+
+ if (phy_dev->duplex != pdata->last_duplex) {
+ unsigned int mac_cr;
+ SMSC_TRACE(HW, "duplex state has changed");
+
+ spin_lock_irqsave(&pdata->mac_lock, flags);
+ mac_cr = smsc911x_mac_read(pdata, MAC_CR);
+ if (phy_dev->duplex) {
+ SMSC_TRACE(HW,
+ "configuring for full duplex mode");
+ mac_cr |= MAC_CR_FDPX_;
+ } else {
+ SMSC_TRACE(HW,
+ "configuring for half duplex mode");
+ mac_cr &= ~MAC_CR_FDPX_;
+ }
+ smsc911x_mac_write(pdata, MAC_CR, mac_cr);
+ spin_unlock_irqrestore(&pdata->mac_lock, flags);
+
+ smsc911x_phy_update_flowcontrol(pdata);
+ pdata->last_duplex = phy_dev->duplex;
+ }
+
+ carrier = netif_carrier_ok(dev);
+ if (carrier != pdata->last_carrier) {
+ SMSC_TRACE(HW, "carrier state has changed");
+ if (carrier) {
+ SMSC_TRACE(HW, "configuring for carrier OK");
+ if ((pdata->gpio_orig_setting & GPIO_CFG_LED1_EN_) &&
+ (!pdata->using_extphy)) {
+ /* Restore orginal GPIO configuration */
+ pdata->gpio_setting = pdata->gpio_orig_setting;
+ smsc911x_reg_write(pdata, GPIO_CFG,
+ pdata->gpio_setting);
+ }
+ } else {
+ SMSC_TRACE(HW, "configuring for no carrier");
+ /* Check global setting that LED1
+ * usage is 10/100 indicator */
+ pdata->gpio_setting = smsc911x_reg_read(pdata,
+ GPIO_CFG);
+ if ((pdata->gpio_setting & GPIO_CFG_LED1_EN_)
+ && (!pdata->using_extphy)) {
+ /* Force 10/100 LED off, after saving
+ * orginal GPIO configuration */
+ pdata->gpio_orig_setting = pdata->gpio_setting;
+
+ pdata->gpio_setting &= ~GPIO_CFG_LED1_EN_;
+ pdata->gpio_setting |= (GPIO_CFG_GPIOBUF0_
+ | GPIO_CFG_GPIODIR0_
+ | GPIO_CFG_GPIOD0_);
+ smsc911x_reg_write(pdata, GPIO_CFG,
+ pdata->gpio_setting);
+ }
+ }
+ pdata->last_carrier = carrier;
+ }
+}
+
+static int smsc911x_mii_probe(struct net_device *dev)
+{
+ struct smsc911x_data *pdata = netdev_priv(dev);
+ struct phy_device *phydev = NULL;
+ int phy_addr;
+
+ /* find the first phy */
+ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+ if (pdata->mii_bus->phy_map[phy_addr]) {
+ phydev = pdata->mii_bus->phy_map[phy_addr];
+ SMSC_TRACE(PROBE, "PHY %d: addr %d, phy_id 0x%08X",
+ phy_addr, phydev->addr, phydev->phy_id);
+ break;
+ }
+ }
+
+ if (!phydev) {
+ pr_err("%s: no PHY found\n", dev->name);
+ return -ENODEV;
+ }
+
+ phydev = phy_connect(dev, phydev->dev.bus_id,
+ &smsc911x_phy_adjust_link, 0, pdata->config.phy_interface);
+
+ if (IS_ERR(phydev)) {
+ pr_err("%s: Could not attach to PHY\n", dev->name);
+ return PTR_ERR(phydev);
+ }
+
+ pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
+ dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq);
+
+ /* mask with MAC supported features */
+ phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
+ phydev->advertising = phydev->supported;
+
+ pdata->phy_dev = phydev;
+ pdata->last_duplex = -1;
+ pdata->last_carrier = -1;
+
+#ifdef USE_PHY_WORK_AROUND
+ if (smsc911x_phy_loopbacktest(dev) < 0) {
+ SMSC_WARNING(HW, "Failed Loop Back Test");
+ return -ENODEV;
+ }
+ SMSC_TRACE(HW, "Passed Loop Back Test");
+#endif /* USE_PHY_WORK_AROUND */
+
+ SMSC_TRACE(HW, "phy initialised succesfully");
+ return 0;
+}
+
+static int __devinit smsc911x_mii_init(struct platform_device *pdev,
+ struct net_device *dev)
+{
+ struct smsc911x_data *pdata = netdev_priv(dev);
+ int err = -ENXIO, i;
+
+ pdata->mii_bus = mdiobus_alloc();
+ if (!pdata->mii_bus) {
+ err = -ENOMEM;
+ goto err_out_1;
+ }
+
+ pdata->mii_bus->name = SMSC_MDIONAME;
+ snprintf(pdata->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+ pdata->mii_bus->priv = pdata;
+ pdata->mii_bus->read = smsc911x_mii_read;
+ pdata->mii_bus->write = smsc911x_mii_write;
+ pdata->mii_bus->irq = pdata->phy_irq;
+ for (i = 0; i < PHY_MAX_ADDR; ++i)
+ pdata->mii_bus->irq[i] = PHY_POLL;
+
+ pdata->mii_bus->parent = &pdev->dev;
+
+ pdata->using_extphy = 0;
+
+ switch (pdata->idrev & 0xFFFF0000) {
+ case 0x01170000:
+ case 0x01150000:
+ case 0x117A0000:
+ case 0x115A0000:
+ /* External PHY supported, try to autodetect */
+ if (smsc911x_phy_initialise_external(pdata) < 0) {
+ SMSC_TRACE(HW, "No external PHY detected, "
+ "using internal PHY");
+ }
+ break;
+ default:
+ SMSC_TRACE(HW, "External PHY is not supported, "
+ "using internal PHY");
+ break;
+ }
+
+ if (!pdata->using_extphy) {
+ /* Mask all PHYs except ID 1 (internal) */
+ pdata->mii_bus->phy_mask = ~(1 << 1);
+ }
+
+ if (mdiobus_register(pdata->mii_bus)) {
+ SMSC_WARNING(PROBE, "Error registering mii bus");
+ goto err_out_free_bus_2;
+ }
+
+ if (smsc911x_mii_probe(dev) < 0) {
+ SMSC_WARNING(PROBE, "Error registering mii bus");
+ goto err_out_unregister_bus_3;
+ }
+
+ return 0;
+
+err_out_unregister_bus_3:
+ mdiobus_unregister(pdata->mii_bus);
+err_out_free_bus_2:
+ mdiobus_free(pdata->mii_bus);
+err_out_1:
+ return err;
+}
+
+/* Gets the number of tx statuses in the fifo */
+static unsigned int smsc911x_tx_get_txstatcount(struct smsc911x_data *pdata)
+{
+ return (smsc911x_reg_read(pdata, TX_FIFO_INF)
+ & TX_FIFO_INF_TSUSED_) >> 16;
+}
+
+/* Reads tx statuses and increments counters where necessary */
+static void smsc911x_tx_update_txcounters(struct net_device *dev)
+{
+ struct smsc911x_data *pdata = netdev_priv(dev);
+ unsigned int tx_stat;
+
+ while ((tx_stat = smsc911x_tx_get_txstatus(pdata)) != 0) {
+ if (unlikely(tx_stat & 0x80000000)) {
+ /* In this driver the packet tag is used as the packet
+ * length. Since a packet length can never reach the
+ * size of 0x8000, this bit is reserved. It is worth
+ * noting that the "reserved bit" in the warning above
+ * does not reference a hardware defined reserved bit
+ * but rather a driver defined one.
+ */
+ SMSC_WARNING(HW,
+ "Packet tag reserved bit is high");
+ } else {
+ if (unlikely(tx_stat & 0x00008000)) {
+ dev->stats.tx_errors++;
+ } else {
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += (tx_stat >> 16);
+ }
+ if (unlikely(tx_stat & 0x00000100)) {
+ dev->stats.collisions += 16;
+ dev->stats.tx_aborted_errors += 1;
+ } else {
+ dev->stats.collisions +=
+ ((tx_stat >> 3) & 0xF);
+ }
+ if (unlikely(tx_stat & 0x00000800))
+ dev->stats.tx_carrier_errors += 1;
+ if (unlikely(tx_stat & 0x00000200)) {
+ dev->stats.collisions++;
+ dev->stats.tx_aborted_errors++;
+ }
+ }
+ }
+}
+
+/* Increments the Rx error counters */
+static void
+smsc911x_rx_counterrors(struct net_device *dev, unsigned int rxstat)
+{
+ int crc_err = 0;
+
+ if (unlikely(rxstat & 0x00008000)) {
+ dev->stats.rx_errors++;
+ if (unlikely(rxstat & 0x00000002)) {
+ dev->stats.rx_crc_errors++;
+ crc_err = 1;
+ }
+ }
+ if (likely(!crc_err)) {
+ if (unlikely((rxstat & 0x00001020) == 0x00001020)) {
+ /* Frame type indicates length,
+ * and length error is set */
+ dev->stats.rx_length_errors++;
+ }
+ if (rxstat & RX_STS_MCAST_)
+ dev->stats.multicast++;
+ }
+}
+
+/* Quickly dumps bad packets */
+static void
+smsc911x_rx_fastforward(struct smsc911x_data *pdata, unsigned int pktbytes)
+{
+ unsigned int pktwords = (pktbytes + NET_IP_ALIGN + 3) >> 2;
+
+ if (likely(pktwords >= 4)) {
+ unsigned int timeout = 500;
+ unsigned int val;
+ smsc911x_reg_write(pdata, RX_DP_CTRL, RX_DP_CTRL_RX_FFWD_);
+ do {
+ udelay(1);
+ val = smsc911x_reg_read(pdata, RX_DP_CTRL);
+ } while (timeout-- && (val & RX_DP_CTRL_RX_FFWD_));
+
+ if (unlikely(timeout == 0))
+ SMSC_WARNING(HW, "Timed out waiting for "
+ "RX FFWD to finish, RX_DP_CTRL: 0x%08X", val);
+ } else {
+ unsigned int temp;
+ while (pktwords--)
+ temp = smsc911x_reg_read(pdata, RX_DATA_FIFO);
+ }
+}
+
+/* NAPI poll function */
+static int smsc911x_poll(struct napi_struct *napi, int budget)
+{
+ struct smsc911x_data *pdata =
+ container_of(napi, struct smsc911x_data, napi);
+ struct net_device *dev = pdata->dev;
+ int npackets = 0;
+
+ while (likely(netif_running(dev)) && (npackets < budget)) {
+ unsigned int pktlength;
+ unsigned int pktwords;
+ struct sk_buff *skb;
+ unsigned int rxstat = smsc911x_rx_get_rxstatus(pdata);
+
+ if (!rxstat) {
+ unsigned int temp;
+ /* We processed all packets available. Tell NAPI it can
+ * stop polling then re-enable rx interrupts */
+ smsc911x_reg_write(pdata, INT_STS, INT_STS_RSFL_);
+ netif_rx_complete(napi);
+ temp = smsc911x_reg_read(pdata, INT_EN);
+ temp |= INT_EN_RSFL_EN_;
+ smsc911x_reg_write(pdata, INT_EN, temp);
+ break;
+ }
+
+ /* Count packet for NAPI scheduling, even if it has an error.
+ * Error packets still require cycles to discard */
+ npackets++;
+
+ pktlength = ((rxstat & 0x3FFF0000) >> 16);
+ pktwords = (pktlength + NET_IP_ALIGN + 3) >> 2;
+ smsc911x_rx_counterrors(dev, rxstat);
+
+ if (unlikely(rxstat & RX_STS_ES_)) {
+ SMSC_WARNING(RX_ERR,
+ "Discarding packet with error bit set");
+ /* Packet has an error, discard it and continue with
+ * the next */
+ smsc911x_rx_fastforward(pdata, pktwords);
+ dev->stats.rx_dropped++;
+ continue;
+ }
+
+ skb = netdev_alloc_skb(dev, pktlength + NET_IP_ALIGN);
+ if (unlikely(!skb)) {
+ SMSC_WARNING(RX_ERR,
+ "Unable to allocate skb for rx packet");
+ /* Drop the packet and stop this polling iteration */
+ smsc911x_rx_fastforward(pdata, pktwords);
+ dev->stats.rx_dropped++;
+ break;
+ }
+
+ skb->data = skb->head;
+ skb_reset_tail_pointer(skb);
+
+ /* Align IP on 16B boundary */
+ skb_reserve(skb, NET_IP_ALIGN);
+ skb_put(skb, pktlength - 4);
+ smsc911x_rx_readfifo(pdata, (unsigned int *)skb->head,
+ pktwords);
+ skb->protocol = eth_type_trans(skb, dev);
+ skb->ip_summed = CHECKSUM_NONE;
+ netif_receive_skb(skb);
+
+ /* Update counters */
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += (pktlength - 4);
+ dev->last_rx = jiffies;
+ }
+
+ /* Return total received packets */
+ return npackets;
+}
+
+/* Returns hash bit number for given MAC address
+ * Example:
+ * 01 00 5E 00 00 01 -> returns bit number 31 */
+static unsigned int smsc911x_hash(char addr[ETH_ALEN])
+{
+ return (ether_crc(ETH_ALEN, addr) >> 26) & 0x3f;
+}
+
+static void smsc911x_rx_multicast_update(struct smsc911x_data *pdata)
+{
+ /* Performs the multicast & mac_cr update. This is called when
+ * safe on the current hardware, and with the mac_lock held */
+ unsigned int mac_cr;
+
+ SMSC_ASSERT_MAC_LOCK(pdata);
+
+ mac_cr = smsc911x_mac_read(pdata, MAC_CR);
+ mac_cr |= pdata->set_bits_mask;
+ mac_cr &= ~(pdata->clear_bits_mask);
+ smsc911x_mac_write(pdata, MAC_CR, mac_cr);
+ smsc911x_mac_write(pdata, HASHH, pdata->hashhi);
+ smsc911x_mac_write(pdata, HASHL, pdata->hashlo);
+ SMSC_TRACE(HW, "maccr 0x%08X, HASHH 0x%08X, HASHL 0x%08X",
+ mac_cr, pdata->hashhi, pdata->hashlo);
+}
+
+static void smsc911x_rx_multicast_update_workaround(struct smsc911x_data *pdata)
+{
+ unsigned int mac_cr;
+
+ /* This function is only called for older LAN911x devices
+ * (revA or revB), where MAC_CR, HASHH and HASHL should not
+ * be modified during Rx - newer devices immediately update the
+ * registers.
+ *
+ * This is called from interrupt context */
+
+ spin_lock(&pdata->mac_lock);
+
+ /* Check Rx has stopped */
+ if (smsc911x_mac_read(pdata, MAC_CR) & MAC_CR_RXEN_)
+ SMSC_WARNING(DRV, "Rx not stopped");
+
+ /* Perform the update - safe to do now Rx has stopped */
+ smsc911x_rx_multicast_update(pdata);
+
+ /* Re-enable Rx */
+ mac_cr = smsc911x_mac_read(pdata, MAC_CR);
+ mac_cr |= MAC_CR_RXEN_;
+ smsc911x_mac_write(pdata, MAC_CR, mac_cr);
+
+ pdata->multicast_update_pending = 0;
+
+ spin_unlock(&pdata->mac_lock);
+}
+
+static int smsc911x_soft_reset(struct smsc911x_data *pdata)
+{
+ unsigned int timeout;
+ unsigned int temp;
+
+ /* Reset the LAN911x */
+ smsc911x_reg_write(pdata, HW_CFG, HW_CFG_SRST_);
+ timeout = 10;
+ do {
+ udelay(10);
+ temp = smsc911x_reg_read(pdata, HW_CFG);
+ } while ((--timeout) && (temp & HW_CFG_SRST_));
+
+ if (unlikely(temp & HW_CFG_SRST_)) {
+ SMSC_WARNING(DRV, "Failed to complete reset");
+ return -EIO;
+ }
+ return 0;
+}
+
+/* Sets the device MAC address to dev_addr, called with mac_lock held */
+static void
+smsc911x_set_mac_address(struct smsc911x_data *pdata, u8 dev_addr[6])
+{
+ u32 mac_high16 = (dev_addr[5] << 8) | dev_addr[4];
+ u32 mac_low32 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
+ (dev_addr[1] << 8) | dev_addr[0];
+
+ SMSC_ASSERT_MAC_LOCK(pdata);
+
+ smsc911x_mac_write(pdata, ADDRH, mac_high16);
+ smsc911x_mac_write(pdata, ADDRL, mac_low32);
+}
+
+static int smsc911x_open(struct net_device *dev)
+{
+ struct smsc911x_data *pdata = netdev_priv(dev);
+ unsigned int timeout;
+ unsigned int temp;
+ unsigned int intcfg;
+
+ /* if the phy is not yet registered, retry later*/
+ if (!pdata->phy_dev) {
+ SMSC_WARNING(HW, "phy_dev is NULL");
+ return -EAGAIN;
+ }
+
+ if (!is_valid_ether_addr(dev->dev_addr)) {
+ SMSC_WARNING(HW, "dev_addr is not a valid MAC address");
+ return -EADDRNOTAVAIL;
+ }
+
+ /* Reset the LAN911x */
+ if (smsc911x_soft_reset(pdata)) {
+ SMSC_WARNING(HW, "soft reset failed");
+ return -EIO;
+ }
+
+ smsc911x_reg_write(pdata, HW_CFG, 0x00050000);
+ smsc911x_reg_write(pdata, AFC_CFG, 0x006E3740);
+
+ /* Make sure EEPROM has finished loading before setting GPIO_CFG */
+ timeout = 50;
+ while ((timeout--) &&
+ (smsc911x_reg_read(pdata, E2P_CMD) & E2P_CMD_EPC_BUSY_)) {
+ udelay(10);
+ }
+
+ if (unlikely(timeout == 0))
+ SMSC_WARNING(IFUP,
+ "Timed out waiting for EEPROM busy bit to clear");
+
+ smsc911x_reg_write(pdata, GPIO_CFG, 0x70070000);
+
+ /* The soft reset above cleared the device's MAC address,
+ * restore it from local copy (set in probe) */
+ spin_lock_irq(&pdata->mac_lock);
+ smsc911x_set_mac_address(pdata, dev->dev_addr);
+ spin_unlock_irq(&pdata->mac_lock);
+
+ /* Initialise irqs, but leave all sources disabled */
+ smsc911x_reg_write(pdata, INT_EN, 0);
+ smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF);
+
+ /* Set interrupt deassertion to 100uS */
+ intcfg = ((10 << 24) | INT_CFG_IRQ_EN_);
+
+ if (pdata->config.irq_polarity) {
+ SMSC_TRACE(IFUP, "irq polarity: active high");
+ intcfg |= INT_CFG_IRQ_POL_;
+ } else {
+ SMSC_TRACE(IFUP, "irq polarity: active low");
+ }
+
+ if (pdata->config.irq_type) {
+ SMSC_TRACE(IFUP, "irq type: push-pull");
+ intcfg |= INT_CFG_IRQ_TYPE_;
+ } else {
+ SMSC_TRACE(IFUP, "irq type: open drain");
+ }
+
+ smsc911x_reg_write(pdata, INT_CFG, intcfg);
+
+ SMSC_TRACE(IFUP, "Testing irq handler using IRQ %d", dev->irq);
+ pdata->software_irq_signal = 0;
+ smp_wmb();
+
+ temp = smsc911x_reg_read(pdata, INT_EN);
+ temp |= INT_EN_SW_INT_EN_;
+ smsc911x_reg_write(pdata, INT_EN, temp);
+
+ timeout = 1000;
+ while (timeout--) {
+ if (pdata->software_irq_signal)
+ break;
+ msleep(1);
+ }
+
+ if (!pdata->software_irq_signal) {
+ dev_warn(&dev->dev, "ISR failed signaling test (IRQ %d)\n",
+ dev->irq);
+ return -ENODEV;
+ }
+ SMSC_TRACE(IFUP, "IRQ handler passed test using IRQ %d", dev->irq);
+
+ dev_info(&dev->dev, "SMSC911x/921x identified at %#08lx, IRQ: %d\n",
+ (unsigned long)pdata->ioaddr, dev->irq);
+
+ /* Bring the PHY up */
+ phy_start(pdata->phy_dev);
+
+ temp = smsc911x_reg_read(pdata, HW_CFG);
+ /* Preserve TX FIFO size and external PHY configuration */
+ temp &= (HW_CFG_TX_FIF_SZ_|0x00000FFF);
+ temp |= HW_CFG_SF_;
+ smsc911x_reg_write(pdata, HW_CFG, temp);
+
+ temp = smsc911x_reg_read(pdata, FIFO_INT);
+ temp |= FIFO_INT_TX_AVAIL_LEVEL_;
+ temp &= ~(FIFO_INT_RX_STS_LEVEL_);
+ smsc911x_reg_write(pdata, FIFO_INT, temp);
+
+ /* set RX Data offset to 2 bytes for alignment */
+ smsc911x_reg_write(pdata, RX_CFG, (2 << 8));
+
+ /* enable NAPI polling before enabling RX interrupts */
+ napi_enable(&pdata->napi);
+
+ temp = smsc911x_reg_read(pdata, INT_EN);
+ temp |= (INT_EN_TDFA_EN_ | INT_EN_RSFL_EN_);
+ smsc911x_reg_write(pdata, INT_EN, temp);
+
+ spin_lock_irq(&pdata->mac_lock);
+ temp = smsc911x_mac_read(pdata, MAC_CR);
+ temp |= (MAC_CR_TXEN_ | MAC_CR_RXEN_ | MAC_CR_HBDIS_);
+ smsc911x_mac_write(pdata, MAC_CR, temp);
+ spin_unlock_irq(&pdata->mac_lock);
+
+ smsc911x_reg_write(pdata, TX_CFG, TX_CFG_TX_ON_);
+
+ netif_start_queue(dev);
+ return 0;
+}
+
+/* Entry point for stopping the interface */
+static int smsc911x_stop(struct net_device *dev)
+{
+ struct smsc911x_data *pdata = netdev_priv(dev);
+ unsigned int temp;
+
+ /* Disable all device interrupts */
+ temp = smsc911x_reg_read(pdata, INT_CFG);
+ temp &= ~INT_CFG_IRQ_EN_;
+ smsc911x_reg_write(pdata, INT_CFG, temp);
+
+ /* Stop Tx and Rx polling */
+ netif_stop_queue(dev);
+ napi_disable(&pdata->napi);
+
+ /* At this point all Rx and Tx activity is stopped */
+ dev->stats.rx_dropped += smsc911x_reg_read(pdata, RX_DROP);
+ smsc911x_tx_update_txcounters(dev);
+
+ /* Bring the PHY down */
+ if (pdata->phy_dev)
+ phy_stop(pdata->phy_dev);
+
+ SMSC_TRACE(IFDOWN, "Interface stopped");
+ return 0;
+}
+
+/* Entry point for transmitting a packet */
+static int smsc911x_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct smsc911x_data *pdata = netdev_priv(dev);
+ unsigned int freespace;
+ unsigned int tx_cmd_a;
+ unsigned int tx_cmd_b;
+ unsigned int temp;
+ u32 wrsz;
+ ulong bufp;
+
+ freespace = smsc911x_reg_read(pdata, TX_FIFO_INF) & TX_FIFO_INF_TDFREE_;
+
+ if (unlikely(freespace < TX_FIFO_LOW_THRESHOLD))
+ SMSC_WARNING(TX_ERR,
+ "Tx data fifo low, space available: %d", freespace);
+
+ /* Word alignment adjustment */
+ tx_cmd_a = (u32)((ulong)skb->data & 0x03) << 16;
+ tx_cmd_a |= TX_CMD_A_FIRST_SEG_ | TX_CMD_A_LAST_SEG_;
+ tx_cmd_a |= (unsigned int)skb->len;
+
+ tx_cmd_b = ((unsigned int)skb->len) << 16;
+ tx_cmd_b |= (unsigned int)skb->len;
+
+ smsc911x_reg_write(pdata, TX_DATA_FIFO, tx_cmd_a);
+ smsc911x_reg_write(pdata, TX_DATA_FIFO, tx_cmd_b);
+
+ bufp = (ulong)skb->data & (~0x3);
+ wrsz = (u32)skb->len + 3;
+ wrsz += (u32)((ulong)skb->data & 0x3);
+ wrsz >>= 2;
+
+ smsc911x_tx_writefifo(pdata, (unsigned int *)bufp, wrsz);
+ freespace -= (skb->len + 32);
+ dev_kfree_skb(skb);
+ dev->trans_start = jiffies;
+
+ if (unlikely(smsc911x_tx_get_txstatcount(pdata) >= 30))
+ smsc911x_tx_update_txcounters(dev);
+
+ if (freespace < TX_FIFO_LOW_THRESHOLD) {
+ netif_stop_queue(dev);
+ temp = smsc911x_reg_read(pdata, FIFO_INT);
+ temp &= 0x00FFFFFF;
+ temp |= 0x32000000;
+ smsc911x_reg_write(pdata, FIFO_INT, temp);
+ }
+
+ return NETDEV_TX_OK;
+}
+
+/* Entry point for getting status counters */
+static struct net_device_stats *smsc911x_get_stats(struct net_device *dev)
+{
+ struct smsc911x_data *pdata = netdev_priv(dev);
+ smsc911x_tx_update_txcounters(dev);
+ dev->stats.rx_dropped += smsc911x_reg_read(pdata, RX_DROP);
+ return &dev->stats;
+}
+
+/* Entry point for setting addressing modes */
+static void smsc911x_set_multicast_list(struct net_device *dev)
+{
+ struct smsc911x_data *pdata = netdev_priv(dev);
+ unsigned long flags;
+
+ if (dev->flags & IFF_PROMISC) {
+ /* Enabling promiscuous mode */
+ pdata->set_bits_mask = MAC_CR_PRMS_;
+ pdata->clear_bits_mask = (MAC_CR_MCPAS_ | MAC_CR_HPFILT_);
+ pdata->hashhi = 0;
+ pdata->hashlo = 0;
+ } else if (dev->flags & IFF_ALLMULTI) {
+ /* Enabling all multicast mode */
+ pdata->set_bits_mask = MAC_CR_MCPAS_;
+ pdata->clear_bits_mask = (MAC_CR_PRMS_ | MAC_CR_HPFILT_);
+ pdata->hashhi = 0;
+ pdata->hashlo = 0;
+ } else if (dev->mc_count > 0) {
+ /* Enabling specific multicast addresses */
+ unsigned int hash_high = 0;
+ unsigned int hash_low = 0;
+ unsigned int count = 0;
+ struct dev_mc_list *mc_list = dev->mc_list;
+
+ pdata->set_bits_mask = MAC_CR_HPFILT_;
+ pdata->clear_bits_mask = (MAC_CR_PRMS_ | MAC_CR_MCPAS_);
+
+ while (mc_list) {
+ count++;
+ if ((mc_list->dmi_addrlen) == ETH_ALEN) {
+ unsigned int bitnum =
+ smsc911x_hash(mc_list->dmi_addr);
+ unsigned int mask = 0x01 << (bitnum & 0x1F);
+ if (bitnum & 0x20)
+ hash_high |= mask;
+ else
+ hash_low |= mask;
+ } else {
+ SMSC_WARNING(DRV, "dmi_addrlen != 6");
+ }
+ mc_list = mc_list->next;
+ }
+ if (count != (unsigned int)dev->mc_count)
+ SMSC_WARNING(DRV, "mc_count != dev->mc_count");
+
+ pdata->hashhi = hash_high;
+ pdata->hashlo = hash_low;
+ } else {
+ /* Enabling local MAC address only */
+ pdata->set_bits_mask = 0;
+ pdata->clear_bits_mask =
+ (MAC_CR_PRMS_ | MAC_CR_MCPAS_ | MAC_CR_HPFILT_);
+ pdata->hashhi = 0;
+ pdata->hashlo = 0;
+ }
+
+ spin_lock_irqsave(&pdata->mac_lock, flags);
+
+ if (pdata->generation <= 1) {
+ /* Older hardware revision - cannot change these flags while
+ * receiving data */
+ if (!pdata->multicast_update_pending) {
+ unsigned int temp;
+ SMSC_TRACE(HW, "scheduling mcast update");
+ pdata->multicast_update_pending = 1;
+
+ /* Request the hardware to stop, then perform the
+ * update when we get an RX_STOP interrupt */
+ smsc911x_reg_write(pdata, INT_STS, INT_STS_RXSTOP_INT_);
+ temp = smsc911x_reg_read(pdata, INT_EN);
+ temp |= INT_EN_RXSTOP_INT_EN_;
+ smsc911x_reg_write(pdata, INT_EN, temp);
+
+ temp = smsc911x_mac_read(pdata, MAC_CR);
+ temp &= ~(MAC_CR_RXEN_);
+ smsc911x_mac_write(pdata, MAC_CR, temp);
+ } else {
+ /* There is another update pending, this should now
+ * use the newer values */
+ }
+ } else {
+ /* Newer hardware revision - can write immediately */
+ smsc911x_rx_multicast_update(pdata);
+ }
+
+ spin_unlock_irqrestore(&pdata->mac_lock, flags);
+}
+
+static irqreturn_t smsc911x_irqhandler(int irq, void *dev_id)
+{
+ struct net_device *dev = dev_id;
+ struct smsc911x_data *pdata = netdev_priv(dev);
+ u32 intsts = smsc911x_reg_read(pdata, INT_STS);
+ u32 inten = smsc911x_reg_read(pdata, INT_EN);
+ int serviced = IRQ_NONE;
+ u32 temp;
+
+ if (unlikely(intsts & inten & INT_STS_SW_INT_)) {
+ temp = smsc911x_reg_read(pdata, INT_EN);
+ temp &= (~INT_EN_SW_INT_EN_);
+ smsc911x_reg_write(pdata, INT_EN, temp);
+ smsc911x_reg_write(pdata, INT_STS, INT_STS_SW_INT_);
+ pdata->software_irq_signal = 1;
+ smp_wmb();
+ serviced = IRQ_HANDLED;
+ }
+
+ if (unlikely(intsts & inten & INT_STS_RXSTOP_INT_)) {
+ /* Called when there is a multicast update scheduled and
+ * it is now safe to complete the update */
+ SMSC_TRACE(INTR, "RX Stop interrupt");
+ temp = smsc911x_reg_read(pdata, INT_EN);
+ temp &= (~INT_EN_RXSTOP_INT_EN_);
+ smsc911x_reg_write(pdata, INT_EN, temp);
+ smsc911x_reg_write(pdata, INT_STS, INT_STS_RXSTOP_INT_);
+ smsc911x_rx_multicast_update_workaround(pdata);
+ serviced = IRQ_HANDLED;
+ }
+
+ if (intsts & inten & INT_STS_TDFA_) {
+ temp = smsc911x_reg_read(pdata, FIFO_INT);
+ temp |= FIFO_INT_TX_AVAIL_LEVEL_;
+ smsc911x_reg_write(pdata, FIFO_INT, temp);
+ smsc911x_reg_write(pdata, INT_STS, INT_STS_TDFA_);
+ netif_wake_queue(dev);
+ serviced = IRQ_HANDLED;
+ }
+
+ if (unlikely(intsts & inten & INT_STS_RXE_)) {
+ SMSC_TRACE(INTR, "RX Error interrupt");
+ smsc911x_reg_write(pdata, INT_STS, INT_STS_RXE_);
+ serviced = IRQ_HANDLED;
+ }
+
+ if (likely(intsts & inten & INT_STS_RSFL_)) {
+ if (likely(netif_rx_schedule_prep(dev, &pdata->napi))) {
+ /* Disable Rx interrupts */
+ temp = smsc911x_reg_read(pdata, INT_EN);
+ temp &= (~INT_EN_RSFL_EN_);
+ smsc911x_reg_write(pdata, INT_EN, temp);
+ /* Schedule a NAPI poll */
+ __netif_rx_schedule(dev, &pdata->napi);
+ } else {
+ SMSC_WARNING(RX_ERR,
+ "netif_rx_schedule_prep failed");
+ }
+ serviced = IRQ_HANDLED;
+ }
+
+ return serviced;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void smsc911x_poll_controller(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ smsc911x_irqhandler(0, dev);
+ enable_irq(dev->irq);
+}
+#endif /* CONFIG_NET_POLL_CONTROLLER */
+
+/* Standard ioctls for mii-tool */
+static int smsc911x_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct smsc911x_data *pdata = netdev_priv(dev);
+
+ if (!netif_running(dev) || !pdata->phy_dev)
+ return -EINVAL;
+
+ return phy_mii_ioctl(pdata->phy_dev, if_mii(ifr), cmd);
+}
+
+static int
+smsc911x_ethtool_getsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct smsc911x_data *pdata = netdev_priv(dev);
+
+ cmd->maxtxpkt = 1;
+ cmd->maxrxpkt = 1;
+ return phy_ethtool_gset(pdata->phy_dev, cmd);
+}
+
+static int
+smsc911x_ethtool_setsettings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct smsc911x_data *pdata = netdev_priv(dev);
+
+ return phy_ethtool_sset(pdata->phy_dev, cmd);
+}
+
+static void smsc911x_ethtool_getdrvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *info)
+{
+ strlcpy(info->driver, SMSC_CHIPNAME, sizeof(info->driver));
+ strlcpy(info->version, SMSC_DRV_VERSION, sizeof(info->version));
+ strlcpy(info->bus_info, dev->dev.parent->bus_id,
+ sizeof(info->bus_info));
+}
+
+static int smsc911x_ethtool_nwayreset(struct net_device *dev)
+{
+ struct smsc911x_data *pdata = netdev_priv(dev);
+
+ return phy_start_aneg(pdata->phy_dev);
+}
+
+static u32 smsc911x_ethtool_getmsglevel(struct net_device *dev)
+{
+ struct smsc911x_data *pdata = netdev_priv(dev);
+ return pdata->msg_enable;
+}
+
+static void smsc911x_ethtool_setmsglevel(struct net_device *dev, u32 level)
+{
+ struct smsc911x_data *pdata = netdev_priv(dev);
+ pdata->msg_enable = level;
+}
+
+static int smsc911x_ethtool_getregslen(struct net_device *dev)
+{
+ return (((E2P_DATA - ID_REV) / 4 + 1) + (WUCSR - MAC_CR) + 1 + 32) *
+ sizeof(u32);
+}
+
+static void
+smsc911x_ethtool_getregs(struct net_device *dev, struct ethtool_regs *regs,
+ void *buf)
+{
+ struct smsc911x_data *pdata = netdev_priv(dev);
+ struct phy_device *phy_dev = pdata->phy_dev;
+ unsigned long flags;
+ unsigned int i;
+ unsigned int j = 0;
+ u32 *data = buf;
+
+ regs->version = pdata->idrev;
+ for (i = ID_REV; i <= E2P_DATA; i += (sizeof(u32)))
+ data[j++] = smsc911x_reg_read(pdata, i);
+
+ for (i = MAC_CR; i <= WUCSR; i++) {
+ spin_lock_irqsave(&pdata->mac_lock, flags);
+ data[j++] = smsc911x_mac_read(pdata, i);
+ spin_unlock_irqrestore(&pdata->mac_lock, flags);
+ }
+
+ for (i = 0; i <= 31; i++)
+ data[j++] = smsc911x_mii_read(phy_dev->bus, phy_dev->addr, i);
+}
+
+static void smsc911x_eeprom_enable_access(struct smsc911x_data *pdata)
+{
+ unsigned int temp = smsc911x_reg_read(pdata, GPIO_CFG);
+ temp &= ~GPIO_CFG_EEPR_EN_;
+ smsc911x_reg_write(pdata, GPIO_CFG, temp);
+ msleep(1);
+}
+
+static int smsc911x_eeprom_send_cmd(struct smsc911x_data *pdata, u32 op)
+{
+ int timeout = 100;
+ u32 e2cmd;
+
+ SMSC_TRACE(DRV, "op 0x%08x", op);
+ if (smsc911x_reg_read(pdata, E2P_CMD) & E2P_CMD_EPC_BUSY_) {
+ SMSC_WARNING(DRV, "Busy at start");
+ return -EBUSY;
+ }
+
+ e2cmd = op | E2P_CMD_EPC_BUSY_;
+ smsc911x_reg_write(pdata, E2P_CMD, e2cmd);
+
+ do {
+ msleep(1);
+ e2cmd = smsc911x_reg_read(pdata, E2P_CMD);
+ } while ((e2cmd & E2P_CMD_EPC_BUSY_) && (timeout--));
+
+ if (!timeout) {
+ SMSC_TRACE(DRV, "TIMED OUT");
+ return -EAGAIN;
+ }
+
+ if (e2cmd & E2P_CMD_EPC_TIMEOUT_) {
+ SMSC_TRACE(DRV, "Error occured during eeprom operation");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int smsc911x_eeprom_read_location(struct smsc911x_data *pdata,
+ u8 address, u8 *data)
+{
+ u32 op = E2P_CMD_EPC_CMD_READ_ | address;
+ int ret;
+
+ SMSC_TRACE(DRV, "address 0x%x", address);
+ ret = smsc911x_eeprom_send_cmd(pdata, op);
+
+ if (!ret)
+ data[address] = smsc911x_reg_read(pdata, E2P_DATA);
+
+ return ret;
+}
+
+static int smsc911x_eeprom_write_location(struct smsc911x_data *pdata,
+ u8 address, u8 data)
+{
+ u32 op = E2P_CMD_EPC_CMD_ERASE_ | address;
+ int ret;
+
+ SMSC_TRACE(DRV, "address 0x%x, data 0x%x", address, data);
+ ret = smsc911x_eeprom_send_cmd(pdata, op);
+
+ if (!ret) {
+ op = E2P_CMD_EPC_CMD_WRITE_ | address;
+ smsc911x_reg_write(pdata, E2P_DATA, (u32)data);
+ ret = smsc911x_eeprom_send_cmd(pdata, op);
+ }
+
+ return ret;
+}
+
+static int smsc911x_ethtool_get_eeprom_len(struct net_device *dev)
+{
+ return SMSC911X_EEPROM_SIZE;
+}
+
+static int smsc911x_ethtool_get_eeprom(struct net_device *dev,
+ struct ethtool_eeprom *eeprom, u8 *data)
+{
+ struct smsc911x_data *pdata = netdev_priv(dev);
+ u8 eeprom_data[SMSC911X_EEPROM_SIZE];
+ int len;
+ int i;
+
+ smsc911x_eeprom_enable_access(pdata);
+
+ len = min(eeprom->len, SMSC911X_EEPROM_SIZE);
+ for (i = 0; i < len; i++) {
+ int ret = smsc911x_eeprom_read_location(pdata, i, eeprom_data);
+ if (ret < 0) {
+ eeprom->len = 0;
+ return ret;
+ }
+ }
+
+ memcpy(data, &eeprom_data[eeprom->offset], len);
+ eeprom->len = len;
+ return 0;
+}
+
+static int smsc911x_ethtool_set_eeprom(struct net_device *dev,
+ struct ethtool_eeprom *eeprom, u8 *data)
+{
+ int ret;
+ struct smsc911x_data *pdata = netdev_priv(dev);
+
+ smsc911x_eeprom_enable_access(pdata);
+ smsc911x_eeprom_send_cmd(pdata, E2P_CMD_EPC_CMD_EWEN_);
+ ret = smsc911x_eeprom_write_location(pdata, eeprom->offset, *data);
+ smsc911x_eeprom_send_cmd(pdata, E2P_CMD_EPC_CMD_EWDS_);
+
+ /* Single byte write, according to man page */
+ eeprom->len = 1;
+
+ return ret;
+}
+
+static const struct ethtool_ops smsc911x_ethtool_ops = {
+ .get_settings = smsc911x_ethtool_getsettings,
+ .set_settings = smsc911x_ethtool_setsettings,
+ .get_link = ethtool_op_get_link,
+ .get_drvinfo = smsc911x_ethtool_getdrvinfo,
+ .nway_reset = smsc911x_ethtool_nwayreset,
+ .get_msglevel = smsc911x_ethtool_getmsglevel,
+ .set_msglevel = smsc911x_ethtool_setmsglevel,
+ .get_regs_len = smsc911x_ethtool_getregslen,
+ .get_regs = smsc911x_ethtool_getregs,
+ .get_eeprom_len = smsc911x_ethtool_get_eeprom_len,
+ .get_eeprom = smsc911x_ethtool_get_eeprom,
+ .set_eeprom = smsc911x_ethtool_set_eeprom,
+};
+
+static const struct net_device_ops smsc911x_netdev_ops = {
+ .ndo_open = smsc911x_open,
+ .ndo_stop = smsc911x_stop,
+ .ndo_start_xmit = smsc911x_hard_start_xmit,
+ .ndo_get_stats = smsc911x_get_stats,
+ .ndo_set_multicast_list = smsc911x_set_multicast_list,
+ .ndo_do_ioctl = smsc911x_do_ioctl,
+ .ndo_validate_addr = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = smsc911x_poll_controller,
+#endif
+};
+
+/* Initializing private device structures, only called from probe */
+static int __devinit smsc911x_init(struct net_device *dev)
+{
+ struct smsc911x_data *pdata = netdev_priv(dev);
+ unsigned int byte_test;
+
+ SMSC_TRACE(PROBE, "Driver Parameters:");
+ SMSC_TRACE(PROBE, "LAN base: 0x%08lX",
+ (unsigned long)pdata->ioaddr);
+ SMSC_TRACE(PROBE, "IRQ: %d", dev->irq);
+ SMSC_TRACE(PROBE, "PHY will be autodetected.");
+
+ spin_lock_init(&pdata->dev_lock);
+
+ if (pdata->ioaddr == 0) {
+ SMSC_WARNING(PROBE, "pdata->ioaddr: 0x00000000");
+ return -ENODEV;
+ }
+
+ /* Check byte ordering */
+ byte_test = smsc911x_reg_read(pdata, BYTE_TEST);
+ SMSC_TRACE(PROBE, "BYTE_TEST: 0x%08X", byte_test);
+ if (byte_test == 0x43218765) {
+ SMSC_TRACE(PROBE, "BYTE_TEST looks swapped, "
+ "applying WORD_SWAP");
+ smsc911x_reg_write(pdata, WORD_SWAP, 0xffffffff);
+
+ /* 1 dummy read of BYTE_TEST is needed after a write to
+ * WORD_SWAP before its contents are valid */
+ byte_test = smsc911x_reg_read(pdata, BYTE_TEST);
+
+ byte_test = smsc911x_reg_read(pdata, BYTE_TEST);
+ }
+
+ if (byte_test != 0x87654321) {
+ SMSC_WARNING(DRV, "BYTE_TEST: 0x%08X", byte_test);
+ if (((byte_test >> 16) & 0xFFFF) == (byte_test & 0xFFFF)) {
+ SMSC_WARNING(PROBE,
+ "top 16 bits equal to bottom 16 bits");
+ SMSC_TRACE(PROBE, "This may mean the chip is set "
+ "for 32 bit while the bus is reading 16 bit");
+ }
+ return -ENODEV;
+ }
+
+ /* Default generation to zero (all workarounds apply) */
+ pdata->generation = 0;
+
+ pdata->idrev = smsc911x_reg_read(pdata, ID_REV);
+ switch (pdata->idrev & 0xFFFF0000) {
+ case 0x01180000:
+ case 0x01170000:
+ case 0x01160000:
+ case 0x01150000:
+ /* LAN911[5678] family */
+ pdata->generation = pdata->idrev & 0x0000FFFF;
+ break;
+
+ case 0x118A0000:
+ case 0x117A0000:
+ case 0x116A0000:
+ case 0x115A0000:
+ /* LAN921[5678] family */
+ pdata->generation = 3;
+ break;
+
+ case 0x92100000:
+ case 0x92110000:
+ case 0x92200000:
+ case 0x92210000:
+ /* LAN9210/LAN9211/LAN9220/LAN9221 */
+ pdata->generation = 4;
+ break;
+
+ default:
+ SMSC_WARNING(PROBE, "LAN911x not identified, idrev: 0x%08X",
+ pdata->idrev);
+ return -ENODEV;
+ }
+
+ SMSC_TRACE(PROBE, "LAN911x identified, idrev: 0x%08X, generation: %d",
+ pdata->idrev, pdata->generation);
+
+ if (pdata->generation == 0)
+ SMSC_WARNING(PROBE,
+ "This driver is not intended for this chip revision");
+
+ /* Reset the LAN911x */
+ if (smsc911x_soft_reset(pdata))
+ return -ENODEV;
+
+ /* Disable all interrupt sources until we bring the device up */
+ smsc911x_reg_write(pdata, INT_EN, 0);
+
+ ether_setup(dev);
+ dev->flags |= IFF_MULTICAST;
+ netif_napi_add(dev, &pdata->napi, smsc911x_poll, SMSC_NAPI_WEIGHT);
+ dev->netdev_ops = &smsc911x_netdev_ops;
+ dev->ethtool_ops = &smsc911x_ethtool_ops;
+
+ return 0;
+}
+
+static int __devexit smsc911x_drv_remove(struct platform_device *pdev)
+{
+ struct net_device *dev;
+ struct smsc911x_data *pdata;
+ struct resource *res;
+
+ dev = platform_get_drvdata(pdev);
+ BUG_ON(!dev);
+ pdata = netdev_priv(dev);
+ BUG_ON(!pdata);
+ BUG_ON(!pdata->ioaddr);
+ BUG_ON(!pdata->phy_dev);
+
+ SMSC_TRACE(IFDOWN, "Stopping driver.");
+
+ phy_disconnect(pdata->phy_dev);
+ pdata->phy_dev = NULL;
+ mdiobus_unregister(pdata->mii_bus);
+ mdiobus_free(pdata->mii_bus);
+
+ platform_set_drvdata(pdev, NULL);
+ unregister_netdev(dev);
+ free_irq(dev->irq, dev);
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "smsc911x-memory");
+ if (!res)
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ release_mem_region(res->start, res->end - res->start);
+
+ iounmap(pdata->ioaddr);
+
+ free_netdev(dev);
+
+ return 0;
+}
+
+static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
+{
+ struct net_device *dev;
+ struct smsc911x_data *pdata;
+ struct smsc911x_platform_config *config = pdev->dev.platform_data;
+ struct resource *res;
+ unsigned int intcfg = 0;
+ int res_size;
+ int retval;
+ DECLARE_MAC_BUF(mac);
+
+ pr_info("%s: Driver version %s.\n", SMSC_CHIPNAME, SMSC_DRV_VERSION);
+
+ /* platform data specifies irq & dynamic bus configuration */
+ if (!pdev->dev.platform_data) {
+ pr_warning("%s: platform_data not provided\n", SMSC_CHIPNAME);
+ retval = -ENODEV;
+ goto out_0;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "smsc911x-memory");
+ if (!res)
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ pr_warning("%s: Could not allocate resource.\n",
+ SMSC_CHIPNAME);
+ retval = -ENODEV;
+ goto out_0;
+ }
+ res_size = res->end - res->start;
+
+ if (!request_mem_region(res->start, res_size, SMSC_CHIPNAME)) {
+ retval = -EBUSY;
+ goto out_0;
+ }
+
+ dev = alloc_etherdev(sizeof(struct smsc911x_data));
+ if (!dev) {
+ pr_warning("%s: Could not allocate device.\n", SMSC_CHIPNAME);
+ retval = -ENOMEM;
+ goto out_release_io_1;
+ }
+
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ pdata = netdev_priv(dev);
+
+ dev->irq = platform_get_irq(pdev, 0);
+ pdata->ioaddr = ioremap_nocache(res->start, res_size);
+
+ /* copy config parameters across to pdata */
+ memcpy(&pdata->config, config, sizeof(pdata->config));
+
+ pdata->dev = dev;
+ pdata->msg_enable = ((1 << debug) - 1);
+
+ if (pdata->ioaddr == NULL) {
+ SMSC_WARNING(PROBE,
+ "Error smsc911x base address invalid");
+ retval = -ENOMEM;
+ goto out_free_netdev_2;
+ }
+
+ retval = smsc911x_init(dev);
+ if (retval < 0)
+ goto out_unmap_io_3;
+
+ /* configure irq polarity and type before connecting isr */
+ if (pdata->config.irq_polarity == SMSC911X_IRQ_POLARITY_ACTIVE_HIGH)
+ intcfg |= INT_CFG_IRQ_POL_;
+
+ if (pdata->config.irq_type == SMSC911X_IRQ_TYPE_PUSH_PULL)
+ intcfg |= INT_CFG_IRQ_TYPE_;
+
+ smsc911x_reg_write(pdata, INT_CFG, intcfg);
+
+ /* Ensure interrupts are globally disabled before connecting ISR */
+ smsc911x_reg_write(pdata, INT_EN, 0);
+ smsc911x_reg_write(pdata, INT_STS, 0xFFFFFFFF);
+
+ retval = request_irq(dev->irq, smsc911x_irqhandler, IRQF_DISABLED,
+ SMSC_CHIPNAME, dev);
+ if (retval) {
+ SMSC_WARNING(PROBE,
+ "Unable to claim requested irq: %d", dev->irq);
+ goto out_unmap_io_3;
+ }
+
+ platform_set_drvdata(pdev, dev);
+
+ retval = register_netdev(dev);
+ if (retval) {
+ SMSC_WARNING(PROBE,
+ "Error %i registering device", retval);
+ goto out_unset_drvdata_4;
+ } else {
+ SMSC_TRACE(PROBE, "Network interface: \"%s\"", dev->name);
+ }
+
+ spin_lock_init(&pdata->mac_lock);
+
+ retval = smsc911x_mii_init(pdev, dev);
+ if (retval) {
+ SMSC_WARNING(PROBE,
+ "Error %i initialising mii", retval);
+ goto out_unregister_netdev_5;
+ }
+
+ spin_lock_irq(&pdata->mac_lock);
+
+ /* Check if mac address has been specified when bringing interface up */
+ if (is_valid_ether_addr(dev->dev_addr)) {
+ smsc911x_set_mac_address(pdata, dev->dev_addr);
+ SMSC_TRACE(PROBE, "MAC Address is specified by configuration");
+ } else {
+ /* Try reading mac address from device. if EEPROM is present
+ * it will already have been set */
+ u32 mac_high16 = smsc911x_mac_read(pdata, ADDRH);
+ u32 mac_low32 = smsc911x_mac_read(pdata, ADDRL);
+ dev->dev_addr[0] = (u8)(mac_low32);
+ dev->dev_addr[1] = (u8)(mac_low32 >> 8);
+ dev->dev_addr[2] = (u8)(mac_low32 >> 16);
+ dev->dev_addr[3] = (u8)(mac_low32 >> 24);
+ dev->dev_addr[4] = (u8)(mac_high16);
+ dev->dev_addr[5] = (u8)(mac_high16 >> 8);
+
+ if (is_valid_ether_addr(dev->dev_addr)) {
+ /* eeprom values are valid so use them */
+ SMSC_TRACE(PROBE,
+ "Mac Address is read from LAN911x EEPROM");
+ } else {
+ /* eeprom values are invalid, generate random MAC */
+ random_ether_addr(dev->dev_addr);
+ smsc911x_set_mac_address(pdata, dev->dev_addr);
+ SMSC_TRACE(PROBE,
+ "MAC Address is set to random_ether_addr");
+ }
+ }
+
+ spin_unlock_irq(&pdata->mac_lock);
+
+ dev_info(&dev->dev, "MAC Address: %s\n",
+ print_mac(mac, dev->dev_addr));
+
+ return 0;
+
+out_unregister_netdev_5:
+ unregister_netdev(dev);
+out_unset_drvdata_4:
+ platform_set_drvdata(pdev, NULL);
+ free_irq(dev->irq, dev);
+out_unmap_io_3:
+ iounmap(pdata->ioaddr);
+out_free_netdev_2:
+ free_netdev(dev);
+out_release_io_1:
+ release_mem_region(res->start, res->end - res->start);
+out_0:
+ return retval;
+}
+
+static struct platform_driver smsc911x_driver = {
+ .probe = smsc911x_drv_probe,
+ .remove = smsc911x_drv_remove,
+ .driver = {
+ .name = SMSC_CHIPNAME,
+ },
+};
+
+/* Entry point for loading the module */
+static int __init smsc911x_init_module(void)
+{
+ return platform_driver_register(&smsc911x_driver);
+}
+
+/* entry point for unloading the module */
+static void __exit smsc911x_cleanup_module(void)
+{
+ platform_driver_unregister(&smsc911x_driver);
+}
+
+module_init(smsc911x_init_module);
+module_exit(smsc911x_cleanup_module);
diff --git a/drivers/net/smsc911x.h b/drivers/net/smsc911x.h
new file mode 100644
index 000000000000..2b76654bb958
--- /dev/null
+++ b/drivers/net/smsc911x.h
@@ -0,0 +1,390 @@
+/***************************************************************************
+ *
+ * Copyright (C) 2004-2008 SMSC
+ * Copyright (C) 2005-2008 ARM
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ ***************************************************************************/
+#ifndef __SMSC911X_H__
+#define __SMSC911X_H__
+
+#define TX_FIFO_LOW_THRESHOLD ((u32)1600)
+#define SMSC911X_EEPROM_SIZE ((u32)7)
+#define USE_DEBUG 0
+
+/* This is the maximum number of packets to be received every
+ * NAPI poll */
+#define SMSC_NAPI_WEIGHT 16
+
+/* implements a PHY loopback test at initialisation time, to ensure a packet
+ * can be succesfully looped back */
+#define USE_PHY_WORK_AROUND
+
+#define DPRINTK(nlevel, klevel, fmt, args...) \
+ ((void)((NETIF_MSG_##nlevel & pdata->msg_enable) && \
+ printk(KERN_##klevel "%s: %s: " fmt "\n", \
+ pdata->dev->name, __func__, ## args)))
+
+#if USE_DEBUG >= 1
+#define SMSC_WARNING(nlevel, fmt, args...) \
+ DPRINTK(nlevel, WARNING, fmt, ## args)
+#else
+#define SMSC_WARNING(nlevel, fmt, args...) \
+ ({ do {} while (0); 0; })
+#endif
+
+#if USE_DEBUG >= 2
+#define SMSC_TRACE(nlevel, fmt, args...) \
+ DPRINTK(nlevel, INFO, fmt, ## args)
+#else
+#define SMSC_TRACE(nlevel, fmt, args...) \
+ ({ do {} while (0); 0; })
+#endif
+
+#ifdef CONFIG_DEBUG_SPINLOCK
+#define SMSC_ASSERT_MAC_LOCK(pdata) \
+ WARN_ON(!spin_is_locked(&pdata->mac_lock))
+#else
+#define SMSC_ASSERT_MAC_LOCK(pdata) do {} while (0)
+#endif /* CONFIG_DEBUG_SPINLOCK */
+
+/* SMSC911x registers and bitfields */
+#define RX_DATA_FIFO 0x00
+
+#define TX_DATA_FIFO 0x20
+#define TX_CMD_A_ON_COMP_ 0x80000000
+#define TX_CMD_A_BUF_END_ALGN_ 0x03000000
+#define TX_CMD_A_4_BYTE_ALGN_ 0x00000000
+#define TX_CMD_A_16_BYTE_ALGN_ 0x01000000
+#define TX_CMD_A_32_BYTE_ALGN_ 0x02000000
+#define TX_CMD_A_DATA_OFFSET_ 0x001F0000
+#define TX_CMD_A_FIRST_SEG_ 0x00002000
+#define TX_CMD_A_LAST_SEG_ 0x00001000
+#define TX_CMD_A_BUF_SIZE_ 0x000007FF
+#define TX_CMD_B_PKT_TAG_ 0xFFFF0000
+#define TX_CMD_B_ADD_CRC_DISABLE_ 0x00002000
+#define TX_CMD_B_DISABLE_PADDING_ 0x00001000
+#define TX_CMD_B_PKT_BYTE_LENGTH_ 0x000007FF
+
+#define RX_STATUS_FIFO 0x40
+#define RX_STS_ES_ 0x00008000
+#define RX_STS_MCAST_ 0x00000400
+
+#define RX_STATUS_FIFO_PEEK 0x44
+
+#define TX_STATUS_FIFO 0x48
+#define TX_STS_ES_ 0x00008000
+
+#define TX_STATUS_FIFO_PEEK 0x4C
+
+#define ID_REV 0x50
+#define ID_REV_CHIP_ID_ 0xFFFF0000
+#define ID_REV_REV_ID_ 0x0000FFFF
+
+#define INT_CFG 0x54
+#define INT_CFG_INT_DEAS_ 0xFF000000
+#define INT_CFG_INT_DEAS_CLR_ 0x00004000
+#define INT_CFG_INT_DEAS_STS_ 0x00002000
+#define INT_CFG_IRQ_INT_ 0x00001000
+#define INT_CFG_IRQ_EN_ 0x00000100
+#define INT_CFG_IRQ_POL_ 0x00000010
+#define INT_CFG_IRQ_TYPE_ 0x00000001
+
+#define INT_STS 0x58
+#define INT_STS_SW_INT_ 0x80000000
+#define INT_STS_TXSTOP_INT_ 0x02000000
+#define INT_STS_RXSTOP_INT_ 0x01000000
+#define INT_STS_RXDFH_INT_ 0x00800000
+#define INT_STS_RXDF_INT_ 0x00400000
+#define INT_STS_TX_IOC_ 0x00200000
+#define INT_STS_RXD_INT_ 0x00100000
+#define INT_STS_GPT_INT_ 0x00080000
+#define INT_STS_PHY_INT_ 0x00040000
+#define INT_STS_PME_INT_ 0x00020000
+#define INT_STS_TXSO_ 0x00010000
+#define INT_STS_RWT_ 0x00008000
+#define INT_STS_RXE_ 0x00004000
+#define INT_STS_TXE_ 0x00002000
+#define INT_STS_TDFU_ 0x00000800
+#define INT_STS_TDFO_ 0x00000400
+#define INT_STS_TDFA_ 0x00000200
+#define INT_STS_TSFF_ 0x00000100
+#define INT_STS_TSFL_ 0x00000080
+#define INT_STS_RXDF_ 0x00000040
+#define INT_STS_RDFL_ 0x00000020
+#define INT_STS_RSFF_ 0x00000010
+#define INT_STS_RSFL_ 0x00000008
+#define INT_STS_GPIO2_INT_ 0x00000004
+#define INT_STS_GPIO1_INT_ 0x00000002
+#define INT_STS_GPIO0_INT_ 0x00000001
+
+#define INT_EN 0x5C
+#define INT_EN_SW_INT_EN_ 0x80000000
+#define INT_EN_TXSTOP_INT_EN_ 0x02000000
+#define INT_EN_RXSTOP_INT_EN_ 0x01000000
+#define INT_EN_RXDFH_INT_EN_ 0x00800000
+#define INT_EN_TIOC_INT_EN_ 0x00200000
+#define INT_EN_RXD_INT_EN_ 0x00100000
+#define INT_EN_GPT_INT_EN_ 0x00080000
+#define INT_EN_PHY_INT_EN_ 0x00040000
+#define INT_EN_PME_INT_EN_ 0x00020000
+#define INT_EN_TXSO_EN_ 0x00010000
+#define INT_EN_RWT_EN_ 0x00008000
+#define INT_EN_RXE_EN_ 0x00004000
+#define INT_EN_TXE_EN_ 0x00002000
+#define INT_EN_TDFU_EN_ 0x00000800
+#define INT_EN_TDFO_EN_ 0x00000400
+#define INT_EN_TDFA_EN_ 0x00000200
+#define INT_EN_TSFF_EN_ 0x00000100
+#define INT_EN_TSFL_EN_ 0x00000080
+#define INT_EN_RXDF_EN_ 0x00000040
+#define INT_EN_RDFL_EN_ 0x00000020
+#define INT_EN_RSFF_EN_ 0x00000010
+#define INT_EN_RSFL_EN_ 0x00000008
+#define INT_EN_GPIO2_INT_ 0x00000004
+#define INT_EN_GPIO1_INT_ 0x00000002
+#define INT_EN_GPIO0_INT_ 0x00000001
+
+#define BYTE_TEST 0x64
+
+#define FIFO_INT 0x68
+#define FIFO_INT_TX_AVAIL_LEVEL_ 0xFF000000
+#define FIFO_INT_TX_STS_LEVEL_ 0x00FF0000
+#define FIFO_INT_RX_AVAIL_LEVEL_ 0x0000FF00
+#define FIFO_INT_RX_STS_LEVEL_ 0x000000FF
+
+#define RX_CFG 0x6C
+#define RX_CFG_RX_END_ALGN_ 0xC0000000
+#define RX_CFG_RX_END_ALGN4_ 0x00000000
+#define RX_CFG_RX_END_ALGN16_ 0x40000000
+#define RX_CFG_RX_END_ALGN32_ 0x80000000
+#define RX_CFG_RX_DMA_CNT_ 0x0FFF0000
+#define RX_CFG_RX_DUMP_ 0x00008000
+#define RX_CFG_RXDOFF_ 0x00001F00
+
+#define TX_CFG 0x70
+#define TX_CFG_TXS_DUMP_ 0x00008000
+#define TX_CFG_TXD_DUMP_ 0x00004000
+#define TX_CFG_TXSAO_ 0x00000004
+#define TX_CFG_TX_ON_ 0x00000002
+#define TX_CFG_STOP_TX_ 0x00000001
+
+#define HW_CFG 0x74
+#define HW_CFG_TTM_ 0x00200000
+#define HW_CFG_SF_ 0x00100000
+#define HW_CFG_TX_FIF_SZ_ 0x000F0000
+#define HW_CFG_TR_ 0x00003000
+#define HW_CFG_SRST_ 0x00000001
+
+/* only available on 115/117 */
+#define HW_CFG_PHY_CLK_SEL_ 0x00000060
+#define HW_CFG_PHY_CLK_SEL_INT_PHY_ 0x00000000
+#define HW_CFG_PHY_CLK_SEL_EXT_PHY_ 0x00000020
+#define HW_CFG_PHY_CLK_SEL_CLK_DIS_ 0x00000040
+#define HW_CFG_SMI_SEL_ 0x00000010
+#define HW_CFG_EXT_PHY_DET_ 0x00000008
+#define HW_CFG_EXT_PHY_EN_ 0x00000004
+#define HW_CFG_SRST_TO_ 0x00000002
+
+/* only available on 116/118 */
+#define HW_CFG_32_16_BIT_MODE_ 0x00000004
+
+#define RX_DP_CTRL 0x78
+#define RX_DP_CTRL_RX_FFWD_ 0x80000000
+
+#define RX_FIFO_INF 0x7C
+#define RX_FIFO_INF_RXSUSED_ 0x00FF0000
+#define RX_FIFO_INF_RXDUSED_ 0x0000FFFF
+
+#define TX_FIFO_INF 0x80
+#define TX_FIFO_INF_TSUSED_ 0x00FF0000
+#define TX_FIFO_INF_TDFREE_ 0x0000FFFF
+
+#define PMT_CTRL 0x84
+#define PMT_CTRL_PM_MODE_ 0x00003000
+#define PMT_CTRL_PM_MODE_D0_ 0x00000000
+#define PMT_CTRL_PM_MODE_D1_ 0x00001000
+#define PMT_CTRL_PM_MODE_D2_ 0x00002000
+#define PMT_CTRL_PM_MODE_D3_ 0x00003000
+#define PMT_CTRL_PHY_RST_ 0x00000400
+#define PMT_CTRL_WOL_EN_ 0x00000200
+#define PMT_CTRL_ED_EN_ 0x00000100
+#define PMT_CTRL_PME_TYPE_ 0x00000040
+#define PMT_CTRL_WUPS_ 0x00000030
+#define PMT_CTRL_WUPS_NOWAKE_ 0x00000000
+#define PMT_CTRL_WUPS_ED_ 0x00000010
+#define PMT_CTRL_WUPS_WOL_ 0x00000020
+#define PMT_CTRL_WUPS_MULTI_ 0x00000030
+#define PMT_CTRL_PME_IND_ 0x00000008
+#define PMT_CTRL_PME_POL_ 0x00000004
+#define PMT_CTRL_PME_EN_ 0x00000002
+#define PMT_CTRL_READY_ 0x00000001
+
+#define GPIO_CFG 0x88
+#define GPIO_CFG_LED3_EN_ 0x40000000
+#define GPIO_CFG_LED2_EN_ 0x20000000
+#define GPIO_CFG_LED1_EN_ 0x10000000
+#define GPIO_CFG_GPIO2_INT_POL_ 0x04000000
+#define GPIO_CFG_GPIO1_INT_POL_ 0x02000000
+#define GPIO_CFG_GPIO0_INT_POL_ 0x01000000
+#define GPIO_CFG_EEPR_EN_ 0x00700000
+#define GPIO_CFG_GPIOBUF2_ 0x00040000
+#define GPIO_CFG_GPIOBUF1_ 0x00020000
+#define GPIO_CFG_GPIOBUF0_ 0x00010000
+#define GPIO_CFG_GPIODIR2_ 0x00000400
+#define GPIO_CFG_GPIODIR1_ 0x00000200
+#define GPIO_CFG_GPIODIR0_ 0x00000100
+#define GPIO_CFG_GPIOD4_ 0x00000020
+#define GPIO_CFG_GPIOD3_ 0x00000010
+#define GPIO_CFG_GPIOD2_ 0x00000004
+#define GPIO_CFG_GPIOD1_ 0x00000002
+#define GPIO_CFG_GPIOD0_ 0x00000001
+
+#define GPT_CFG 0x8C
+#define GPT_CFG_TIMER_EN_ 0x20000000
+#define GPT_CFG_GPT_LOAD_ 0x0000FFFF
+
+#define GPT_CNT 0x90
+#define GPT_CNT_GPT_CNT_ 0x0000FFFF
+
+#define WORD_SWAP 0x98
+
+#define FREE_RUN 0x9C
+
+#define RX_DROP 0xA0
+
+#define MAC_CSR_CMD 0xA4
+#define MAC_CSR_CMD_CSR_BUSY_ 0x80000000
+#define MAC_CSR_CMD_R_NOT_W_ 0x40000000
+#define MAC_CSR_CMD_CSR_ADDR_ 0x000000FF
+
+#define MAC_CSR_DATA 0xA8
+
+#define AFC_CFG 0xAC
+#define AFC_CFG_AFC_HI_ 0x00FF0000
+#define AFC_CFG_AFC_LO_ 0x0000FF00
+#define AFC_CFG_BACK_DUR_ 0x000000F0
+#define AFC_CFG_FCMULT_ 0x00000008
+#define AFC_CFG_FCBRD_ 0x00000004
+#define AFC_CFG_FCADD_ 0x00000002
+#define AFC_CFG_FCANY_ 0x00000001
+
+#define E2P_CMD 0xB0
+#define E2P_CMD_EPC_BUSY_ 0x80000000
+#define E2P_CMD_EPC_CMD_ 0x70000000
+#define E2P_CMD_EPC_CMD_READ_ 0x00000000
+#define E2P_CMD_EPC_CMD_EWDS_ 0x10000000
+#define E2P_CMD_EPC_CMD_EWEN_ 0x20000000
+#define E2P_CMD_EPC_CMD_WRITE_ 0x30000000
+#define E2P_CMD_EPC_CMD_WRAL_ 0x40000000
+#define E2P_CMD_EPC_CMD_ERASE_ 0x50000000
+#define E2P_CMD_EPC_CMD_ERAL_ 0x60000000
+#define E2P_CMD_EPC_CMD_RELOAD_ 0x70000000
+#define E2P_CMD_EPC_TIMEOUT_ 0x00000200
+#define E2P_CMD_MAC_ADDR_LOADED_ 0x00000100
+#define E2P_CMD_EPC_ADDR_ 0x000000FF
+
+#define E2P_DATA 0xB4
+#define E2P_DATA_EEPROM_DATA_ 0x000000FF
+#define LAN_REGISTER_EXTENT 0x00000100
+
+/*
+ * MAC Control and Status Register (Indirect Address)
+ * Offset (through the MAC_CSR CMD and DATA port)
+ */
+#define MAC_CR 0x01
+#define MAC_CR_RXALL_ 0x80000000
+#define MAC_CR_HBDIS_ 0x10000000
+#define MAC_CR_RCVOWN_ 0x00800000
+#define MAC_CR_LOOPBK_ 0x00200000
+#define MAC_CR_FDPX_ 0x00100000
+#define MAC_CR_MCPAS_ 0x00080000
+#define MAC_CR_PRMS_ 0x00040000
+#define MAC_CR_INVFILT_ 0x00020000
+#define MAC_CR_PASSBAD_ 0x00010000
+#define MAC_CR_HFILT_ 0x00008000
+#define MAC_CR_HPFILT_ 0x00002000
+#define MAC_CR_LCOLL_ 0x00001000
+#define MAC_CR_BCAST_ 0x00000800
+#define MAC_CR_DISRTY_ 0x00000400
+#define MAC_CR_PADSTR_ 0x00000100
+#define MAC_CR_BOLMT_MASK_ 0x000000C0
+#define MAC_CR_DFCHK_ 0x00000020
+#define MAC_CR_TXEN_ 0x00000008
+#define MAC_CR_RXEN_ 0x00000004
+
+#define ADDRH 0x02
+
+#define ADDRL 0x03
+
+#define HASHH 0x04
+
+#define HASHL 0x05
+
+#define MII_ACC 0x06
+#define MII_ACC_PHY_ADDR_ 0x0000F800
+#define MII_ACC_MIIRINDA_ 0x000007C0
+#define MII_ACC_MII_WRITE_ 0x00000002
+#define MII_ACC_MII_BUSY_ 0x00000001
+
+#define MII_DATA 0x07
+
+#define FLOW 0x08
+#define FLOW_FCPT_ 0xFFFF0000
+#define FLOW_FCPASS_ 0x00000004
+#define FLOW_FCEN_ 0x00000002
+#define FLOW_FCBSY_ 0x00000001
+
+#define VLAN1 0x09
+
+#define VLAN2 0x0A
+
+#define WUFF 0x0B
+
+#define WUCSR 0x0C
+#define WUCSR_GUE_ 0x00000200
+#define WUCSR_WUFR_ 0x00000040
+#define WUCSR_MPR_ 0x00000020
+#define WUCSR_WAKE_EN_ 0x00000004
+#define WUCSR_MPEN_ 0x00000002
+
+/*
+ * Phy definitions (vendor-specific)
+ */
+#define LAN9118_PHY_ID 0x00C0001C
+
+#define MII_INTSTS 0x1D
+
+#define MII_INTMSK 0x1E
+#define PHY_INTMSK_AN_RCV_ (1 << 1)
+#define PHY_INTMSK_PDFAULT_ (1 << 2)
+#define PHY_INTMSK_AN_ACK_ (1 << 3)
+#define PHY_INTMSK_LNKDOWN_ (1 << 4)
+#define PHY_INTMSK_RFAULT_ (1 << 5)
+#define PHY_INTMSK_AN_COMP_ (1 << 6)
+#define PHY_INTMSK_ENERGYON_ (1 << 7)
+#define PHY_INTMSK_DEFAULT_ (PHY_INTMSK_ENERGYON_ | \
+ PHY_INTMSK_AN_COMP_ | \
+ PHY_INTMSK_RFAULT_ | \
+ PHY_INTMSK_LNKDOWN_)
+
+#define ADVERTISE_PAUSE_ALL (ADVERTISE_PAUSE_CAP | \
+ ADVERTISE_PAUSE_ASYM)
+
+#define LPA_PAUSE_ALL (LPA_PAUSE_CAP | \
+ LPA_PAUSE_ASYM)
+
+#endif /* __SMSC911X_H__ */
diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c
new file mode 100644
index 000000000000..27e017d96966
--- /dev/null
+++ b/drivers/net/smsc9420.c
@@ -0,0 +1,1744 @@
+ /***************************************************************************
+ *
+ * Copyright (C) 2007,2008 SMSC
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ ***************************************************************************
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <linux/pci.h>
+#include <linux/if_vlan.h>
+#include <linux/dma-mapping.h>
+#include <linux/crc32.h>
+#include <asm/unaligned.h>
+#include "smsc9420.h"
+
+#define DRV_NAME "smsc9420"
+#define PFX DRV_NAME ": "
+#define DRV_MDIONAME "smsc9420-mdio"
+#define DRV_DESCRIPTION "SMSC LAN9420 driver"
+#define DRV_VERSION "1.01"
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
+
+struct smsc9420_dma_desc {
+ u32 status;
+ u32 length;
+ u32 buffer1;
+ u32 buffer2;
+};
+
+struct smsc9420_ring_info {
+ struct sk_buff *skb;
+ dma_addr_t mapping;
+};
+
+struct smsc9420_pdata {
+ void __iomem *base_addr;
+ struct pci_dev *pdev;
+ struct net_device *dev;
+
+ struct smsc9420_dma_desc *rx_ring;
+ struct smsc9420_dma_desc *tx_ring;
+ struct smsc9420_ring_info *tx_buffers;
+ struct smsc9420_ring_info *rx_buffers;
+ dma_addr_t rx_dma_addr;
+ dma_addr_t tx_dma_addr;
+ int tx_ring_head, tx_ring_tail;
+ int rx_ring_head, rx_ring_tail;
+
+ spinlock_t int_lock;
+ spinlock_t phy_lock;
+
+ struct napi_struct napi;
+
+ bool software_irq_signal;
+ bool rx_csum;
+ u32 msg_enable;
+
+ struct phy_device *phy_dev;
+ struct mii_bus *mii_bus;
+ int phy_irq[PHY_MAX_ADDR];
+ int last_duplex;
+ int last_carrier;
+};
+
+static const struct pci_device_id smsc9420_id_table[] = {
+ { PCI_VENDOR_ID_9420, PCI_DEVICE_ID_9420, PCI_ANY_ID, PCI_ANY_ID, },
+ { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, smsc9420_id_table);
+
+#define SMSC_MSG_DEFAULT (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK)
+
+static uint smsc_debug;
+static uint debug = -1;
+module_param(debug, uint, 0);
+MODULE_PARM_DESC(debug, "debug level");
+
+#define smsc_dbg(TYPE, f, a...) \
+do { if ((pd)->msg_enable & NETIF_MSG_##TYPE) \
+ printk(KERN_DEBUG PFX f "\n", ## a); \
+} while (0)
+
+#define smsc_info(TYPE, f, a...) \
+do { if ((pd)->msg_enable & NETIF_MSG_##TYPE) \
+ printk(KERN_INFO PFX f "\n", ## a); \
+} while (0)
+
+#define smsc_warn(TYPE, f, a...) \
+do { if ((pd)->msg_enable & NETIF_MSG_##TYPE) \
+ printk(KERN_WARNING PFX f "\n", ## a); \
+} while (0)
+
+static inline u32 smsc9420_reg_read(struct smsc9420_pdata *pd, u32 offset)
+{
+ return ioread32(pd->base_addr + offset);
+}
+
+static inline void
+smsc9420_reg_write(struct smsc9420_pdata *pd, u32 offset, u32 value)
+{
+ iowrite32(value, pd->base_addr + offset);
+}
+
+static inline void smsc9420_pci_flush_write(struct smsc9420_pdata *pd)
+{
+ /* to ensure PCI write completion, we must perform a PCI read */
+ smsc9420_reg_read(pd, ID_REV);
+}
+
+static int smsc9420_mii_read(struct mii_bus *bus, int phyaddr, int regidx)
+{
+ struct smsc9420_pdata *pd = (struct smsc9420_pdata *)bus->priv;
+ unsigned long flags;
+ u32 addr;
+ int i, reg = -EIO;
+
+ spin_lock_irqsave(&pd->phy_lock, flags);
+
+ /* confirm MII not busy */
+ if ((smsc9420_reg_read(pd, MII_ACCESS) & MII_ACCESS_MII_BUSY_)) {
+ smsc_warn(DRV, "MII is busy???");
+ goto out;
+ }
+
+ /* set the address, index & direction (read from PHY) */
+ addr = ((phyaddr & 0x1F) << 11) | ((regidx & 0x1F) << 6) |
+ MII_ACCESS_MII_READ_;
+ smsc9420_reg_write(pd, MII_ACCESS, addr);
+
+ /* wait for read to complete with 50us timeout */
+ for (i = 0; i < 5; i++) {
+ if (!(smsc9420_reg_read(pd, MII_ACCESS) &
+ MII_ACCESS_MII_BUSY_)) {
+ reg = (u16)smsc9420_reg_read(pd, MII_DATA);
+ goto out;
+ }
+ udelay(10);
+ }
+
+ smsc_warn(DRV, "MII busy timeout!");
+
+out:
+ spin_unlock_irqrestore(&pd->phy_lock, flags);
+ return reg;
+}
+
+static int smsc9420_mii_write(struct mii_bus *bus, int phyaddr, int regidx,
+ u16 val)
+{
+ struct smsc9420_pdata *pd = (struct smsc9420_pdata *)bus->priv;
+ unsigned long flags;
+ u32 addr;
+ int i, reg = -EIO;
+
+ spin_lock_irqsave(&pd->phy_lock, flags);
+
+ /* confirm MII not busy */
+ if ((smsc9420_reg_read(pd, MII_ACCESS) & MII_ACCESS_MII_BUSY_)) {
+ smsc_warn(DRV, "MII is busy???");
+ goto out;
+ }
+
+ /* put the data to write in the MAC */
+ smsc9420_reg_write(pd, MII_DATA, (u32)val);
+
+ /* set the address, index & direction (write to PHY) */
+ addr = ((phyaddr & 0x1F) << 11) | ((regidx & 0x1F) << 6) |
+ MII_ACCESS_MII_WRITE_;
+ smsc9420_reg_write(pd, MII_ACCESS, addr);
+
+ /* wait for write to complete with 50us timeout */
+ for (i = 0; i < 5; i++) {
+ if (!(smsc9420_reg_read(pd, MII_ACCESS) &
+ MII_ACCESS_MII_BUSY_)) {
+ reg = 0;
+ goto out;
+ }
+ udelay(10);
+ }
+
+ smsc_warn(DRV, "MII busy timeout!");
+
+out:
+ spin_unlock_irqrestore(&pd->phy_lock, flags);
+ return reg;
+}
+
+/* Returns hash bit number for given MAC address
+ * Example:
+ * 01 00 5E 00 00 01 -> returns bit number 31 */
+static u32 smsc9420_hash(u8 addr[ETH_ALEN])
+{
+ return (ether_crc(ETH_ALEN, addr) >> 26) & 0x3f;
+}
+
+static int smsc9420_eeprom_reload(struct smsc9420_pdata *pd)
+{
+ int timeout = 100000;
+
+ BUG_ON(!pd);
+
+ if (smsc9420_reg_read(pd, E2P_CMD) & E2P_CMD_EPC_BUSY_) {
+ smsc_dbg(DRV, "smsc9420_eeprom_reload: Eeprom busy");
+ return -EIO;
+ }
+
+ smsc9420_reg_write(pd, E2P_CMD,
+ (E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_RELOAD_));
+
+ do {
+ udelay(10);
+ if (!(smsc9420_reg_read(pd, E2P_CMD) & E2P_CMD_EPC_BUSY_))
+ return 0;
+ } while (timeout--);
+
+ smsc_warn(DRV, "smsc9420_eeprom_reload: Eeprom timed out");
+ return -EIO;
+}
+
+/* Standard ioctls for mii-tool */
+static int smsc9420_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct smsc9420_pdata *pd = netdev_priv(dev);
+
+ if (!netif_running(dev) || !pd->phy_dev)
+ return -EINVAL;
+
+ return phy_mii_ioctl(pd->phy_dev, if_mii(ifr), cmd);
+}
+
+static int smsc9420_ethtool_get_settings(struct net_device *dev,
+ struct ethtool_cmd *cmd)
+{
+ struct smsc9420_pdata *pd = netdev_priv(dev);
+
+ cmd->maxtxpkt = 1;
+ cmd->maxrxpkt = 1;
+ return phy_ethtool_gset(pd->phy_dev, cmd);
+}
+
+static int smsc9420_ethtool_set_settings(struct net_device *dev,
+ struct ethtool_cmd *cmd)
+{
+ struct smsc9420_pdata *pd = netdev_priv(dev);
+
+ return phy_ethtool_sset(pd->phy_dev, cmd);
+}
+
+static void smsc9420_ethtool_get_drvinfo(struct net_device *netdev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ struct smsc9420_pdata *pd = netdev_priv(netdev);
+
+ strcpy(drvinfo->driver, DRV_NAME);
+ strcpy(drvinfo->bus_info, pci_name(pd->pdev));
+ strcpy(drvinfo->version, DRV_VERSION);
+}
+
+static u32 smsc9420_ethtool_get_msglevel(struct net_device *netdev)
+{
+ struct smsc9420_pdata *pd = netdev_priv(netdev);
+ return pd->msg_enable;
+}
+
+static void smsc9420_ethtool_set_msglevel(struct net_device *netdev, u32 data)
+{
+ struct smsc9420_pdata *pd = netdev_priv(netdev);
+ pd->msg_enable = data;
+}
+
+static int smsc9420_ethtool_nway_reset(struct net_device *netdev)
+{
+ struct smsc9420_pdata *pd = netdev_priv(netdev);
+ return phy_start_aneg(pd->phy_dev);
+}
+
+static int smsc9420_ethtool_getregslen(struct net_device *dev)
+{
+ /* all smsc9420 registers plus all phy registers */
+ return 0x100 + (32 * sizeof(u32));
+}
+
+static void
+smsc9420_ethtool_getregs(struct net_device *dev, struct ethtool_regs *regs,
+ void *buf)
+{
+ struct smsc9420_pdata *pd = netdev_priv(dev);
+ struct phy_device *phy_dev = pd->phy_dev;
+ unsigned int i, j = 0;
+ u32 *data = buf;
+
+ regs->version = smsc9420_reg_read(pd, ID_REV);
+ for (i = 0; i < 0x100; i += (sizeof(u32)))
+ data[j++] = smsc9420_reg_read(pd, i);
+
+ for (i = 0; i <= 31; i++)
+ data[j++] = smsc9420_mii_read(phy_dev->bus, phy_dev->addr, i);
+}
+
+static void smsc9420_eeprom_enable_access(struct smsc9420_pdata *pd)
+{
+ unsigned int temp = smsc9420_reg_read(pd, GPIO_CFG);
+ temp &= ~GPIO_CFG_EEPR_EN_;
+ smsc9420_reg_write(pd, GPIO_CFG, temp);
+ msleep(1);
+}
+
+static int smsc9420_eeprom_send_cmd(struct smsc9420_pdata *pd, u32 op)
+{
+ int timeout = 100;
+ u32 e2cmd;
+
+ smsc_dbg(HW, "op 0x%08x", op);
+ if (smsc9420_reg_read(pd, E2P_CMD) & E2P_CMD_EPC_BUSY_) {
+ smsc_warn(HW, "Busy at start");
+ return -EBUSY;
+ }
+
+ e2cmd = op | E2P_CMD_EPC_BUSY_;
+ smsc9420_reg_write(pd, E2P_CMD, e2cmd);
+
+ do {
+ msleep(1);
+ e2cmd = smsc9420_reg_read(pd, E2P_CMD);
+ } while ((e2cmd & E2P_CMD_EPC_BUSY_) && (timeout--));
+
+ if (!timeout) {
+ smsc_info(HW, "TIMED OUT");
+ return -EAGAIN;
+ }
+
+ if (e2cmd & E2P_CMD_EPC_TIMEOUT_) {
+ smsc_info(HW, "Error occured during eeprom operation");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int smsc9420_eeprom_read_location(struct smsc9420_pdata *pd,
+ u8 address, u8 *data)
+{
+ u32 op = E2P_CMD_EPC_CMD_READ_ | address;
+ int ret;
+
+ smsc_dbg(HW, "address 0x%x", address);
+ ret = smsc9420_eeprom_send_cmd(pd, op);
+
+ if (!ret)
+ data[address] = smsc9420_reg_read(pd, E2P_DATA);
+
+ return ret;
+}
+
+static int smsc9420_eeprom_write_location(struct smsc9420_pdata *pd,
+ u8 address, u8 data)
+{
+ u32 op = E2P_CMD_EPC_CMD_ERASE_ | address;
+ int ret;
+
+ smsc_dbg(HW, "address 0x%x, data 0x%x", address, data);
+ ret = smsc9420_eeprom_send_cmd(pd, op);
+
+ if (!ret) {
+ op = E2P_CMD_EPC_CMD_WRITE_ | address;
+ smsc9420_reg_write(pd, E2P_DATA, (u32)data);
+ ret = smsc9420_eeprom_send_cmd(pd, op);
+ }
+
+ return ret;
+}
+
+static int smsc9420_ethtool_get_eeprom_len(struct net_device *dev)
+{
+ return SMSC9420_EEPROM_SIZE;
+}
+
+static int smsc9420_ethtool_get_eeprom(struct net_device *dev,
+ struct ethtool_eeprom *eeprom, u8 *data)
+{
+ struct smsc9420_pdata *pd = netdev_priv(dev);
+ u8 eeprom_data[SMSC9420_EEPROM_SIZE];
+ int len, i;
+
+ smsc9420_eeprom_enable_access(pd);
+
+ len = min(eeprom->len, SMSC9420_EEPROM_SIZE);
+ for (i = 0; i < len; i++) {
+ int ret = smsc9420_eeprom_read_location(pd, i, eeprom_data);
+ if (ret < 0) {
+ eeprom->len = 0;
+ return ret;
+ }
+ }
+
+ memcpy(data, &eeprom_data[eeprom->offset], len);
+ eeprom->len = len;
+ return 0;
+}
+
+static int smsc9420_ethtool_set_eeprom(struct net_device *dev,
+ struct ethtool_eeprom *eeprom, u8 *data)
+{
+ struct smsc9420_pdata *pd = netdev_priv(dev);
+ int ret;
+
+ smsc9420_eeprom_enable_access(pd);
+ smsc9420_eeprom_send_cmd(pd, E2P_CMD_EPC_CMD_EWEN_);
+ ret = smsc9420_eeprom_write_location(pd, eeprom->offset, *data);
+ smsc9420_eeprom_send_cmd(pd, E2P_CMD_EPC_CMD_EWDS_);
+
+ /* Single byte write, according to man page */
+ eeprom->len = 1;
+
+ return ret;
+}
+
+static const struct ethtool_ops smsc9420_ethtool_ops = {
+ .get_settings = smsc9420_ethtool_get_settings,
+ .set_settings = smsc9420_ethtool_set_settings,
+ .get_drvinfo = smsc9420_ethtool_get_drvinfo,
+ .get_msglevel = smsc9420_ethtool_get_msglevel,
+ .set_msglevel = smsc9420_ethtool_set_msglevel,
+ .nway_reset = smsc9420_ethtool_nway_reset,
+ .get_link = ethtool_op_get_link,
+ .get_eeprom_len = smsc9420_ethtool_get_eeprom_len,
+ .get_eeprom = smsc9420_ethtool_get_eeprom,
+ .set_eeprom = smsc9420_ethtool_set_eeprom,
+ .get_regs_len = smsc9420_ethtool_getregslen,
+ .get_regs = smsc9420_ethtool_getregs,
+};
+
+/* Sets the device MAC address to dev_addr */
+static void smsc9420_set_mac_address(struct net_device *dev)
+{
+ struct smsc9420_pdata *pd = netdev_priv(dev);
+ u8 *dev_addr = dev->dev_addr;
+ u32 mac_high16 = (dev_addr[5] << 8) | dev_addr[4];
+ u32 mac_low32 = (dev_addr[3] << 24) | (dev_addr[2] << 16) |
+ (dev_addr[1] << 8) | dev_addr[0];
+
+ smsc9420_reg_write(pd, ADDRH, mac_high16);
+ smsc9420_reg_write(pd, ADDRL, mac_low32);
+}
+
+static void smsc9420_check_mac_address(struct net_device *dev)
+{
+ struct smsc9420_pdata *pd = netdev_priv(dev);
+
+ /* Check if mac address has been specified when bringing interface up */
+ if (is_valid_ether_addr(dev->dev_addr)) {
+ smsc9420_set_mac_address(dev);
+ smsc_dbg(PROBE, "MAC Address is specified by configuration");
+ } else {
+ /* Try reading mac address from device. if EEPROM is present
+ * it will already have been set */
+ u32 mac_high16 = smsc9420_reg_read(pd, ADDRH);
+ u32 mac_low32 = smsc9420_reg_read(pd, ADDRL);
+ dev->dev_addr[0] = (u8)(mac_low32);
+ dev->dev_addr[1] = (u8)(mac_low32 >> 8);
+ dev->dev_addr[2] = (u8)(mac_low32 >> 16);
+ dev->dev_addr[3] = (u8)(mac_low32 >> 24);
+ dev->dev_addr[4] = (u8)(mac_high16);
+ dev->dev_addr[5] = (u8)(mac_high16 >> 8);
+
+ if (is_valid_ether_addr(dev->dev_addr)) {
+ /* eeprom values are valid so use them */
+ smsc_dbg(PROBE, "Mac Address is read from EEPROM");
+ } else {
+ /* eeprom values are invalid, generate random MAC */
+ random_ether_addr(dev->dev_addr);
+ smsc9420_set_mac_address(dev);
+ smsc_dbg(PROBE,
+ "MAC Address is set to random_ether_addr");
+ }
+ }
+}
+
+static void smsc9420_stop_tx(struct smsc9420_pdata *pd)
+{
+ u32 dmac_control, mac_cr, dma_intr_ena;
+ int timeOut = 1000;
+
+ /* disable TX DMAC */
+ dmac_control = smsc9420_reg_read(pd, DMAC_CONTROL);
+ dmac_control &= (~DMAC_CONTROL_ST_);
+ smsc9420_reg_write(pd, DMAC_CONTROL, dmac_control);
+
+ /* Wait max 10ms for transmit process to stop */
+ while (timeOut--) {
+ if (smsc9420_reg_read(pd, DMAC_STATUS) & DMAC_STS_TS_)
+ break;
+ udelay(10);
+ }
+
+ if (!timeOut)
+ smsc_warn(IFDOWN, "TX DMAC failed to stop");
+
+ /* ACK Tx DMAC stop bit */
+ smsc9420_reg_write(pd, DMAC_STATUS, DMAC_STS_TXPS_);
+
+ /* mask TX DMAC interrupts */
+ dma_intr_ena = smsc9420_reg_read(pd, DMAC_INTR_ENA);
+ dma_intr_ena &= ~(DMAC_INTR_ENA_TX_);
+ smsc9420_reg_write(pd, DMAC_INTR_ENA, dma_intr_ena);
+ smsc9420_pci_flush_write(pd);
+
+ /* stop MAC TX */
+ mac_cr = smsc9420_reg_read(pd, MAC_CR) & (~MAC_CR_TXEN_);
+ smsc9420_reg_write(pd, MAC_CR, mac_cr);
+ smsc9420_pci_flush_write(pd);
+}
+
+static void smsc9420_free_tx_ring(struct smsc9420_pdata *pd)
+{
+ int i;
+
+ BUG_ON(!pd->tx_ring);
+
+ if (!pd->tx_buffers)
+ return;
+
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ struct sk_buff *skb = pd->tx_buffers[i].skb;
+
+ if (skb) {
+ BUG_ON(!pd->tx_buffers[i].mapping);
+ pci_unmap_single(pd->pdev, pd->tx_buffers[i].mapping,
+ skb->len, PCI_DMA_TODEVICE);
+ dev_kfree_skb_any(skb);
+ }
+
+ pd->tx_ring[i].status = 0;
+ pd->tx_ring[i].length = 0;
+ pd->tx_ring[i].buffer1 = 0;
+ pd->tx_ring[i].buffer2 = 0;
+ }
+ wmb();
+
+ kfree(pd->tx_buffers);
+ pd->tx_buffers = NULL;
+
+ pd->tx_ring_head = 0;
+ pd->tx_ring_tail = 0;
+}
+
+static void smsc9420_free_rx_ring(struct smsc9420_pdata *pd)
+{
+ int i;
+
+ BUG_ON(!pd->rx_ring);
+
+ if (!pd->rx_buffers)
+ return;
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ if (pd->rx_buffers[i].skb)
+ dev_kfree_skb_any(pd->rx_buffers[i].skb);
+
+ if (pd->rx_buffers[i].mapping)
+ pci_unmap_single(pd->pdev, pd->rx_buffers[i].mapping,
+ PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
+
+ pd->rx_ring[i].status = 0;
+ pd->rx_ring[i].length = 0;
+ pd->rx_ring[i].buffer1 = 0;
+ pd->rx_ring[i].buffer2 = 0;
+ }
+ wmb();
+
+ kfree(pd->rx_buffers);
+ pd->rx_buffers = NULL;
+
+ pd->rx_ring_head = 0;
+ pd->rx_ring_tail = 0;
+}
+
+static void smsc9420_stop_rx(struct smsc9420_pdata *pd)
+{
+ int timeOut = 1000;
+ u32 mac_cr, dmac_control, dma_intr_ena;
+
+ /* mask RX DMAC interrupts */
+ dma_intr_ena = smsc9420_reg_read(pd, DMAC_INTR_ENA);
+ dma_intr_ena &= (~DMAC_INTR_ENA_RX_);
+ smsc9420_reg_write(pd, DMAC_INTR_ENA, dma_intr_ena);
+ smsc9420_pci_flush_write(pd);
+
+ /* stop RX MAC prior to stoping DMA */
+ mac_cr = smsc9420_reg_read(pd, MAC_CR) & (~MAC_CR_RXEN_);
+ smsc9420_reg_write(pd, MAC_CR, mac_cr);
+ smsc9420_pci_flush_write(pd);
+
+ /* stop RX DMAC */
+ dmac_control = smsc9420_reg_read(pd, DMAC_CONTROL);
+ dmac_control &= (~DMAC_CONTROL_SR_);
+ smsc9420_reg_write(pd, DMAC_CONTROL, dmac_control);
+ smsc9420_pci_flush_write(pd);
+
+ /* wait up to 10ms for receive to stop */
+ while (timeOut--) {
+ if (smsc9420_reg_read(pd, DMAC_STATUS) & DMAC_STS_RS_)
+ break;
+ udelay(10);
+ }
+
+ if (!timeOut)
+ smsc_warn(IFDOWN, "RX DMAC did not stop! timeout.");
+
+ /* ACK the Rx DMAC stop bit */
+ smsc9420_reg_write(pd, DMAC_STATUS, DMAC_STS_RXPS_);
+}
+
+static irqreturn_t smsc9420_isr(int irq, void *dev_id)
+{
+ struct smsc9420_pdata *pd = dev_id;
+ u32 int_cfg, int_sts, int_ctl;
+ irqreturn_t ret = IRQ_NONE;
+ ulong flags;
+
+ BUG_ON(!pd);
+ BUG_ON(!pd->base_addr);
+
+ int_cfg = smsc9420_reg_read(pd, INT_CFG);
+
+ /* check if it's our interrupt */
+ if ((int_cfg & (INT_CFG_IRQ_EN_ | INT_CFG_IRQ_INT_)) !=
+ (INT_CFG_IRQ_EN_ | INT_CFG_IRQ_INT_))
+ return IRQ_NONE;
+
+ int_sts = smsc9420_reg_read(pd, INT_STAT);
+
+ if (likely(INT_STAT_DMAC_INT_ & int_sts)) {
+ u32 status = smsc9420_reg_read(pd, DMAC_STATUS);
+ u32 ints_to_clear = 0;
+
+ if (status & DMAC_STS_TX_) {
+ ints_to_clear |= (DMAC_STS_TX_ | DMAC_STS_NIS_);
+ netif_wake_queue(pd->dev);
+ }
+
+ if (status & DMAC_STS_RX_) {
+ /* mask RX DMAC interrupts */
+ u32 dma_intr_ena = smsc9420_reg_read(pd, DMAC_INTR_ENA);
+ dma_intr_ena &= (~DMAC_INTR_ENA_RX_);
+ smsc9420_reg_write(pd, DMAC_INTR_ENA, dma_intr_ena);
+ smsc9420_pci_flush_write(pd);
+
+ ints_to_clear |= (DMAC_STS_RX_ | DMAC_STS_NIS_);
+ netif_rx_schedule(&pd->napi);
+ }
+
+ if (ints_to_clear)
+ smsc9420_reg_write(pd, DMAC_STATUS, ints_to_clear);
+
+ ret = IRQ_HANDLED;
+ }
+
+ if (unlikely(INT_STAT_SW_INT_ & int_sts)) {
+ /* mask software interrupt */
+ spin_lock_irqsave(&pd->int_lock, flags);
+ int_ctl = smsc9420_reg_read(pd, INT_CTL);
+ int_ctl &= (~INT_CTL_SW_INT_EN_);
+ smsc9420_reg_write(pd, INT_CTL, int_ctl);
+ spin_unlock_irqrestore(&pd->int_lock, flags);
+
+ smsc9420_reg_write(pd, INT_STAT, INT_STAT_SW_INT_);
+ pd->software_irq_signal = true;
+ smp_wmb();
+
+ ret = IRQ_HANDLED;
+ }
+
+ /* to ensure PCI write completion, we must perform a PCI read */
+ smsc9420_pci_flush_write(pd);
+
+ return ret;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void smsc9420_poll_controller(struct net_device *dev)
+{
+ disable_irq(dev->irq);
+ smsc9420_isr(0, dev);
+ enable_irq(dev->irq);
+}
+#endif /* CONFIG_NET_POLL_CONTROLLER */
+
+static void smsc9420_dmac_soft_reset(struct smsc9420_pdata *pd)
+{
+ smsc9420_reg_write(pd, BUS_MODE, BUS_MODE_SWR_);
+ smsc9420_reg_read(pd, BUS_MODE);
+ udelay(2);
+ if (smsc9420_reg_read(pd, BUS_MODE) & BUS_MODE_SWR_)
+ smsc_warn(DRV, "Software reset not cleared");
+}
+
+static int smsc9420_stop(struct net_device *dev)
+{
+ struct smsc9420_pdata *pd = netdev_priv(dev);
+ u32 int_cfg;
+ ulong flags;
+
+ BUG_ON(!pd);
+ BUG_ON(!pd->phy_dev);
+
+ /* disable master interrupt */
+ spin_lock_irqsave(&pd->int_lock, flags);
+ int_cfg = smsc9420_reg_read(pd, INT_CFG) & (~INT_CFG_IRQ_EN_);
+ smsc9420_reg_write(pd, INT_CFG, int_cfg);
+ spin_unlock_irqrestore(&pd->int_lock, flags);
+
+ netif_tx_disable(dev);
+ napi_disable(&pd->napi);
+
+ smsc9420_stop_tx(pd);
+ smsc9420_free_tx_ring(pd);
+
+ smsc9420_stop_rx(pd);
+ smsc9420_free_rx_ring(pd);
+
+ free_irq(dev->irq, pd);
+
+ smsc9420_dmac_soft_reset(pd);
+
+ phy_stop(pd->phy_dev);
+
+ phy_disconnect(pd->phy_dev);
+ pd->phy_dev = NULL;
+ mdiobus_unregister(pd->mii_bus);
+ mdiobus_free(pd->mii_bus);
+
+ return 0;
+}
+
+static void smsc9420_rx_count_stats(struct net_device *dev, u32 desc_status)
+{
+ if (unlikely(desc_status & RDES0_ERROR_SUMMARY_)) {
+ dev->stats.rx_errors++;
+ if (desc_status & RDES0_DESCRIPTOR_ERROR_)
+ dev->stats.rx_over_errors++;
+ else if (desc_status & (RDES0_FRAME_TOO_LONG_ |
+ RDES0_RUNT_FRAME_ | RDES0_COLLISION_SEEN_))
+ dev->stats.rx_frame_errors++;
+ else if (desc_status & RDES0_CRC_ERROR_)
+ dev->stats.rx_crc_errors++;
+ }
+
+ if (unlikely(desc_status & RDES0_LENGTH_ERROR_))
+ dev->stats.rx_length_errors++;
+
+ if (unlikely(!((desc_status & RDES0_LAST_DESCRIPTOR_) &&
+ (desc_status & RDES0_FIRST_DESCRIPTOR_))))
+ dev->stats.rx_length_errors++;
+
+ if (desc_status & RDES0_MULTICAST_FRAME_)
+ dev->stats.multicast++;
+}
+
+static void smsc9420_rx_handoff(struct smsc9420_pdata *pd, const int index,
+ const u32 status)
+{
+ struct net_device *dev = pd->dev;
+ struct sk_buff *skb;
+ u16 packet_length = (status & RDES0_FRAME_LENGTH_MASK_)
+ >> RDES0_FRAME_LENGTH_SHFT_;
+
+ /* remove crc from packet lendth */
+ packet_length -= 4;
+
+ if (pd->rx_csum)
+ packet_length -= 2;
+
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += packet_length;
+
+ pci_unmap_single(pd->pdev, pd->rx_buffers[index].mapping,
+ PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
+ pd->rx_buffers[index].mapping = 0;
+
+ skb = pd->rx_buffers[index].skb;
+ pd->rx_buffers[index].skb = NULL;
+
+ if (pd->rx_csum) {
+ u16 hw_csum = get_unaligned_le16(skb_tail_pointer(skb) +
+ NET_IP_ALIGN + packet_length + 4);
+ put_unaligned_le16(cpu_to_le16(hw_csum), &skb->csum);
+ skb->ip_summed = CHECKSUM_COMPLETE;
+ }
+
+ skb_reserve(skb, NET_IP_ALIGN);
+ skb_put(skb, packet_length);
+
+ skb->protocol = eth_type_trans(skb, dev);
+
+ netif_receive_skb(skb);
+ dev->last_rx = jiffies;
+}
+
+static int smsc9420_alloc_rx_buffer(struct smsc9420_pdata *pd, int index)
+{
+ struct sk_buff *skb = netdev_alloc_skb(pd->dev, PKT_BUF_SZ);
+ dma_addr_t mapping;
+
+ BUG_ON(pd->rx_buffers[index].skb);
+ BUG_ON(pd->rx_buffers[index].mapping);
+
+ if (unlikely(!skb)) {
+ smsc_warn(RX_ERR, "Failed to allocate new skb!");
+ return -ENOMEM;
+ }
+
+ skb->dev = pd->dev;
+
+ mapping = pci_map_single(pd->pdev, skb_tail_pointer(skb),
+ PKT_BUF_SZ, PCI_DMA_FROMDEVICE);
+ if (pci_dma_mapping_error(pd->pdev, mapping)) {
+ dev_kfree_skb_any(skb);
+ smsc_warn(RX_ERR, "pci_map_single failed!");
+ return -ENOMEM;
+ }
+
+ pd->rx_buffers[index].skb = skb;
+ pd->rx_buffers[index].mapping = mapping;
+ pd->rx_ring[index].buffer1 = mapping + NET_IP_ALIGN;
+ pd->rx_ring[index].status = RDES0_OWN_;
+ wmb();
+
+ return 0;
+}
+
+static void smsc9420_alloc_new_rx_buffers(struct smsc9420_pdata *pd)
+{
+ while (pd->rx_ring_tail != pd->rx_ring_head) {
+ if (smsc9420_alloc_rx_buffer(pd, pd->rx_ring_tail))
+ break;
+
+ pd->rx_ring_tail = (pd->rx_ring_tail + 1) % RX_RING_SIZE;
+ }
+}
+
+static int smsc9420_rx_poll(struct napi_struct *napi, int budget)
+{
+ struct smsc9420_pdata *pd =
+ container_of(napi, struct smsc9420_pdata, napi);
+ struct net_device *dev = pd->dev;
+ u32 drop_frame_cnt, dma_intr_ena, status;
+ int work_done;
+
+ for (work_done = 0; work_done < budget; work_done++) {
+ rmb();
+ status = pd->rx_ring[pd->rx_ring_head].status;
+
+ /* stop if DMAC owns this dma descriptor */
+ if (status & RDES0_OWN_)
+ break;
+
+ smsc9420_rx_count_stats(dev, status);
+ smsc9420_rx_handoff(pd, pd->rx_ring_head, status);
+ pd->rx_ring_head = (pd->rx_ring_head + 1) % RX_RING_SIZE;
+ smsc9420_alloc_new_rx_buffers(pd);
+ }
+
+ drop_frame_cnt = smsc9420_reg_read(pd, MISS_FRAME_CNTR);
+ dev->stats.rx_dropped +=
+ (drop_frame_cnt & 0xFFFF) + ((drop_frame_cnt >> 17) & 0x3FF);
+
+ /* Kick RXDMA */
+ smsc9420_reg_write(pd, RX_POLL_DEMAND, 1);
+ smsc9420_pci_flush_write(pd);
+
+ if (work_done < budget) {
+ netif_rx_complete(&pd->napi);
+
+ /* re-enable RX DMA interrupts */
+ dma_intr_ena = smsc9420_reg_read(pd, DMAC_INTR_ENA);
+ dma_intr_ena |= (DMAC_INTR_ENA_RX_ | DMAC_INTR_ENA_NIS_);
+ smsc9420_reg_write(pd, DMAC_INTR_ENA, dma_intr_ena);
+ smsc9420_pci_flush_write(pd);
+ }
+ return work_done;
+}
+
+static void
+smsc9420_tx_update_stats(struct net_device *dev, u32 status, u32 length)
+{
+ if (unlikely(status & TDES0_ERROR_SUMMARY_)) {
+ dev->stats.tx_errors++;
+ if (status & (TDES0_EXCESSIVE_DEFERRAL_ |
+ TDES0_EXCESSIVE_COLLISIONS_))
+ dev->stats.tx_aborted_errors++;
+
+ if (status & (TDES0_LOSS_OF_CARRIER_ | TDES0_NO_CARRIER_))
+ dev->stats.tx_carrier_errors++;
+ } else {
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += (length & 0x7FF);
+ }
+
+ if (unlikely(status & TDES0_EXCESSIVE_COLLISIONS_)) {
+ dev->stats.collisions += 16;
+ } else {
+ dev->stats.collisions +=
+ (status & TDES0_COLLISION_COUNT_MASK_) >>
+ TDES0_COLLISION_COUNT_SHFT_;
+ }
+
+ if (unlikely(status & TDES0_HEARTBEAT_FAIL_))
+ dev->stats.tx_heartbeat_errors++;
+}
+
+/* Check for completed dma transfers, update stats and free skbs */
+static void smsc9420_complete_tx(struct net_device *dev)
+{
+ struct smsc9420_pdata *pd = netdev_priv(dev);
+
+ while (pd->tx_ring_tail != pd->tx_ring_head) {
+ int index = pd->tx_ring_tail;
+ u32 status, length;
+
+ rmb();
+ status = pd->tx_ring[index].status;
+ length = pd->tx_ring[index].length;
+
+ /* Check if DMA still owns this descriptor */
+ if (unlikely(TDES0_OWN_ & status))
+ break;
+
+ smsc9420_tx_update_stats(dev, status, length);
+
+ BUG_ON(!pd->tx_buffers[index].skb);
+ BUG_ON(!pd->tx_buffers[index].mapping);
+
+ pci_unmap_single(pd->pdev, pd->tx_buffers[index].mapping,
+ pd->tx_buffers[index].skb->len, PCI_DMA_TODEVICE);
+ pd->tx_buffers[index].mapping = 0;
+
+ dev_kfree_skb_any(pd->tx_buffers[index].skb);
+ pd->tx_buffers[index].skb = NULL;
+
+ pd->tx_ring[index].buffer1 = 0;
+ wmb();
+
+ pd->tx_ring_tail = (pd->tx_ring_tail + 1) % TX_RING_SIZE;
+ }
+}
+
+static int smsc9420_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct smsc9420_pdata *pd = netdev_priv(dev);
+ dma_addr_t mapping;
+ int index = pd->tx_ring_head;
+ u32 tmp_desc1;
+ bool about_to_take_last_desc =
+ (((pd->tx_ring_head + 2) % TX_RING_SIZE) == pd->tx_ring_tail);
+
+ smsc9420_complete_tx(dev);
+
+ rmb();
+ BUG_ON(pd->tx_ring[index].status & TDES0_OWN_);
+ BUG_ON(pd->tx_buffers[index].skb);
+ BUG_ON(pd->tx_buffers[index].mapping);
+
+ mapping = pci_map_single(pd->pdev, skb->data,
+ skb->len, PCI_DMA_TODEVICE);
+ if (pci_dma_mapping_error(pd->pdev, mapping)) {
+ smsc_warn(TX_ERR, "pci_map_single failed, dropping packet");
+ return NETDEV_TX_BUSY;
+ }
+
+ pd->tx_buffers[index].skb = skb;
+ pd->tx_buffers[index].mapping = mapping;
+
+ tmp_desc1 = (TDES1_LS_ | ((u32)skb->len & 0x7FF));
+ if (unlikely(about_to_take_last_desc)) {
+ tmp_desc1 |= TDES1_IC_;
+ netif_stop_queue(pd->dev);
+ }
+
+ /* check if we are at the last descriptor and need to set EOR */
+ if (unlikely(index == (TX_RING_SIZE - 1)))
+ tmp_desc1 |= TDES1_TER_;
+
+ pd->tx_ring[index].buffer1 = mapping;
+ pd->tx_ring[index].length = tmp_desc1;
+ wmb();
+
+ /* increment head */
+ pd->tx_ring_head = (pd->tx_ring_head + 1) % TX_RING_SIZE;
+
+ /* assign ownership to DMAC */
+ pd->tx_ring[index].status = TDES0_OWN_;
+ wmb();
+
+ /* kick the DMA */
+ smsc9420_reg_write(pd, TX_POLL_DEMAND, 1);
+ smsc9420_pci_flush_write(pd);
+
+ dev->trans_start = jiffies;
+
+ return NETDEV_TX_OK;
+}
+
+static struct net_device_stats *smsc9420_get_stats(struct net_device *dev)
+{
+ struct smsc9420_pdata *pd = netdev_priv(dev);
+ u32 counter = smsc9420_reg_read(pd, MISS_FRAME_CNTR);
+ dev->stats.rx_dropped +=
+ (counter & 0x0000FFFF) + ((counter >> 17) & 0x000003FF);
+ return &dev->stats;
+}
+
+static void smsc9420_set_multicast_list(struct net_device *dev)
+{
+ struct smsc9420_pdata *pd = netdev_priv(dev);
+ u32 mac_cr = smsc9420_reg_read(pd, MAC_CR);
+
+ if (dev->flags & IFF_PROMISC) {
+ smsc_dbg(HW, "Promiscuous Mode Enabled");
+ mac_cr |= MAC_CR_PRMS_;
+ mac_cr &= (~MAC_CR_MCPAS_);
+ mac_cr &= (~MAC_CR_HPFILT_);
+ } else if (dev->flags & IFF_ALLMULTI) {
+ smsc_dbg(HW, "Receive all Multicast Enabled");
+ mac_cr &= (~MAC_CR_PRMS_);
+ mac_cr |= MAC_CR_MCPAS_;
+ mac_cr &= (~MAC_CR_HPFILT_);
+ } else if (dev->mc_count > 0) {
+ struct dev_mc_list *mc_list = dev->mc_list;
+ u32 hash_lo = 0, hash_hi = 0;
+
+ smsc_dbg(HW, "Multicast filter enabled");
+ while (mc_list) {
+ u32 bit_num = smsc9420_hash(mc_list->dmi_addr);
+ u32 mask = 1 << (bit_num & 0x1F);
+
+ if (bit_num & 0x20)
+ hash_hi |= mask;
+ else
+ hash_lo |= mask;
+
+ mc_list = mc_list->next;
+ }
+ smsc9420_reg_write(pd, HASHH, hash_hi);
+ smsc9420_reg_write(pd, HASHL, hash_lo);
+
+ mac_cr &= (~MAC_CR_PRMS_);
+ mac_cr &= (~MAC_CR_MCPAS_);
+ mac_cr |= MAC_CR_HPFILT_;
+ } else {
+ smsc_dbg(HW, "Receive own packets only.");
+ smsc9420_reg_write(pd, HASHH, 0);
+ smsc9420_reg_write(pd, HASHL, 0);
+
+ mac_cr &= (~MAC_CR_PRMS_);
+ mac_cr &= (~MAC_CR_MCPAS_);
+ mac_cr &= (~MAC_CR_HPFILT_);
+ }
+
+ smsc9420_reg_write(pd, MAC_CR, mac_cr);
+ smsc9420_pci_flush_write(pd);
+}
+
+static void smsc9420_phy_update_flowcontrol(struct smsc9420_pdata *pd)
+{
+ struct phy_device *phy_dev = pd->phy_dev;
+ u32 flow;
+
+ if (phy_dev->duplex == DUPLEX_FULL) {
+ u16 lcladv = phy_read(phy_dev, MII_ADVERTISE);
+ u16 rmtadv = phy_read(phy_dev, MII_LPA);
+ u8 cap = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
+
+ if (cap & FLOW_CTRL_RX)
+ flow = 0xFFFF0002;
+ else
+ flow = 0;
+
+ smsc_info(LINK, "rx pause %s, tx pause %s",
+ (cap & FLOW_CTRL_RX ? "enabled" : "disabled"),
+ (cap & FLOW_CTRL_TX ? "enabled" : "disabled"));
+ } else {
+ smsc_info(LINK, "half duplex");
+ flow = 0;
+ }
+
+ smsc9420_reg_write(pd, FLOW, flow);
+}
+
+/* Update link mode if anything has changed. Called periodically when the
+ * PHY is in polling mode, even if nothing has changed. */
+static void smsc9420_phy_adjust_link(struct net_device *dev)
+{
+ struct smsc9420_pdata *pd = netdev_priv(dev);
+ struct phy_device *phy_dev = pd->phy_dev;
+ int carrier;
+
+ if (phy_dev->duplex != pd->last_duplex) {
+ u32 mac_cr = smsc9420_reg_read(pd, MAC_CR);
+ if (phy_dev->duplex) {
+ smsc_dbg(LINK, "full duplex mode");
+ mac_cr |= MAC_CR_FDPX_;
+ } else {
+ smsc_dbg(LINK, "half duplex mode");
+ mac_cr &= ~MAC_CR_FDPX_;
+ }
+ smsc9420_reg_write(pd, MAC_CR, mac_cr);
+
+ smsc9420_phy_update_flowcontrol(pd);
+ pd->last_duplex = phy_dev->duplex;
+ }
+
+ carrier = netif_carrier_ok(dev);
+ if (carrier != pd->last_carrier) {
+ if (carrier)
+ smsc_dbg(LINK, "carrier OK");
+ else
+ smsc_dbg(LINK, "no carrier");
+ pd->last_carrier = carrier;
+ }
+}
+
+static int smsc9420_mii_probe(struct net_device *dev)
+{
+ struct smsc9420_pdata *pd = netdev_priv(dev);
+ struct phy_device *phydev = NULL;
+
+ BUG_ON(pd->phy_dev);
+
+ /* Device only supports internal PHY at address 1 */
+ if (!pd->mii_bus->phy_map[1]) {
+ pr_err("%s: no PHY found at address 1\n", dev->name);
+ return -ENODEV;
+ }
+
+ phydev = pd->mii_bus->phy_map[1];
+ smsc_info(PROBE, "PHY addr %d, phy_id 0x%08X", phydev->addr,
+ phydev->phy_id);
+
+ phydev = phy_connect(dev, phydev->dev.bus_id,
+ &smsc9420_phy_adjust_link, 0, PHY_INTERFACE_MODE_MII);
+
+ if (IS_ERR(phydev)) {
+ pr_err("%s: Could not attach to PHY\n", dev->name);
+ return PTR_ERR(phydev);
+ }
+
+ pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
+ dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq);
+
+ /* mask with MAC supported features */
+ phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
+ phydev->advertising = phydev->supported;
+
+ pd->phy_dev = phydev;
+ pd->last_duplex = -1;
+ pd->last_carrier = -1;
+
+ return 0;
+}
+
+static int smsc9420_mii_init(struct net_device *dev)
+{
+ struct smsc9420_pdata *pd = netdev_priv(dev);
+ int err = -ENXIO, i;
+
+ pd->mii_bus = mdiobus_alloc();
+ if (!pd->mii_bus) {
+ err = -ENOMEM;
+ goto err_out_1;
+ }
+ pd->mii_bus->name = DRV_MDIONAME;
+ snprintf(pd->mii_bus->id, MII_BUS_ID_SIZE, "%x",
+ (pd->pdev->bus->number << 8) | pd->pdev->devfn);
+ pd->mii_bus->priv = pd;
+ pd->mii_bus->read = smsc9420_mii_read;
+ pd->mii_bus->write = smsc9420_mii_write;
+ pd->mii_bus->irq = pd->phy_irq;
+ for (i = 0; i < PHY_MAX_ADDR; ++i)
+ pd->mii_bus->irq[i] = PHY_POLL;
+
+ /* Mask all PHYs except ID 1 (internal) */
+ pd->mii_bus->phy_mask = ~(1 << 1);
+
+ if (mdiobus_register(pd->mii_bus)) {
+ smsc_warn(PROBE, "Error registering mii bus");
+ goto err_out_free_bus_2;
+ }
+
+ if (smsc9420_mii_probe(dev) < 0) {
+ smsc_warn(PROBE, "Error probing mii bus");
+ goto err_out_unregister_bus_3;
+ }
+
+ return 0;
+
+err_out_unregister_bus_3:
+ mdiobus_unregister(pd->mii_bus);
+err_out_free_bus_2:
+ mdiobus_free(pd->mii_bus);
+err_out_1:
+ return err;
+}
+
+static int smsc9420_alloc_tx_ring(struct smsc9420_pdata *pd)
+{
+ int i;
+
+ BUG_ON(!pd->tx_ring);
+
+ pd->tx_buffers = kmalloc((sizeof(struct smsc9420_ring_info) *
+ TX_RING_SIZE), GFP_KERNEL);
+ if (!pd->tx_buffers) {
+ smsc_warn(IFUP, "Failed to allocated tx_buffers");
+ return -ENOMEM;
+ }
+
+ /* Initialize the TX Ring */
+ for (i = 0; i < TX_RING_SIZE; i++) {
+ pd->tx_buffers[i].skb = NULL;
+ pd->tx_buffers[i].mapping = 0;
+ pd->tx_ring[i].status = 0;
+ pd->tx_ring[i].length = 0;
+ pd->tx_ring[i].buffer1 = 0;
+ pd->tx_ring[i].buffer2 = 0;
+ }
+ pd->tx_ring[TX_RING_SIZE - 1].length = TDES1_TER_;
+ wmb();
+
+ pd->tx_ring_head = 0;
+ pd->tx_ring_tail = 0;
+
+ smsc9420_reg_write(pd, TX_BASE_ADDR, pd->tx_dma_addr);
+ smsc9420_pci_flush_write(pd);
+
+ return 0;
+}
+
+static int smsc9420_alloc_rx_ring(struct smsc9420_pdata *pd)
+{
+ int i;
+
+ BUG_ON(!pd->rx_ring);
+
+ pd->rx_buffers = kmalloc((sizeof(struct smsc9420_ring_info) *
+ RX_RING_SIZE), GFP_KERNEL);
+ if (pd->rx_buffers == NULL) {
+ smsc_warn(IFUP, "Failed to allocated rx_buffers");
+ goto out;
+ }
+
+ /* initialize the rx ring */
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ pd->rx_ring[i].status = 0;
+ pd->rx_ring[i].length = PKT_BUF_SZ;
+ pd->rx_ring[i].buffer2 = 0;
+ pd->rx_buffers[i].skb = NULL;
+ pd->rx_buffers[i].mapping = 0;
+ }
+ pd->rx_ring[RX_RING_SIZE - 1].length = (PKT_BUF_SZ | RDES1_RER_);
+
+ /* now allocate the entire ring of skbs */
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ if (smsc9420_alloc_rx_buffer(pd, i)) {
+ smsc_warn(IFUP, "failed to allocate rx skb %d", i);
+ goto out_free_rx_skbs;
+ }
+ }
+
+ pd->rx_ring_head = 0;
+ pd->rx_ring_tail = 0;
+
+ smsc9420_reg_write(pd, VLAN1, ETH_P_8021Q);
+ smsc_dbg(IFUP, "VLAN1 = 0x%08x", smsc9420_reg_read(pd, VLAN1));
+
+ if (pd->rx_csum) {
+ /* Enable RX COE */
+ u32 coe = smsc9420_reg_read(pd, COE_CR) | RX_COE_EN;
+ smsc9420_reg_write(pd, COE_CR, coe);
+ smsc_dbg(IFUP, "COE_CR = 0x%08x", coe);
+ }
+
+ smsc9420_reg_write(pd, RX_BASE_ADDR, pd->rx_dma_addr);
+ smsc9420_pci_flush_write(pd);
+
+ return 0;
+
+out_free_rx_skbs:
+ smsc9420_free_rx_ring(pd);
+out:
+ return -ENOMEM;
+}
+
+static int smsc9420_open(struct net_device *dev)
+{
+ struct smsc9420_pdata *pd;
+ u32 bus_mode, mac_cr, dmac_control, int_cfg, dma_intr_ena, int_ctl;
+ 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;
+ goto out_0;
+ }
+
+ netif_carrier_off(dev);
+
+ /* disable, mask and acknowlege all interrupts */
+ spin_lock_irqsave(&pd->int_lock, flags);
+ int_cfg = smsc9420_reg_read(pd, INT_CFG) & (~INT_CFG_IRQ_EN_);
+ smsc9420_reg_write(pd, INT_CFG, int_cfg);
+ smsc9420_reg_write(pd, INT_CTL, 0);
+ spin_unlock_irqrestore(&pd->int_lock, flags);
+ smsc9420_reg_write(pd, DMAC_INTR_ENA, 0);
+ 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 = -ENODEV;
+ goto out_0;
+ }
+
+ smsc9420_dmac_soft_reset(pd);
+
+ /* make sure MAC_CR is sane */
+ smsc9420_reg_write(pd, MAC_CR, 0);
+
+ smsc9420_set_mac_address(dev);
+
+ /* Configure GPIO pins to drive LEDs */
+ smsc9420_reg_write(pd, GPIO_CFG,
+ (GPIO_CFG_LED_3_ | GPIO_CFG_LED_2_ | GPIO_CFG_LED_1_));
+
+ bus_mode = BUS_MODE_DMA_BURST_LENGTH_16;
+
+#ifdef __BIG_ENDIAN
+ bus_mode |= BUS_MODE_DBO_;
+#endif
+
+ smsc9420_reg_write(pd, BUS_MODE, bus_mode);
+
+ smsc9420_pci_flush_write(pd);
+
+ /* set bus master bridge arbitration priority for Rx and TX DMA */
+ smsc9420_reg_write(pd, BUS_CFG, BUS_CFG_RXTXWEIGHT_4_1);
+
+ smsc9420_reg_write(pd, DMAC_CONTROL,
+ (DMAC_CONTROL_SF_ | DMAC_CONTROL_OSF_));
+
+ smsc9420_pci_flush_write(pd);
+
+ /* test the IRQ connection to the ISR */
+ smsc_dbg(IFUP, "Testing ISR using IRQ %d", dev->irq);
+
+ spin_lock_irqsave(&pd->int_lock, flags);
+ /* configure interrupt deassertion timer and enable interrupts */
+ int_cfg = smsc9420_reg_read(pd, INT_CFG) | INT_CFG_IRQ_EN_;
+ int_cfg &= ~(INT_CFG_INT_DEAS_MASK);
+ int_cfg |= (INT_DEAS_TIME & INT_CFG_INT_DEAS_MASK);
+ smsc9420_reg_write(pd, INT_CFG, int_cfg);
+
+ /* unmask software interrupt */
+ int_ctl = smsc9420_reg_read(pd, INT_CTL) | INT_CTL_SW_INT_EN_;
+ smsc9420_reg_write(pd, INT_CTL, int_ctl);
+ spin_unlock_irqrestore(&pd->int_lock, flags);
+ smsc9420_pci_flush_write(pd);
+
+ timeout = 1000;
+ pd->software_irq_signal = false;
+ smp_wmb();
+ while (timeout--) {
+ if (pd->software_irq_signal)
+ break;
+ msleep(1);
+ }
+
+ /* disable interrupts */
+ spin_lock_irqsave(&pd->int_lock, flags);
+ int_cfg = smsc9420_reg_read(pd, INT_CFG) & (~INT_CFG_IRQ_EN_);
+ smsc9420_reg_write(pd, INT_CFG, int_cfg);
+ spin_unlock_irqrestore(&pd->int_lock, flags);
+
+ if (!pd->software_irq_signal) {
+ smsc_warn(IFUP, "ISR failed signaling test");
+ result = -ENODEV;
+ goto out_free_irq_1;
+ }
+
+ smsc_dbg(IFUP, "ISR passed test using IRQ %d", dev->irq);
+
+ result = smsc9420_alloc_tx_ring(pd);
+ if (result) {
+ smsc_warn(IFUP, "Failed to Initialize tx dma ring");
+ result = -ENOMEM;
+ goto out_free_irq_1;
+ }
+
+ result = smsc9420_alloc_rx_ring(pd);
+ if (result) {
+ smsc_warn(IFUP, "Failed to Initialize rx dma ring");
+ result = -ENOMEM;
+ goto out_free_tx_ring_2;
+ }
+
+ result = smsc9420_mii_init(dev);
+ if (result) {
+ smsc_warn(IFUP, "Failed to initialize Phy");
+ result = -ENODEV;
+ goto out_free_rx_ring_3;
+ }
+
+ /* Bring the PHY up */
+ phy_start(pd->phy_dev);
+
+ napi_enable(&pd->napi);
+
+ /* start tx and rx */
+ mac_cr = smsc9420_reg_read(pd, MAC_CR) | MAC_CR_TXEN_ | MAC_CR_RXEN_;
+ smsc9420_reg_write(pd, MAC_CR, mac_cr);
+
+ dmac_control = smsc9420_reg_read(pd, DMAC_CONTROL);
+ dmac_control |= DMAC_CONTROL_ST_ | DMAC_CONTROL_SR_;
+ smsc9420_reg_write(pd, DMAC_CONTROL, dmac_control);
+ smsc9420_pci_flush_write(pd);
+
+ dma_intr_ena = smsc9420_reg_read(pd, DMAC_INTR_ENA);
+ dma_intr_ena |=
+ (DMAC_INTR_ENA_TX_ | DMAC_INTR_ENA_RX_ | DMAC_INTR_ENA_NIS_);
+ smsc9420_reg_write(pd, DMAC_INTR_ENA, dma_intr_ena);
+ smsc9420_pci_flush_write(pd);
+
+ netif_wake_queue(dev);
+
+ smsc9420_reg_write(pd, RX_POLL_DEMAND, 1);
+
+ /* enable interrupts */
+ spin_lock_irqsave(&pd->int_lock, flags);
+ int_cfg = smsc9420_reg_read(pd, INT_CFG) | INT_CFG_IRQ_EN_;
+ smsc9420_reg_write(pd, INT_CFG, int_cfg);
+ spin_unlock_irqrestore(&pd->int_lock, flags);
+
+ return 0;
+
+out_free_rx_ring_3:
+ smsc9420_free_rx_ring(pd);
+out_free_tx_ring_2:
+ smsc9420_free_tx_ring(pd);
+out_free_irq_1:
+ free_irq(dev->irq, pd);
+out_0:
+ return result;
+}
+
+#ifdef CONFIG_PM
+
+static int smsc9420_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct smsc9420_pdata *pd = netdev_priv(dev);
+ u32 int_cfg;
+ ulong flags;
+
+ /* disable interrupts */
+ spin_lock_irqsave(&pd->int_lock, flags);
+ int_cfg = smsc9420_reg_read(pd, INT_CFG) & (~INT_CFG_IRQ_EN_);
+ smsc9420_reg_write(pd, INT_CFG, int_cfg);
+ spin_unlock_irqrestore(&pd->int_lock, flags);
+
+ if (netif_running(dev)) {
+ netif_tx_disable(dev);
+ smsc9420_stop_tx(pd);
+ smsc9420_free_tx_ring(pd);
+
+ napi_disable(&pd->napi);
+ smsc9420_stop_rx(pd);
+ smsc9420_free_rx_ring(pd);
+
+ free_irq(dev->irq, pd);
+
+ netif_device_detach(dev);
+ }
+
+ pci_save_state(pdev);
+ pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ return 0;
+}
+
+static int smsc9420_resume(struct pci_dev *pdev)
+{
+ struct net_device *dev = pci_get_drvdata(pdev);
+ struct smsc9420_pdata *pd = netdev_priv(dev);
+ int err;
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_restore_state(pdev);
+
+ err = pci_enable_device(pdev);
+ if (err)
+ return err;
+
+ pci_set_master(pdev);
+
+ err = pci_enable_wake(pdev, 0, 0);
+ if (err)
+ smsc_warn(IFUP, "pci_enable_wake failed: %d", err);
+
+ if (netif_running(dev)) {
+ err = smsc9420_open(dev);
+ netif_device_attach(dev);
+ }
+ return err;
+}
+
+#endif /* CONFIG_PM */
+
+static const struct net_device_ops smsc9420_netdev_ops = {
+ .ndo_open = smsc9420_open,
+ .ndo_stop = smsc9420_stop,
+ .ndo_start_xmit = smsc9420_hard_start_xmit,
+ .ndo_get_stats = smsc9420_get_stats,
+ .ndo_set_multicast_list = smsc9420_set_multicast_list,
+ .ndo_do_ioctl = smsc9420_do_ioctl,
+ .ndo_validate_addr = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = smsc9420_poll_controller,
+#endif /* CONFIG_NET_POLL_CONTROLLER */
+};
+
+static int __devinit
+smsc9420_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct net_device *dev;
+ struct smsc9420_pdata *pd;
+ void __iomem *virt_addr;
+ int result = 0;
+ u32 id_rev;
+
+ printk(KERN_INFO DRV_DESCRIPTION " version " DRV_VERSION "\n");
+
+ /* First do the PCI initialisation */
+ result = pci_enable_device(pdev);
+ if (unlikely(result)) {
+ printk(KERN_ERR "Cannot enable smsc9420\n");
+ goto out_0;
+ }
+
+ pci_set_master(pdev);
+
+ dev = alloc_etherdev(sizeof(*pd));
+ if (!dev) {
+ printk(KERN_ERR "ether device alloc failed\n");
+ goto out_disable_pci_device_1;
+ }
+
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ if (!(pci_resource_flags(pdev, SMSC_BAR) & IORESOURCE_MEM)) {
+ printk(KERN_ERR "Cannot find PCI device base address\n");
+ goto out_free_netdev_2;
+ }
+
+ if ((pci_request_regions(pdev, DRV_NAME))) {
+ printk(KERN_ERR "Cannot obtain PCI resources, aborting.\n");
+ goto out_free_netdev_2;
+ }
+
+ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
+ printk(KERN_ERR "No usable DMA configuration, aborting.\n");
+ goto out_free_regions_3;
+ }
+
+ virt_addr = ioremap(pci_resource_start(pdev, SMSC_BAR),
+ pci_resource_len(pdev, SMSC_BAR));
+ if (!virt_addr) {
+ printk(KERN_ERR "Cannot map device registers, aborting.\n");
+ goto out_free_regions_3;
+ }
+
+ /* 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 */
+ pd->rx_ring = pci_alloc_consistent(pdev,
+ sizeof(struct smsc9420_dma_desc) * RX_RING_SIZE +
+ sizeof(struct smsc9420_dma_desc) * TX_RING_SIZE,
+ &pd->rx_dma_addr);
+
+ if (!pd->rx_ring)
+ goto out_free_io_4;
+
+ /* descriptors are aligned due to the nature of pci_alloc_consistent */
+ pd->tx_ring = (struct smsc9420_dma_desc *)
+ (pd->rx_ring + RX_RING_SIZE);
+ pd->tx_dma_addr = pd->rx_dma_addr +
+ sizeof(struct smsc9420_dma_desc) * RX_RING_SIZE;
+
+ pd->pdev = pdev;
+ pd->dev = dev;
+ pd->base_addr = virt_addr;
+ pd->msg_enable = smsc_debug;
+ pd->rx_csum = true;
+
+ smsc_dbg(PROBE, "lan_base=0x%08lx", (ulong)virt_addr);
+
+ id_rev = smsc9420_reg_read(pd, ID_REV);
+ switch (id_rev & 0xFFFF0000) {
+ case 0x94200000:
+ smsc_info(PROBE, "LAN9420 identified, ID_REV=0x%08X", id_rev);
+ break;
+ default:
+ smsc_warn(PROBE, "LAN9420 NOT identified");
+ smsc_warn(PROBE, "ID_REV=0x%08X", id_rev);
+ goto out_free_dmadesc_5;
+ }
+
+ smsc9420_dmac_soft_reset(pd);
+ smsc9420_eeprom_reload(pd);
+ smsc9420_check_mac_address(dev);
+
+ 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);
+
+ result = register_netdev(dev);
+ if (result) {
+ smsc_warn(PROBE, "error %i registering device", result);
+ goto out_free_dmadesc_5;
+ }
+
+ pci_set_drvdata(pdev, dev);
+
+ spin_lock_init(&pd->int_lock);
+ spin_lock_init(&pd->phy_lock);
+
+ dev_info(&dev->dev, "MAC Address: %pM\n", dev->dev_addr);
+
+ return 0;
+
+out_free_dmadesc_5:
+ pci_free_consistent(pdev, sizeof(struct smsc9420_dma_desc) *
+ (RX_RING_SIZE + TX_RING_SIZE), pd->rx_ring, pd->rx_dma_addr);
+out_free_io_4:
+ iounmap(virt_addr - LAN9420_CPSR_ENDIAN_OFFSET);
+out_free_regions_3:
+ pci_release_regions(pdev);
+out_free_netdev_2:
+ free_netdev(dev);
+out_disable_pci_device_1:
+ pci_disable_device(pdev);
+out_0:
+ return -ENODEV;
+}
+
+static void __devexit smsc9420_remove(struct pci_dev *pdev)
+{
+ struct net_device *dev;
+ struct smsc9420_pdata *pd;
+
+ dev = pci_get_drvdata(pdev);
+ if (!dev)
+ return;
+
+ pci_set_drvdata(pdev, NULL);
+
+ pd = netdev_priv(dev);
+ unregister_netdev(dev);
+
+ /* tx_buffers and rx_buffers are freed in stop */
+ BUG_ON(pd->tx_buffers);
+ BUG_ON(pd->rx_buffers);
+
+ BUG_ON(!pd->tx_ring);
+ BUG_ON(!pd->rx_ring);
+
+ 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);
+ pci_release_regions(pdev);
+ free_netdev(dev);
+ pci_disable_device(pdev);
+}
+
+static struct pci_driver smsc9420_driver = {
+ .name = DRV_NAME,
+ .id_table = smsc9420_id_table,
+ .probe = smsc9420_probe,
+ .remove = __devexit_p(smsc9420_remove),
+#ifdef CONFIG_PM
+ .suspend = smsc9420_suspend,
+ .resume = smsc9420_resume,
+#endif /* CONFIG_PM */
+};
+
+static int __init smsc9420_init_module(void)
+{
+ smsc_debug = netif_msg_init(debug, SMSC_MSG_DEFAULT);
+
+ return pci_register_driver(&smsc9420_driver);
+}
+
+static void __exit smsc9420_exit_module(void)
+{
+ pci_unregister_driver(&smsc9420_driver);
+}
+
+module_init(smsc9420_init_module);
+module_exit(smsc9420_exit_module);
diff --git a/drivers/net/smsc9420.h b/drivers/net/smsc9420.h
new file mode 100644
index 000000000000..69c351f93f86
--- /dev/null
+++ b/drivers/net/smsc9420.h
@@ -0,0 +1,275 @@
+ /***************************************************************************
+ *
+ * Copyright (C) 2007,2008 SMSC
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ ***************************************************************************
+ */
+
+#ifndef _SMSC9420_H
+#define _SMSC9420_H
+
+#define TX_RING_SIZE (32)
+#define RX_RING_SIZE (128)
+
+/* interrupt deassertion in multiples of 10us */
+#define INT_DEAS_TIME (50)
+
+#define NAPI_WEIGHT (64)
+#define SMSC_BAR (3)
+
+#ifdef __BIG_ENDIAN
+/* Register set is duplicated for BE at an offset of 0x200 */
+#define LAN9420_CPSR_ENDIAN_OFFSET (0x200)
+#else
+#define LAN9420_CPSR_ENDIAN_OFFSET (0)
+#endif
+
+#define PCI_VENDOR_ID_9420 (0x1055)
+#define PCI_DEVICE_ID_9420 (0xE420)
+
+#define LAN_REGISTER_EXTENT (0x400)
+
+#define SMSC9420_EEPROM_SIZE ((u32)11)
+
+#define PKT_BUF_SZ (VLAN_ETH_FRAME_LEN + NET_IP_ALIGN + 4)
+
+/***********************************************/
+/* DMA Controller Control and Status Registers */
+/***********************************************/
+#define BUS_MODE (0x00)
+#define BUS_MODE_SWR_ (BIT(0))
+#define BUS_MODE_DMA_BURST_LENGTH_1 (BIT(8))
+#define BUS_MODE_DMA_BURST_LENGTH_2 (BIT(9))
+#define BUS_MODE_DMA_BURST_LENGTH_4 (BIT(10))
+#define BUS_MODE_DMA_BURST_LENGTH_8 (BIT(11))
+#define BUS_MODE_DMA_BURST_LENGTH_16 (BIT(12))
+#define BUS_MODE_DMA_BURST_LENGTH_32 (BIT(13))
+#define BUS_MODE_DBO_ (BIT(20))
+
+#define TX_POLL_DEMAND (0x04)
+
+#define RX_POLL_DEMAND (0x08)
+
+#define RX_BASE_ADDR (0x0C)
+
+#define TX_BASE_ADDR (0x10)
+
+#define DMAC_STATUS (0x14)
+#define DMAC_STS_TS_ (7 << 20)
+#define DMAC_STS_RS_ (7 << 17)
+#define DMAC_STS_NIS_ (BIT(16))
+#define DMAC_STS_AIS_ (BIT(15))
+#define DMAC_STS_RWT_ (BIT(9))
+#define DMAC_STS_RXPS_ (BIT(8))
+#define DMAC_STS_RXBU_ (BIT(7))
+#define DMAC_STS_RX_ (BIT(6))
+#define DMAC_STS_TXUNF_ (BIT(5))
+#define DMAC_STS_TXBU_ (BIT(2))
+#define DMAC_STS_TXPS_ (BIT(1))
+#define DMAC_STS_TX_ (BIT(0))
+
+#define DMAC_CONTROL (0x18)
+#define DMAC_CONTROL_TTM_ (BIT(22))
+#define DMAC_CONTROL_SF_ (BIT(21))
+#define DMAC_CONTROL_ST_ (BIT(13))
+#define DMAC_CONTROL_OSF_ (BIT(2))
+#define DMAC_CONTROL_SR_ (BIT(1))
+
+#define DMAC_INTR_ENA (0x1C)
+#define DMAC_INTR_ENA_NIS_ (BIT(16))
+#define DMAC_INTR_ENA_AIS_ (BIT(15))
+#define DMAC_INTR_ENA_RWT_ (BIT(9))
+#define DMAC_INTR_ENA_RXPS_ (BIT(8))
+#define DMAC_INTR_ENA_RXBU_ (BIT(7))
+#define DMAC_INTR_ENA_RX_ (BIT(6))
+#define DMAC_INTR_ENA_TXBU_ (BIT(2))
+#define DMAC_INTR_ENA_TXPS_ (BIT(1))
+#define DMAC_INTR_ENA_TX_ (BIT(0))
+
+#define MISS_FRAME_CNTR (0x20)
+
+#define TX_BUFF_ADDR (0x50)
+
+#define RX_BUFF_ADDR (0x54)
+
+/* Transmit Descriptor Bit Defs */
+#define TDES0_OWN_ (0x80000000)
+#define TDES0_ERROR_SUMMARY_ (0x00008000)
+#define TDES0_LOSS_OF_CARRIER_ (0x00000800)
+#define TDES0_NO_CARRIER_ (0x00000400)
+#define TDES0_LATE_COLLISION_ (0x00000200)
+#define TDES0_EXCESSIVE_COLLISIONS_ (0x00000100)
+#define TDES0_HEARTBEAT_FAIL_ (0x00000080)
+#define TDES0_COLLISION_COUNT_MASK_ (0x00000078)
+#define TDES0_COLLISION_COUNT_SHFT_ (3)
+#define TDES0_EXCESSIVE_DEFERRAL_ (0x00000004)
+#define TDES0_DEFERRED_ (0x00000001)
+
+#define TDES1_IC_ 0x80000000
+#define TDES1_LS_ 0x40000000
+#define TDES1_FS_ 0x20000000
+#define TDES1_TXCSEN_ 0x08000000
+#define TDES1_TER_ (BIT(25))
+#define TDES1_TCH_ 0x01000000
+
+/* Receive Descriptor 0 Bit Defs */
+#define RDES0_OWN_ (0x80000000)
+#define RDES0_FRAME_LENGTH_MASK_ (0x07FF0000)
+#define RDES0_FRAME_LENGTH_SHFT_ (16)
+#define RDES0_ERROR_SUMMARY_ (0x00008000)
+#define RDES0_DESCRIPTOR_ERROR_ (0x00004000)
+#define RDES0_LENGTH_ERROR_ (0x00001000)
+#define RDES0_RUNT_FRAME_ (0x00000800)
+#define RDES0_MULTICAST_FRAME_ (0x00000400)
+#define RDES0_FIRST_DESCRIPTOR_ (0x00000200)
+#define RDES0_LAST_DESCRIPTOR_ (0x00000100)
+#define RDES0_FRAME_TOO_LONG_ (0x00000080)
+#define RDES0_COLLISION_SEEN_ (0x00000040)
+#define RDES0_FRAME_TYPE_ (0x00000020)
+#define RDES0_WATCHDOG_TIMEOUT_ (0x00000010)
+#define RDES0_MII_ERROR_ (0x00000008)
+#define RDES0_DRIBBLING_BIT_ (0x00000004)
+#define RDES0_CRC_ERROR_ (0x00000002)
+
+/* Receive Descriptor 1 Bit Defs */
+#define RDES1_RER_ (0x02000000)
+
+/***********************************************/
+/* MAC Control and Status Registers */
+/***********************************************/
+#define MAC_CR (0x80)
+#define MAC_CR_RXALL_ (0x80000000)
+#define MAC_CR_DIS_RXOWN_ (0x00800000)
+#define MAC_CR_LOOPBK_ (0x00200000)
+#define MAC_CR_FDPX_ (0x00100000)
+#define MAC_CR_MCPAS_ (0x00080000)
+#define MAC_CR_PRMS_ (0x00040000)
+#define MAC_CR_INVFILT_ (0x00020000)
+#define MAC_CR_PASSBAD_ (0x00010000)
+#define MAC_CR_HFILT_ (0x00008000)
+#define MAC_CR_HPFILT_ (0x00002000)
+#define MAC_CR_LCOLL_ (0x00001000)
+#define MAC_CR_DIS_BCAST_ (0x00000800)
+#define MAC_CR_DIS_RTRY_ (0x00000400)
+#define MAC_CR_PADSTR_ (0x00000100)
+#define MAC_CR_BOLMT_MSK (0x000000C0)
+#define MAC_CR_MFCHK_ (0x00000020)
+#define MAC_CR_TXEN_ (0x00000008)
+#define MAC_CR_RXEN_ (0x00000004)
+
+#define ADDRH (0x84)
+
+#define ADDRL (0x88)
+
+#define HASHH (0x8C)
+
+#define HASHL (0x90)
+
+#define MII_ACCESS (0x94)
+#define MII_ACCESS_MII_BUSY_ (0x00000001)
+#define MII_ACCESS_MII_WRITE_ (0x00000002)
+#define MII_ACCESS_MII_READ_ (0x00000000)
+#define MII_ACCESS_INDX_MSK_ (0x000007C0)
+#define MII_ACCESS_PHYADDR_MSK_ (0x0000F8C0)
+#define MII_ACCESS_INDX_SHFT_CNT (6)
+#define MII_ACCESS_PHYADDR_SHFT_CNT (11)
+
+#define MII_DATA (0x98)
+
+#define FLOW (0x9C)
+
+#define VLAN1 (0xA0)
+
+#define VLAN2 (0xA4)
+
+#define WUFF (0xA8)
+
+#define WUCSR (0xAC)
+
+#define COE_CR (0xB0)
+#define TX_COE_EN (0x00010000)
+#define RX_COE_MODE (0x00000002)
+#define RX_COE_EN (0x00000001)
+
+/***********************************************/
+/* System Control and Status Registers */
+/***********************************************/
+#define ID_REV (0xC0)
+
+#define INT_CTL (0xC4)
+#define INT_CTL_SW_INT_EN_ (0x00008000)
+#define INT_CTL_SBERR_INT_EN_ (1 << 12)
+#define INT_CTL_MBERR_INT_EN_ (1 << 13)
+#define INT_CTL_GPT_INT_EN_ (0x00000008)
+#define INT_CTL_PHY_INT_EN_ (0x00000004)
+#define INT_CTL_WAKE_INT_EN_ (0x00000002)
+
+#define INT_STAT (0xC8)
+#define INT_STAT_SW_INT_ (1 << 15)
+#define INT_STAT_MBERR_INT_ (1 << 13)
+#define INT_STAT_SBERR_INT_ (1 << 12)
+#define INT_STAT_GPT_INT_ (1 << 3)
+#define INT_STAT_PHY_INT_ (0x00000004)
+#define INT_STAT_WAKE_INT_ (0x00000002)
+#define INT_STAT_DMAC_INT_ (0x00000001)
+
+#define INT_CFG (0xCC)
+#define INT_CFG_IRQ_INT_ (0x00080000)
+#define INT_CFG_IRQ_EN_ (0x00040000)
+#define INT_CFG_INT_DEAS_CLR_ (0x00000200)
+#define INT_CFG_INT_DEAS_MASK (0x000000FF)
+
+#define GPIO_CFG (0xD0)
+#define GPIO_CFG_LED_3_ (0x40000000)
+#define GPIO_CFG_LED_2_ (0x20000000)
+#define GPIO_CFG_LED_1_ (0x10000000)
+#define GPIO_CFG_EEPR_EN_ (0x00700000)
+
+#define GPT_CFG (0xD4)
+#define GPT_CFG_TIMER_EN_ (0x20000000)
+
+#define GPT_CNT (0xD8)
+
+#define BUS_CFG (0xDC)
+#define BUS_CFG_RXTXWEIGHT_1_1 (0 << 25)
+#define BUS_CFG_RXTXWEIGHT_2_1 (1 << 25)
+#define BUS_CFG_RXTXWEIGHT_3_1 (2 << 25)
+#define BUS_CFG_RXTXWEIGHT_4_1 (3 << 25)
+
+#define PMT_CTRL (0xE0)
+
+#define FREE_RUN (0xF4)
+
+#define E2P_CMD (0xF8)
+#define E2P_CMD_EPC_BUSY_ (0x80000000)
+#define E2P_CMD_EPC_CMD_ (0x70000000)
+#define E2P_CMD_EPC_CMD_READ_ (0x00000000)
+#define E2P_CMD_EPC_CMD_EWDS_ (0x10000000)
+#define E2P_CMD_EPC_CMD_EWEN_ (0x20000000)
+#define E2P_CMD_EPC_CMD_WRITE_ (0x30000000)
+#define E2P_CMD_EPC_CMD_WRAL_ (0x40000000)
+#define E2P_CMD_EPC_CMD_ERASE_ (0x50000000)
+#define E2P_CMD_EPC_CMD_ERAL_ (0x60000000)
+#define E2P_CMD_EPC_CMD_RELOAD_ (0x70000000)
+#define E2P_CMD_EPC_TIMEOUT_ (0x00000200)
+#define E2P_CMD_MAC_ADDR_LOADED_ (0x00000100)
+#define E2P_CMD_EPC_ADDR_ (0x000000FF)
+
+#define E2P_DATA (0xFC)
+#define E2P_DATA_EEPROM_DATA_ (0x000000FF)
+
+#endif /* _SMSC9420_H */
diff --git a/drivers/net/sonic.c b/drivers/net/sonic.c
index 8069f3e32d83..211e805c1223 100644
--- a/drivers/net/sonic.c
+++ b/drivers/net/sonic.c
@@ -450,7 +450,6 @@ static void sonic_rx(struct net_device *dev)
skb_trim(used_skb, pkt_len);
used_skb->protocol = eth_type_trans(used_skb, dev);
netif_rx(used_skb);
- dev->last_rx = jiffies;
lp->stats.rx_packets++;
lp->stats.rx_bytes += pkt_len;
diff --git a/drivers/net/sonic.h b/drivers/net/sonic.h
index 7db13e4a7ea5..07091dd27e5d 100644
--- a/drivers/net/sonic.h
+++ b/drivers/net/sonic.h
@@ -371,7 +371,7 @@ static inline __u16 sonic_buf_get(void* base, int bitmode,
static inline void sonic_cda_put(struct net_device* dev, int entry,
int offset, __u16 val)
{
- struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ struct sonic_local *lp = netdev_priv(dev);
sonic_buf_put(lp->cda, lp->dma_bitmode,
(entry * SIZEOF_SONIC_CD) + offset, val);
}
@@ -379,27 +379,27 @@ static inline void sonic_cda_put(struct net_device* dev, int entry,
static inline __u16 sonic_cda_get(struct net_device* dev, int entry,
int offset)
{
- struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ struct sonic_local *lp = netdev_priv(dev);
return sonic_buf_get(lp->cda, lp->dma_bitmode,
(entry * SIZEOF_SONIC_CD) + offset);
}
static inline void sonic_set_cam_enable(struct net_device* dev, __u16 val)
{
- struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ struct sonic_local *lp = netdev_priv(dev);
sonic_buf_put(lp->cda, lp->dma_bitmode, SONIC_CDA_CAM_ENABLE, val);
}
static inline __u16 sonic_get_cam_enable(struct net_device* dev)
{
- struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ struct sonic_local *lp = netdev_priv(dev);
return sonic_buf_get(lp->cda, lp->dma_bitmode, SONIC_CDA_CAM_ENABLE);
}
static inline void sonic_tda_put(struct net_device* dev, int entry,
int offset, __u16 val)
{
- struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ struct sonic_local *lp = netdev_priv(dev);
sonic_buf_put(lp->tda, lp->dma_bitmode,
(entry * SIZEOF_SONIC_TD) + offset, val);
}
@@ -407,7 +407,7 @@ static inline void sonic_tda_put(struct net_device* dev, int entry,
static inline __u16 sonic_tda_get(struct net_device* dev, int entry,
int offset)
{
- struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ struct sonic_local *lp = netdev_priv(dev);
return sonic_buf_get(lp->tda, lp->dma_bitmode,
(entry * SIZEOF_SONIC_TD) + offset);
}
@@ -415,7 +415,7 @@ static inline __u16 sonic_tda_get(struct net_device* dev, int entry,
static inline void sonic_rda_put(struct net_device* dev, int entry,
int offset, __u16 val)
{
- struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ struct sonic_local *lp = netdev_priv(dev);
sonic_buf_put(lp->rda, lp->dma_bitmode,
(entry * SIZEOF_SONIC_RD) + offset, val);
}
@@ -423,7 +423,7 @@ static inline void sonic_rda_put(struct net_device* dev, int entry,
static inline __u16 sonic_rda_get(struct net_device* dev, int entry,
int offset)
{
- struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ struct sonic_local *lp = netdev_priv(dev);
return sonic_buf_get(lp->rda, lp->dma_bitmode,
(entry * SIZEOF_SONIC_RD) + offset);
}
@@ -431,7 +431,7 @@ static inline __u16 sonic_rda_get(struct net_device* dev, int entry,
static inline void sonic_rra_put(struct net_device* dev, int entry,
int offset, __u16 val)
{
- struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ struct sonic_local *lp = netdev_priv(dev);
sonic_buf_put(lp->rra, lp->dma_bitmode,
(entry * SIZEOF_SONIC_RR) + offset, val);
}
@@ -439,7 +439,7 @@ static inline void sonic_rra_put(struct net_device* dev, int entry,
static inline __u16 sonic_rra_get(struct net_device* dev, int entry,
int offset)
{
- struct sonic_local* lp = (struct sonic_local *) dev->priv;
+ struct sonic_local *lp = netdev_priv(dev);
return sonic_buf_get(lp->rra, lp->dma_bitmode,
(entry * SIZEOF_SONIC_RR) + offset);
}
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 07599b492359..c5c123d3af57 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -789,7 +789,7 @@ spider_net_set_low_watermark(struct spider_net_card *card)
* spider_net_release_tx_chain releases the tx descriptors that spider has
* finished with (if non-brutal) or simply release tx descriptors (if brutal).
* If some other context is calling this function, we return 1 so that we're
- * scheduled again (if we were scheduled) and will not loose initiative.
+ * scheduled again (if we were scheduled) and will not lose initiative.
*/
static int
spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
@@ -1302,7 +1302,7 @@ static int spider_net_poll(struct napi_struct *napi, int budget)
/* if all packets are in the stack, enable interrupts and return 0 */
/* if not, return 1 */
if (packets_done < budget) {
- netif_rx_complete(netdev, napi);
+ netif_rx_complete(napi);
spider_net_rx_irq_on(card);
card->ignore_rx_ramfull = 0;
}
@@ -1529,8 +1529,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg,
spider_net_refill_rx_chain(card);
spider_net_enable_rxdmac(card);
card->num_rx_ints ++;
- netif_rx_schedule(card->netdev,
- &card->napi);
+ netif_rx_schedule(&card->napi);
}
show_error = 0;
break;
@@ -1550,8 +1549,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg,
spider_net_refill_rx_chain(card);
spider_net_enable_rxdmac(card);
card->num_rx_ints ++;
- netif_rx_schedule(card->netdev,
- &card->napi);
+ netif_rx_schedule(&card->napi);
show_error = 0;
break;
@@ -1565,8 +1563,7 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg,
spider_net_refill_rx_chain(card);
spider_net_enable_rxdmac(card);
card->num_rx_ints ++;
- netif_rx_schedule(card->netdev,
- &card->napi);
+ netif_rx_schedule(&card->napi);
show_error = 0;
break;
@@ -1660,11 +1657,11 @@ spider_net_interrupt(int irq, void *ptr)
if (status_reg & SPIDER_NET_RXINT ) {
spider_net_rx_irq_off(card);
- netif_rx_schedule(netdev, &card->napi);
+ netif_rx_schedule(&card->napi);
card->num_rx_ints ++;
}
if (status_reg & SPIDER_NET_TXINT)
- netif_rx_schedule(netdev, &card->napi);
+ netif_rx_schedule(&card->napi);
if (status_reg & SPIDER_NET_LINKINT)
spider_net_link_reset(netdev);
diff --git a/drivers/net/spider_net_ethtool.c b/drivers/net/spider_net_ethtool.c
index 85691d2a0be2..5bae728c3820 100644
--- a/drivers/net/spider_net_ethtool.c
+++ b/drivers/net/spider_net_ethtool.c
@@ -118,7 +118,7 @@ spider_net_ethtool_nway_reset(struct net_device *netdev)
static u32
spider_net_ethtool_get_rx_csum(struct net_device *netdev)
{
- struct spider_net_card *card = netdev->priv;
+ struct spider_net_card *card = netdev_priv(netdev);
return card->options.rx_csum;
}
@@ -126,7 +126,7 @@ spider_net_ethtool_get_rx_csum(struct net_device *netdev)
static int
spider_net_ethtool_set_rx_csum(struct net_device *netdev, u32 n)
{
- struct spider_net_card *card = netdev->priv;
+ struct spider_net_card *card = netdev_priv(netdev);
card->options.rx_csum = n;
return 0;
@@ -137,7 +137,7 @@ static void
spider_net_ethtool_get_ringparam(struct net_device *netdev,
struct ethtool_ringparam *ering)
{
- struct spider_net_card *card = netdev->priv;
+ struct spider_net_card *card = netdev_priv(netdev);
ering->tx_max_pending = SPIDER_NET_TX_DESCRIPTORS_MAX;
ering->tx_pending = card->tx_chain.num_desc;
@@ -158,7 +158,7 @@ static int spider_net_get_sset_count(struct net_device *netdev, int sset)
static void spider_net_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, u64 *data)
{
- struct spider_net_card *card = netdev->priv;
+ struct spider_net_card *card = netdev_priv(netdev);
data[0] = netdev->stats.tx_packets;
data[1] = netdev->stats.tx_bytes;
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
index 1d2ef8f47780..f54ac2389da2 100644
--- a/drivers/net/starfire.c
+++ b/drivers/net/starfire.c
@@ -653,7 +653,6 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
void __iomem *base;
int drv_flags, io_size;
int boguscnt;
- DECLARE_MAC_BUF(mac);
/* when built into the kernel, we only print version if device is found */
#ifndef MODULE
@@ -823,9 +822,9 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
if (register_netdev(dev))
goto err_out_cleardev;
- printk(KERN_INFO "%s: %s at %p, %s, IRQ %d.\n",
+ printk(KERN_INFO "%s: %s at %p, %pM, IRQ %d.\n",
dev->name, netdrv_tbl[chip_idx].name, base,
- print_mac(mac, dev->dev_addr), irq);
+ dev->dev_addr, irq);
if (drv_flags & CanHaveMII) {
int phy, phy_idx = 0;
@@ -881,9 +880,9 @@ static int mdio_read(struct net_device *dev, int phy_id, int location)
void __iomem *mdio_addr = np->base + MIICtrl + (phy_id<<7) + (location<<2);
int result, boguscnt=1000;
/* ??? Should we add a busy-wait here? */
- do
+ do {
result = readl(mdio_addr);
- while ((result & 0xC0000000) != 0x80000000 && --boguscnt > 0);
+ } while ((result & 0xC0000000) != 0x80000000 && --boguscnt > 0);
if (boguscnt == 0)
return 0;
if ((result & 0xffff) == 0xffff)
@@ -1291,8 +1290,8 @@ static irqreturn_t intr_handler(int irq, void *dev_instance)
if (intr_status & (IntrRxDone | IntrRxEmpty)) {
u32 enable;
- if (likely(netif_rx_schedule_prep(dev, &np->napi))) {
- __netif_rx_schedule(dev, &np->napi);
+ if (likely(netif_rx_schedule_prep(&np->napi))) {
+ __netif_rx_schedule(&np->napi);
enable = readl(ioaddr + IntrEnable);
enable &= ~(IntrRxDone | IntrRxEmpty);
writel(enable, ioaddr + IntrEnable);
@@ -1452,12 +1451,8 @@ static int __netdev_rx(struct net_device *dev, int *quota)
#ifndef final_version /* Remove after testing. */
/* You will want this info for the initial debug. */
if (debug > 5) {
- printk(KERN_DEBUG " Rx data " MAC_FMT " " MAC_FMT
- " %2.2x%2.2x.\n",
- skb->data[0], skb->data[1], skb->data[2],
- skb->data[3], skb->data[4], skb->data[5],
- skb->data[6], skb->data[7], skb->data[8],
- skb->data[9], skb->data[10], skb->data[11],
+ printk(KERN_DEBUG " Rx data %pM %pM %2.2x%2.2x.\n",
+ skb->data, skb->data + 6,
skb->data[12], skb->data[13]);
}
#endif
@@ -1501,7 +1496,6 @@ static int __netdev_rx(struct net_device *dev, int *quota)
} else
#endif /* VLAN_SUPPORT */
netif_receive_skb(skb);
- dev->last_rx = jiffies;
np->stats.rx_packets++;
next_rx:
@@ -1509,6 +1503,11 @@ static int __netdev_rx(struct net_device *dev, int *quota)
desc->status = 0;
np->rx_done = (np->rx_done + 1) % DONE_Q_SIZE;
}
+
+ if (*quota == 0) { /* out of rx quota */
+ retcode = 1;
+ goto out;
+ }
writew(np->rx_done, np->base + CompletionQConsumerIdx);
out:
@@ -1536,7 +1535,7 @@ static int netdev_poll(struct napi_struct *napi, int budget)
intr_status = readl(ioaddr + IntrStatus);
} while (intr_status & (IntrRxDone | IntrRxEmpty));
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
intr_status = readl(ioaddr + IntrEnable);
intr_status |= IntrRxDone | IntrRxEmpty;
writel(intr_status, ioaddr + IntrEnable);
diff --git a/drivers/net/stnic.c b/drivers/net/stnic.c
index 2ed0bd596815..87a6b8eabc67 100644
--- a/drivers/net/stnic.c
+++ b/drivers/net/stnic.c
@@ -60,8 +60,6 @@ static byte stnic_eadr[6] =
static struct net_device *stnic_dev;
-static int stnic_open (struct net_device *dev);
-static int stnic_close (struct net_device *dev);
static void stnic_reset (struct net_device *dev);
static void stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr,
int ring_page);
@@ -122,11 +120,7 @@ static int __init stnic_probe(void)
/* Set the base address to point to the NIC, not the "real" base! */
dev->base_addr = 0x1000;
dev->irq = IRQ_STNIC;
- dev->open = &stnic_open;
- dev->stop = &stnic_close;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = ei_poll;
-#endif
+ dev->netdev_ops = &ei_netdev_ops;
/* Snarf the interrupt now. There's no point in waiting since we cannot
share and the board will usually be enabled. */
@@ -168,23 +162,6 @@ static int __init stnic_probe(void)
return 0;
}
-static int
-stnic_open (struct net_device *dev)
-{
-#if 0
- printk (KERN_DEBUG "stnic open\n");
-#endif
- ei_open (dev);
- return 0;
-}
-
-static int
-stnic_close (struct net_device *dev)
-{
- ei_close (dev);
- return 0;
-}
-
static void
stnic_reset (struct net_device *dev)
{
diff --git a/drivers/net/sun3_82586.c b/drivers/net/sun3_82586.c
index e531302d95f5..e0d84772771c 100644
--- a/drivers/net/sun3_82586.c
+++ b/drivers/net/sun3_82586.c
@@ -209,7 +209,7 @@ static int sun3_82586_open(struct net_device *dev)
static int check586(struct net_device *dev,char *where,unsigned size)
{
struct priv pb;
- struct priv *p = /* (struct priv *) dev->priv*/ &pb;
+ struct priv *p = &pb;
char *iscp_addr;
int i;
@@ -247,7 +247,7 @@ static int check586(struct net_device *dev,char *where,unsigned size)
*/
static void alloc586(struct net_device *dev)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
sun3_reset586();
DELAY(1);
@@ -363,17 +363,21 @@ static int __init sun3_82586_probe1(struct net_device *dev,int ioaddr)
goto out;
}
- ((struct priv *) (dev->priv))->memtop = (char *)dvma_btov(dev->mem_start);
- ((struct priv *) (dev->priv))->base = (unsigned long) dvma_btov(0);
+ ((struct priv *)netdev_priv(dev))->memtop =
+ (char *)dvma_btov(dev->mem_start);
+ ((struct priv *)netdev_priv(dev))->base = (unsigned long) dvma_btov(0);
alloc586(dev);
/* set number of receive-buffs according to memsize */
if(size == 0x2000)
- ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_8;
+ ((struct priv *)netdev_priv(dev))->num_recv_buffs =
+ NUM_RECV_BUFFS_8;
else if(size == 0x4000)
- ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16;
+ ((struct priv *)netdev_priv(dev))->num_recv_buffs =
+ NUM_RECV_BUFFS_16;
else
- ((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_32;
+ ((struct priv *)netdev_priv(dev))->num_recv_buffs =
+ NUM_RECV_BUFFS_32;
printk("Memaddr: 0x%lx, Memsize: %d, IRQ %d\n",dev->mem_start,size, dev->irq);
@@ -397,7 +401,7 @@ static int init586(struct net_device *dev)
{
void *ptr;
int i,result=0;
- struct priv *p = (struct priv *) dev->priv;
+ 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;
@@ -631,7 +635,7 @@ 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 = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
memset((char *) rfd,0,sizeof(struct rfd_struct)*(p->num_recv_buffs+rfdadd));
p->rfd_first = rfd;
@@ -683,7 +687,7 @@ static irqreturn_t sun3_82586_interrupt(int irq,void *dev_id)
printk ("sun3_82586-interrupt: irq %d for unknown device.\n",irq);
return IRQ_NONE;
}
- p = (struct priv *) dev->priv;
+ p = netdev_priv(dev);
if(debuglevel > 1)
printk("I");
@@ -753,7 +757,7 @@ static void sun3_82586_rcv_int(struct net_device *dev)
unsigned short totlen;
struct sk_buff *skb;
struct rbd_struct *rbd;
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
if(debuglevel > 0)
printk("R");
@@ -871,7 +875,7 @@ static void sun3_82586_rcv_int(struct net_device *dev)
static void sun3_82586_rnr_int(struct net_device *dev)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
p->stats.rx_errors++;
@@ -895,7 +899,7 @@ static void sun3_82586_rnr_int(struct net_device *dev)
static void sun3_82586_xmt_int(struct net_device *dev)
{
int status;
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
if(debuglevel > 0)
printk("X");
@@ -945,7 +949,7 @@ static void sun3_82586_xmt_int(struct net_device *dev)
static void startrecv586(struct net_device *dev)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
WAIT_4_SCB_CMD();
WAIT_4_SCB_CMD_RUC();
@@ -957,7 +961,7 @@ static void startrecv586(struct net_device *dev)
static void sun3_82586_timeout(struct net_device *dev)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
#ifndef NO_NOPCOMMANDS
if(p->scb->cus & CU_ACTIVE) /* COMMAND-UNIT active? */
{
@@ -999,7 +1003,7 @@ static int sun3_82586_send_packet(struct sk_buff *skb, struct net_device *dev)
#ifndef NO_NOPCOMMANDS
int next_nop;
#endif
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
if(skb->len > XMIT_BUFF_SIZE)
{
@@ -1108,7 +1112,7 @@ static int sun3_82586_send_packet(struct sk_buff *skb, struct net_device *dev)
static struct net_device_stats *sun3_82586_get_stats(struct net_device *dev)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
unsigned short crc,aln,rsc,ovrn;
crc = swab16(p->scb->crc_errs); /* get error-statistic from the ni82586 */
@@ -1171,7 +1175,7 @@ void cleanup_module(void)
*/
void sun3_82586_dump(struct net_device *dev,void *ptr)
{
- struct priv *p = (struct priv *) dev->priv;
+ struct priv *p = netdev_priv(dev);
struct dump_cmd_struct *dump_cmd = (struct dump_cmd_struct *) ptr;
int i;
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index 359452a06c67..4bb8f72c65cc 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -303,7 +303,6 @@ static int __init lance_probe( struct net_device *dev)
static int did_version;
volatile unsigned short *ioaddr_probe;
unsigned short tmp1, tmp2;
- DECLARE_MAC_BUF(mac);
#ifdef CONFIG_SUN3
ioaddr = (unsigned long)ioremap(LANCE_OBIO, PAGE_SIZE);
@@ -379,7 +378,7 @@ static int __init lance_probe( struct net_device *dev)
MEM->init.hwaddr[4] = dev->dev_addr[5];
MEM->init.hwaddr[5] = dev->dev_addr[4];
- printk("%s\n", print_mac(mac, dev->dev_addr));
+ printk("%pM\n", dev->dev_addr);
MEM->init.mode = 0x0000;
MEM->init.filter[0] = 0x00000000;
@@ -824,12 +823,10 @@ static int lance_rx( struct net_device *dev )
#if 0
if (lance_debug >= 3) {
u_char *data = PKTBUF_ADDR(head);
- DECLARE_MAC_BUF(mac);
- DECLARE_MAC_BUF(mac2)
printk("%s: RX pkt %d type 0x%04x"
- " from %s to %s",
+ " from %pM to %pM",
dev->name, lp->new_tx, ((u_short *)data)[6],
- print_mac(mac, &data[6]), print_mac(mac2, data));
+ &data[6], data);
printk(" data %02x %02x %02x %02x %02x %02x %02x %02x "
"len %d at %08x\n",
@@ -852,7 +849,6 @@ static int lance_rx( struct net_device *dev )
skb->protocol = eth_type_trans( skb, dev );
netif_rx( skb );
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
}
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index 018d0fca9422..7f69c7f176c4 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -878,7 +878,6 @@ static void bigmac_rx(struct bigmac *bp)
/* No checksums done by the BigMAC ;-( */
skb->protocol = eth_type_trans(skb, bp->dev);
netif_rx(skb);
- bp->dev->last_rx = jiffies;
bp->enet_stats.rx_packets++;
bp->enet_stats.rx_bytes += len;
next:
@@ -917,7 +916,7 @@ static irqreturn_t bigmac_interrupt(int irq, void *dev_id)
static int bigmac_open(struct net_device *dev)
{
- struct bigmac *bp = (struct bigmac *) dev->priv;
+ struct bigmac *bp = netdev_priv(dev);
int ret;
ret = request_irq(dev->irq, &bigmac_interrupt, IRQF_SHARED, dev->name, bp);
@@ -934,7 +933,7 @@ static int bigmac_open(struct net_device *dev)
static int bigmac_close(struct net_device *dev)
{
- struct bigmac *bp = (struct bigmac *) dev->priv;
+ struct bigmac *bp = netdev_priv(dev);
del_timer(&bp->bigmac_timer);
bp->timer_state = asleep;
@@ -948,7 +947,7 @@ static int bigmac_close(struct net_device *dev)
static void bigmac_tx_timeout(struct net_device *dev)
{
- struct bigmac *bp = (struct bigmac *) dev->priv;
+ struct bigmac *bp = netdev_priv(dev);
bigmac_init_hw(bp, 0);
netif_wake_queue(dev);
@@ -957,7 +956,7 @@ static void bigmac_tx_timeout(struct net_device *dev)
/* Put a packet on the wire. */
static int bigmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct bigmac *bp = (struct bigmac *) dev->priv;
+ struct bigmac *bp = netdev_priv(dev);
int len, entry;
u32 mapping;
@@ -990,7 +989,7 @@ static int bigmac_start_xmit(struct sk_buff *skb, struct net_device *dev)
static struct net_device_stats *bigmac_get_stats(struct net_device *dev)
{
- struct bigmac *bp = (struct bigmac *) dev->priv;
+ struct bigmac *bp = netdev_priv(dev);
bigmac_get_counters(bp, bp->bregs);
return &bp->enet_stats;
@@ -998,7 +997,7 @@ static struct net_device_stats *bigmac_get_stats(struct net_device *dev)
static void bigmac_set_multicast(struct net_device *dev)
{
- struct bigmac *bp = (struct bigmac *) dev->priv;
+ struct bigmac *bp = netdev_priv(dev);
void __iomem *bregs = bp->bregs;
struct dev_mc_list *dmi = dev->mc_list;
char *addrs;
@@ -1061,7 +1060,7 @@ static void bigmac_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *i
static u32 bigmac_get_link(struct net_device *dev)
{
- struct bigmac *bp = dev->priv;
+ struct bigmac *bp = netdev_priv(dev);
spin_lock_irq(&bp->lock);
bp->sw_bmsr = bigmac_tcvr_read(bp, bp->tregs, BIGMAC_BMSR);
@@ -1081,7 +1080,6 @@ static int __devinit bigmac_ether_init(struct of_device *op,
static int version_printed;
struct net_device *dev;
u8 bsizes, bsizes_more;
- DECLARE_MAC_BUF(mac);
struct bigmac *bp;
int i;
@@ -1212,8 +1210,8 @@ static int __devinit bigmac_ether_init(struct of_device *op,
dev_set_drvdata(&bp->bigmac_op->dev, bp);
- printk(KERN_INFO "%s: BigMAC 100baseT Ethernet %s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "%s: BigMAC 100baseT Ethernet %pM\n",
+ dev->name, dev->dev_addr);
return 0;
@@ -1235,7 +1233,7 @@ fail_and_cleanup:
bp->bmac_block,
bp->bblock_dvma);
- /* This also frees the co-located 'dev->priv' */
+ /* This also frees the co-located private data */
free_netdev(dev);
return -ENODEV;
}
diff --git a/drivers/net/sundance.c b/drivers/net/sundance.c
index f860ea150395..698893b92003 100644
--- a/drivers/net/sundance.c
+++ b/drivers/net/sundance.c
@@ -468,7 +468,6 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
int bar = 1;
#endif
int phy, phy_end, phy_idx = 0;
- DECLARE_MAC_BUF(mac);
/* when built into the kernel, we only print version if device is found */
#ifndef MODULE
@@ -547,9 +546,9 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
if (i)
goto err_out_unmap_rx;
- printk(KERN_INFO "%s: %s at %p, %s, IRQ %d.\n",
+ printk(KERN_INFO "%s: %s at %p, %pM, IRQ %d.\n",
dev->name, pci_id_tbl[chip_idx].name, ioaddr,
- print_mac(mac, dev->dev_addr), irq);
+ dev->dev_addr, irq);
np->phys[0] = 1; /* Default setting */
np->mii_preamble_required++;
@@ -1351,7 +1350,6 @@ static void rx_poll(unsigned long data)
skb->protocol = eth_type_trans(skb, dev);
/* Note: checksum -> skb->ip_summed = CHECKSUM_UNNECESSARY; */
netif_rx(skb);
- dev->last_rx = jiffies;
}
entry = (entry + 1) % RX_RING_SIZE;
received++;
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c
index fed7eba65ead..8a7460412482 100644
--- a/drivers/net/sungem.c
+++ b/drivers/net/sungem.c
@@ -164,7 +164,7 @@ static u16 __phy_read(struct gem *gp, int phy_addr, int reg)
static inline int _phy_read(struct net_device *dev, int mii_id, int reg)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
return __phy_read(gp, mii_id, reg);
}
@@ -197,7 +197,7 @@ static void __phy_write(struct gem *gp, int phy_addr, int reg, u16 val)
static inline void _phy_write(struct net_device *dev, int mii_id, int reg, int val)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
__phy_write(gp, mii_id, reg, val & 0xffff);
}
@@ -863,7 +863,6 @@ static int gem_rx(struct gem *gp, int work_to_do)
gp->net_stats.rx_packets++;
gp->net_stats.rx_bytes += len;
- gp->dev->last_rx = jiffies;
next:
entry = NEXT_RX(entry);
@@ -922,7 +921,7 @@ static int gem_poll(struct napi_struct *napi, int budget)
gp->status = readl(gp->regs + GREG_STAT);
} while (gp->status & GREG_STAT_NAPI);
- __netif_rx_complete(dev, napi);
+ __netif_rx_complete(napi);
gem_enable_ints(gp);
spin_unlock_irqrestore(&gp->lock, flags);
@@ -933,7 +932,7 @@ static int gem_poll(struct napi_struct *napi, int budget)
static irqreturn_t gem_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
unsigned long flags;
/* Swallow interrupts when shutting the chip down, though
@@ -945,7 +944,7 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id)
spin_lock_irqsave(&gp->lock, flags);
- if (netif_rx_schedule_prep(dev, &gp->napi)) {
+ if (netif_rx_schedule_prep(&gp->napi)) {
u32 gem_status = readl(gp->regs + GREG_STAT);
if (gem_status == 0) {
@@ -955,7 +954,7 @@ static irqreturn_t gem_interrupt(int irq, void *dev_id)
}
gp->status = gem_status;
gem_disable_ints(gp);
- __netif_rx_schedule(dev, &gp->napi);
+ __netif_rx_schedule(&gp->napi);
}
spin_unlock_irqrestore(&gp->lock, flags);
@@ -979,7 +978,7 @@ static void gem_poll_controller(struct net_device *dev)
static void gem_tx_timeout(struct net_device *dev)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
if (!gp->running) {
@@ -1018,7 +1017,7 @@ static __inline__ int gem_intme(int entry)
static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
int entry;
u64 ctrl;
unsigned long flags;
@@ -2208,7 +2207,7 @@ static void gem_stop_phy(struct gem *gp, int wol)
static int gem_do_start(struct net_device *dev)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
unsigned long flags;
spin_lock_irqsave(&gp->lock, flags);
@@ -2255,7 +2254,7 @@ static int gem_do_start(struct net_device *dev)
static void gem_do_stop(struct net_device *dev, int wol)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
unsigned long flags;
spin_lock_irqsave(&gp->lock, flags);
@@ -2330,7 +2329,7 @@ static void gem_reset_task(struct work_struct *work)
static int gem_open(struct net_device *dev)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
int rc = 0;
mutex_lock(&gp->pm_mutex);
@@ -2349,7 +2348,7 @@ static int gem_open(struct net_device *dev)
static int gem_close(struct net_device *dev)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
mutex_lock(&gp->pm_mutex);
@@ -2368,7 +2367,7 @@ static int gem_close(struct net_device *dev)
static int gem_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
unsigned long flags;
mutex_lock(&gp->pm_mutex);
@@ -2432,7 +2431,7 @@ static int gem_suspend(struct pci_dev *pdev, pm_message_t state)
static int gem_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
unsigned long flags;
printk(KERN_INFO "%s: resuming\n", dev->name);
@@ -2506,7 +2505,7 @@ static int gem_resume(struct pci_dev *pdev)
static struct net_device_stats *gem_get_stats(struct net_device *dev)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
struct net_device_stats *stats = &gp->net_stats;
spin_lock_irq(&gp->lock);
@@ -2542,7 +2541,7 @@ static struct net_device_stats *gem_get_stats(struct net_device *dev)
static int gem_set_mac_address(struct net_device *dev, void *addr)
{
struct sockaddr *macaddr = (struct sockaddr *) addr;
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
unsigned char *e = &dev->dev_addr[0];
if (!is_valid_ether_addr(macaddr->sa_data))
@@ -2570,7 +2569,7 @@ static int gem_set_mac_address(struct net_device *dev, void *addr)
static void gem_set_multicast(struct net_device *dev)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
u32 rxcfg, rxcfg_new;
int limit = 10000;
@@ -2619,7 +2618,7 @@ static void gem_set_multicast(struct net_device *dev)
static int gem_change_mtu(struct net_device *dev, int new_mtu)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
if (new_mtu < GEM_MIN_MTU || new_mtu > GEM_MAX_MTU)
return -EINVAL;
@@ -2650,7 +2649,7 @@ static int gem_change_mtu(struct net_device *dev, int new_mtu)
static void gem_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
strcpy(info->driver, DRV_NAME);
strcpy(info->version, DRV_VERSION);
@@ -2659,7 +2658,7 @@ static void gem_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info
static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
if (gp->phy_type == phy_mii_mdio0 ||
gp->phy_type == phy_mii_mdio1) {
@@ -2720,7 +2719,7 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static int gem_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
/* Verify the settings we care about. */
if (cmd->autoneg != AUTONEG_ENABLE &&
@@ -2751,7 +2750,7 @@ static int gem_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static int gem_nway_reset(struct net_device *dev)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
if (!gp->want_autoneg)
return -EINVAL;
@@ -2768,13 +2767,13 @@ static int gem_nway_reset(struct net_device *dev)
static u32 gem_get_msglevel(struct net_device *dev)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
return gp->msg_enable;
}
static void gem_set_msglevel(struct net_device *dev, u32 value)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
gp->msg_enable = value;
}
@@ -2786,7 +2785,7 @@ static void gem_set_msglevel(struct net_device *dev, u32 value)
static void gem_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
/* Add more when I understand how to program the chip */
if (gp->has_wol) {
@@ -2800,7 +2799,7 @@ static void gem_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
static int gem_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
if (!gp->has_wol)
return -EOPNOTSUPP;
@@ -2822,7 +2821,7 @@ static const struct ethtool_ops gem_ethtool_ops = {
static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
struct mii_ioctl_data *data = if_mii(ifr);
int rc = -EOPNOTSUPP;
unsigned long flags;
@@ -2954,7 +2953,7 @@ static void gem_remove_one(struct pci_dev *pdev)
struct net_device *dev = pci_get_drvdata(pdev);
if (dev) {
- struct gem *gp = dev->priv;
+ struct gem *gp = netdev_priv(dev);
unregister_netdev(dev);
@@ -2998,7 +2997,6 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
struct net_device *dev;
struct gem *gp;
int err, pci_using_dac;
- DECLARE_MAC_BUF(mac);
if (gem_version_printed++ == 0)
printk(KERN_INFO "%s", version);
@@ -3058,7 +3056,7 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
}
SET_NETDEV_DEV(dev, &pdev->dev);
- gp = dev->priv;
+ gp = netdev_priv(dev);
err = pci_request_regions(pdev, DRV_NAME);
if (err) {
@@ -3182,9 +3180,8 @@ static int __devinit gem_init_one(struct pci_dev *pdev,
goto err_out_free_consistent;
}
- printk(KERN_INFO "%s: Sun GEM (PCI) 10/100/1000BaseT Ethernet "
- "%s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "%s: Sun GEM (PCI) 10/100/1000BaseT Ethernet %pM\n",
+ dev->name, dev->dev_addr);
if (gp->phy_type == phy_mii_mdio0 ||
gp->phy_type == phy_mii_mdio1)
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index f1ebeb5f65b2..b22d3355fb45 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -2072,7 +2072,6 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev)
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
hp->net_stats.rx_packets++;
hp->net_stats.rx_bytes += len;
next:
@@ -2131,7 +2130,7 @@ static irqreturn_t quattro_sbus_interrupt(int irq, void *cookie)
for (i = 0; i < 4; i++) {
struct net_device *dev = qp->happy_meals[i];
- struct happy_meal *hp = dev->priv;
+ struct happy_meal *hp = netdev_priv(dev);
u32 happy_status = hme_read32(hp, hp->gregs + GREG_STAT);
HMD(("quattro_interrupt: status=%08x ", happy_status));
@@ -2176,7 +2175,7 @@ static irqreturn_t quattro_sbus_interrupt(int irq, void *cookie)
static int happy_meal_open(struct net_device *dev)
{
- struct happy_meal *hp = dev->priv;
+ struct happy_meal *hp = netdev_priv(dev);
int res;
HMD(("happy_meal_open: "));
@@ -2208,7 +2207,7 @@ static int happy_meal_open(struct net_device *dev)
static int happy_meal_close(struct net_device *dev)
{
- struct happy_meal *hp = dev->priv;
+ struct happy_meal *hp = netdev_priv(dev);
spin_lock_irq(&hp->happy_lock);
happy_meal_stop(hp, hp->gregs);
@@ -2237,7 +2236,7 @@ static int happy_meal_close(struct net_device *dev)
static void happy_meal_tx_timeout(struct net_device *dev)
{
- struct happy_meal *hp = dev->priv;
+ struct happy_meal *hp = netdev_priv(dev);
printk (KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
tx_dump_log();
@@ -2255,7 +2254,7 @@ static void happy_meal_tx_timeout(struct net_device *dev)
static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct happy_meal *hp = dev->priv;
+ struct happy_meal *hp = netdev_priv(dev);
int entry;
u32 tx_flags;
@@ -2344,7 +2343,7 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev)
static struct net_device_stats *happy_meal_get_stats(struct net_device *dev)
{
- struct happy_meal *hp = dev->priv;
+ struct happy_meal *hp = netdev_priv(dev);
spin_lock_irq(&hp->happy_lock);
happy_meal_get_counters(hp, hp->bigmacregs);
@@ -2355,7 +2354,7 @@ static struct net_device_stats *happy_meal_get_stats(struct net_device *dev)
static void happy_meal_set_multicast(struct net_device *dev)
{
- struct happy_meal *hp = dev->priv;
+ struct happy_meal *hp = netdev_priv(dev);
void __iomem *bregs = hp->bigmacregs;
struct dev_mc_list *dmi = dev->mc_list;
char *addrs;
@@ -2401,7 +2400,7 @@ static void happy_meal_set_multicast(struct net_device *dev)
/* Ethtool support... */
static int hme_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- struct happy_meal *hp = dev->priv;
+ struct happy_meal *hp = netdev_priv(dev);
cmd->supported =
(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
@@ -2446,7 +2445,7 @@ static int hme_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static int hme_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
- struct happy_meal *hp = dev->priv;
+ struct happy_meal *hp = netdev_priv(dev);
/* Verify the settings we care about. */
if (cmd->autoneg != AUTONEG_ENABLE &&
@@ -2470,7 +2469,7 @@ static int hme_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
static void hme_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
- struct happy_meal *hp = dev->priv;
+ struct happy_meal *hp = netdev_priv(dev);
strcpy(info->driver, "sunhme");
strcpy(info->version, "2.02");
@@ -2492,7 +2491,7 @@ static void hme_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info
static u32 hme_get_link(struct net_device *dev)
{
- struct happy_meal *hp = dev->priv;
+ struct happy_meal *hp = netdev_priv(dev);
spin_lock_irq(&hp->happy_lock);
hp->sw_bmcr = happy_meal_tcvr_read(hp, hp->tcvregs, MII_BMCR);
@@ -2617,7 +2616,6 @@ static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe)
struct net_device *dev;
int i, qfe_slot = -1;
int err = -ENODEV;
- DECLARE_MAC_BUF(mac);
if (is_qfe) {
qp = quattro_sbus_find(op);
@@ -2797,7 +2795,7 @@ static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe)
printk(KERN_INFO "%s: HAPPY MEAL (SBUS) 10/100baseT Ethernet ",
dev->name);
- printk("%s\n", print_mac(mac, dev->dev_addr));
+ printk("%pM\n", dev->dev_addr);
return 0;
@@ -2932,7 +2930,6 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
int i, qfe_slot = -1;
char prom_name[64];
int err;
- DECLARE_MAC_BUF(mac);
/* Now make sure pci_dev cookie is there. */
#ifdef CONFIG_SPARC
@@ -2973,7 +2970,7 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
dev->base_addr = (long) pdev;
- hp = (struct happy_meal *)dev->priv;
+ hp = netdev_priv(dev);
memset(hp, 0, sizeof(*hp));
hp->happy_dev = pdev;
@@ -3141,7 +3138,7 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev,
printk(KERN_INFO "%s: HAPPY MEAL (PCI/CheerIO) 10/100BaseT Ethernet ",
dev->name);
- printk("%s\n", print_mac(mac, dev->dev_addr));
+ printk("%pM\n", dev->dev_addr);
return 0;
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 704301a5a7ff..281373281756 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -555,7 +555,6 @@ static void lance_rx_dvma(struct net_device *dev)
len);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
}
@@ -726,7 +725,6 @@ static void lance_rx_pio(struct net_device *dev)
lance_piocopy_to_skb(skb, &(ib->rx_buf[entry][0]), len);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
}
@@ -1321,7 +1319,6 @@ static int __devinit sparc_lance_probe_one(struct of_device *op,
static unsigned version_printed;
struct lance_private *lp;
struct net_device *dev;
- DECLARE_MAC_BUF(mac);
int i;
dev = alloc_etherdev(sizeof(struct lance_private) + 8);
@@ -1491,8 +1488,8 @@ no_link_test:
dev_set_drvdata(&op->dev, lp);
- printk(KERN_INFO "%s: LANCE %s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "%s: LANCE %pM\n",
+ dev->name, dev->dev_addr);
return 0;
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index f63644744ff9..6e8f377355fe 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -446,7 +446,6 @@ static void qe_rx(struct sunqe *qep)
len);
skb->protocol = eth_type_trans(skb, qep->dev);
netif_rx(skb);
- qep->dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += len;
}
@@ -513,7 +512,7 @@ static irqreturn_t qec_interrupt(int irq, void *dev_id)
static int qe_open(struct net_device *dev)
{
- struct sunqe *qep = (struct sunqe *) dev->priv;
+ struct sunqe *qep = netdev_priv(dev);
qep->mconfig = (MREGS_MCONFIG_TXENAB |
MREGS_MCONFIG_RXENAB |
@@ -523,7 +522,7 @@ static int qe_open(struct net_device *dev)
static int qe_close(struct net_device *dev)
{
- struct sunqe *qep = (struct sunqe *) dev->priv;
+ struct sunqe *qep = netdev_priv(dev);
qe_stop(qep);
return 0;
@@ -549,7 +548,7 @@ static void qe_tx_reclaim(struct sunqe *qep)
static void qe_tx_timeout(struct net_device *dev)
{
- struct sunqe *qep = (struct sunqe *) dev->priv;
+ struct sunqe *qep = netdev_priv(dev);
int tx_full;
spin_lock_irq(&qep->lock);
@@ -575,7 +574,7 @@ out:
/* Get a packet queued to go onto the wire. */
static int qe_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct sunqe *qep = (struct sunqe *) dev->priv;
+ struct sunqe *qep = netdev_priv(dev);
struct sunqe_buffers *qbufs = qep->buffers;
__u32 txbuf_dvma, qbufs_dvma = qep->buffers_dvma;
unsigned char *txbuf;
@@ -627,7 +626,7 @@ static int qe_start_xmit(struct sk_buff *skb, struct net_device *dev)
static void qe_set_multicast(struct net_device *dev)
{
- struct sunqe *qep = (struct sunqe *) dev->priv;
+ struct sunqe *qep = netdev_priv(dev);
struct dev_mc_list *dmi = dev->mc_list;
u8 new_mconfig = qep->mconfig;
char *addrs;
@@ -693,7 +692,7 @@ static void qe_set_multicast(struct net_device *dev)
static void qe_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
const struct linux_prom_registers *regs;
- struct sunqe *qep = dev->priv;
+ struct sunqe *qep = netdev_priv(dev);
struct of_device *op;
strcpy(info->driver, "sunqe");
@@ -708,7 +707,7 @@ static void qe_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
static u32 qe_get_link(struct net_device *dev)
{
- struct sunqe *qep = dev->priv;
+ struct sunqe *qep = netdev_priv(dev);
void __iomem *mregs = qep->mregs;
u8 phyconfig;
diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c
index a720065553df..233f1cda36e5 100644
--- a/drivers/net/sunvnet.c
+++ b/drivers/net/sunvnet.c
@@ -1149,7 +1149,6 @@ static int __devinit vnet_port_probe(struct vio_dev *vdev,
struct vnet *vp;
const u64 *rmac;
int len, i, err, switch_port;
- DECLARE_MAC_BUF(mac);
print_version();
@@ -1214,8 +1213,8 @@ static int __devinit vnet_port_probe(struct vio_dev *vdev,
dev_set_drvdata(&vdev->dev, port);
- printk(KERN_INFO "%s: PORT ( remote-mac %s%s )\n",
- vp->dev->name, print_mac(mac, port->raddr),
+ printk(KERN_INFO "%s: PORT ( remote-mac %pM%s )\n",
+ vp->dev->name, port->raddr,
switch_port ? " switch-port" : "");
vio_port_up(&port->vio);
diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c
index df20cafff7dd..bcd0e60cbda9 100644
--- a/drivers/net/tc35815.c
+++ b/drivers/net/tc35815.c
@@ -37,6 +37,7 @@ static const char *version = "tc35815.c:v" DRV_VERSION "\n";
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/in.h>
+#include <linux/if_vlan.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/spinlock.h>
@@ -236,7 +237,7 @@ struct tc35815_regs {
#define Rx_Halted 0x00008000 /* Rx Halted */
#define Rx_Good 0x00004000 /* Rx Good */
#define Rx_RxPar 0x00002000 /* Rx Parity Error */
- /* 0x00001000 not use */
+#define Rx_TypePkt 0x00001000 /* Rx Type Packet */
#define Rx_LongErr 0x00000800 /* Rx Long Error */
#define Rx_Over 0x00000400 /* Rx Overflow */
#define Rx_CRCErr 0x00000200 /* Rx CRC Error */
@@ -244,8 +245,9 @@ struct tc35815_regs {
#define Rx_10Stat 0x00000080 /* Rx 10Mbps Status */
#define Rx_IntRx 0x00000040 /* Rx Interrupt */
#define Rx_CtlRecd 0x00000020 /* Rx Control Receive */
+#define Rx_InLenErr 0x00000010 /* Rx In Range Frame Length Error */
-#define Rx_Stat_Mask 0x0000EFC0 /* Rx All Status Mask */
+#define Rx_Stat_Mask 0x0000FFF0 /* Rx All Status Mask */
/* Int_En bit asign -------------------------------------------------------- */
#define Int_NRAbtEn 0x00000800 /* 1:Non-recoverable Abort Enable */
@@ -340,7 +342,7 @@ struct BDesc {
Tx_En) /* maybe 0x7b01 */
#endif
#define RX_CTL_CMD (Rx_EnGood | Rx_EnRxPar | Rx_EnLongErr | Rx_EnOver \
- | Rx_EnCRCErr | Rx_EnAlign | Rx_RxEn) /* maybe 0x6f01 */
+ | Rx_EnCRCErr | Rx_EnAlign | Rx_StripCRC | Rx_RxEn) /* maybe 0x6f11 */
#define INT_EN_CMD (Int_NRAbtEn | \
Int_DmParErrEn | Int_DParDEn | Int_DParErrEn | \
Int_SSysErrEn | Int_RMasAbtEn | Int_RTargAbtEn | \
@@ -372,9 +374,11 @@ struct BDesc {
#if RX_CTL_CMD & Rx_LongEn
#define RX_BUF_SIZE PAGE_SIZE
#elif RX_CTL_CMD & Rx_StripCRC
-#define RX_BUF_SIZE ALIGN(ETH_FRAME_LEN + 4 + 2, 32) /* +2: reserve */
+#define RX_BUF_SIZE \
+ L1_CACHE_ALIGN(ETH_FRAME_LEN + VLAN_HLEN + NET_IP_ALIGN)
#else
-#define RX_BUF_SIZE ALIGN(ETH_FRAME_LEN + 2, 32) /* +2: reserve */
+#define RX_BUF_SIZE \
+ L1_CACHE_ALIGN(ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN + NET_IP_ALIGN)
#endif
#endif /* TC35815_USE_PACKEDBUFFER */
#define RX_FD_RESERVE (2 / 2) /* max 2 BD per RxFD */
@@ -865,7 +869,6 @@ static int __devinit tc35815_init_one(struct pci_dev *pdev,
struct net_device *dev;
struct tc35815_local *lp;
int rc;
- DECLARE_MAC_BUF(mac);
static int printed_version;
if (!printed_version++) {
@@ -942,11 +945,11 @@ static int __devinit tc35815_init_one(struct pci_dev *pdev,
goto err_out;
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
- printk(KERN_INFO "%s: %s at 0x%lx, %s, IRQ %d\n",
+ printk(KERN_INFO "%s: %s at 0x%lx, %pM, IRQ %d\n",
dev->name,
chip_info[ent->driver_data].name,
dev->base_addr,
- print_mac(mac, dev->dev_addr),
+ dev->dev_addr,
dev->irq);
rc = tc_mii_init(dev);
@@ -1288,12 +1291,9 @@ panic_queues(struct net_device *dev)
static void print_eth(const u8 *add)
{
- DECLARE_MAC_BUF(mac);
-
printk(KERN_DEBUG "print_eth(%p)\n", add);
- printk(KERN_DEBUG " %s =>", print_mac(mac, add + 6));
- printk(KERN_CONT " %s : %02x%02x\n",
- print_mac(mac, add), add[12], add[13]);
+ printk(KERN_DEBUG " %pM => %pM : %02x%02x\n",
+ add + 6, add, add[12], add[13]);
}
static int tc35815_tx_full(struct net_device *dev)
@@ -1609,8 +1609,8 @@ static irqreturn_t tc35815_interrupt(int irq, void *dev_id)
if (!(dmactl & DMA_IntMask)) {
/* disable interrupts */
tc_writel(dmactl | DMA_IntMask, &tr->DMA_Ctl);
- if (netif_rx_schedule_prep(dev, &lp->napi))
- __netif_rx_schedule(dev, &lp->napi);
+ if (netif_rx_schedule_prep(&lp->napi))
+ __netif_rx_schedule(&lp->napi);
else {
printk(KERN_ERR "%s: interrupt taken in poll\n",
dev->name);
@@ -1669,7 +1669,7 @@ tc35815_rx(struct net_device *dev)
struct RxFD *next_rfd;
#endif
#if (RX_CTL_CMD & Rx_StripCRC) == 0
- pkt_len -= 4;
+ pkt_len -= ETH_FCS_LEN;
#endif
if (netif_msg_rx_status(lp))
@@ -1688,14 +1688,14 @@ tc35815_rx(struct net_device *dev)
#endif
#ifdef TC35815_USE_PACKEDBUFFER
BUG_ON(bd_count > 2);
- skb = dev_alloc_skb(pkt_len + 2); /* +2: for reserve */
+ skb = dev_alloc_skb(pkt_len + NET_IP_ALIGN);
if (skb == NULL) {
printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
dev->name);
dev->stats.rx_dropped++;
break;
}
- skb_reserve(skb, 2); /* 16 bit alignment */
+ skb_reserve(skb, NET_IP_ALIGN);
data = skb_put(skb, pkt_len);
@@ -1747,8 +1747,9 @@ tc35815_rx(struct net_device *dev)
pci_unmap_single(lp->pci_dev,
lp->rx_skbs[cur_bd].skb_dma,
RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
- if (!HAVE_DMA_RXALIGN(lp))
- memmove(skb->data, skb->data - 2, pkt_len);
+ if (!HAVE_DMA_RXALIGN(lp) && NET_IP_ALIGN)
+ memmove(skb->data, skb->data - NET_IP_ALIGN,
+ pkt_len);
data = skb_put(skb, pkt_len);
#endif /* TC35815_USE_PACKEDBUFFER */
if (netif_msg_pktdata(lp))
@@ -1760,7 +1761,6 @@ tc35815_rx(struct net_device *dev)
#else
netif_rx(skb);
#endif
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
} else {
@@ -1919,7 +1919,7 @@ static int tc35815_poll(struct napi_struct *napi, int budget)
spin_unlock(&lp->lock);
if (received < budget) {
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
/* enable interrupts */
tc_writel(tc_readl(&tr->DMA_Ctl) & ~DMA_IntMask, &tr->DMA_Ctl);
}
@@ -2153,13 +2153,12 @@ static void tc35815_set_cam_entry(struct net_device *dev, int index, unsigned ch
int cam_index = index * 6;
u32 cam_data;
u32 saved_addr;
- DECLARE_MAC_BUF(mac);
saved_addr = tc_readl(&tr->CAM_Adr);
if (netif_msg_hw(lp))
- printk(KERN_DEBUG "%s: CAM %d: %s\n",
- dev->name, index, print_mac(mac, addr));
+ printk(KERN_DEBUG "%s: CAM %d: %pM\n",
+ dev->name, index, addr);
if (index & 1) {
/* read modify write */
tc_writel(cam_index - 2, &tr->CAM_Adr);
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
index 91f9054a1d95..a10a83a11d9f 100644
--- a/drivers/net/tehuti.c
+++ b/drivers/net/tehuti.c
@@ -251,7 +251,7 @@ static void bdx_isr_extra(struct bdx_priv *priv, u32 isr)
static irqreturn_t bdx_isr_napi(int irq, void *dev)
{
struct net_device *ndev = dev;
- struct bdx_priv *priv = ndev->priv;
+ struct bdx_priv *priv = netdev_priv(ndev);
u32 isr;
ENTER;
@@ -265,8 +265,8 @@ static irqreturn_t bdx_isr_napi(int irq, void *dev)
bdx_isr_extra(priv, isr);
if (isr & (IR_RX_DESC_0 | IR_TX_FREE_0)) {
- if (likely(netif_rx_schedule_prep(ndev, &priv->napi))) {
- __netif_rx_schedule(ndev, &priv->napi);
+ if (likely(netif_rx_schedule_prep(&priv->napi))) {
+ __netif_rx_schedule(&priv->napi);
RET(IRQ_HANDLED);
} else {
/* NOTE: we get here if intr has slipped into window
@@ -289,7 +289,6 @@ static irqreturn_t bdx_isr_napi(int irq, void *dev)
static int bdx_poll(struct napi_struct *napi, int budget)
{
struct bdx_priv *priv = container_of(napi, struct bdx_priv, napi);
- struct net_device *dev = priv->ndev;
int work_done;
ENTER;
@@ -303,7 +302,7 @@ static int bdx_poll(struct napi_struct *napi, int budget)
* device lock and allow waiting tasks (eg rmmod) to advance) */
priv->napi_stop = 0;
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
bdx_enable_interrupts(priv);
}
return work_done;
@@ -559,7 +558,7 @@ static int bdx_close(struct net_device *ndev)
struct bdx_priv *priv = NULL;
ENTER;
- priv = ndev->priv;
+ priv = netdev_priv(ndev);
napi_disable(&priv->napi);
@@ -588,7 +587,7 @@ static int bdx_open(struct net_device *ndev)
int rc;
ENTER;
- priv = ndev->priv;
+ priv = netdev_priv(ndev);
bdx_reset(priv);
if (netif_running(ndev))
netif_stop_queue(priv->ndev);
@@ -633,7 +632,7 @@ static int bdx_range_check(struct bdx_priv *priv, u32 offset)
static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd)
{
- struct bdx_priv *priv = ndev->priv;
+ struct bdx_priv *priv = netdev_priv(ndev);
u32 data[3];
int error;
@@ -698,7 +697,7 @@ static int bdx_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
*/
static void __bdx_vlan_rx_vid(struct net_device *ndev, uint16_t vid, int enable)
{
- struct bdx_priv *priv = ndev->priv;
+ struct bdx_priv *priv = netdev_priv(ndev);
u32 reg, bit, val;
ENTER;
@@ -748,7 +747,7 @@ static void bdx_vlan_rx_kill_vid(struct net_device *ndev, unsigned short vid)
static void
bdx_vlan_rx_register(struct net_device *ndev, struct vlan_group *grp)
{
- struct bdx_priv *priv = ndev->priv;
+ struct bdx_priv *priv = netdev_priv(ndev);
ENTER;
DBG("device='%s', group='%p'\n", ndev->name, grp);
@@ -787,7 +786,7 @@ static int bdx_change_mtu(struct net_device *ndev, int new_mtu)
static void bdx_setmulti(struct net_device *ndev)
{
- struct bdx_priv *priv = ndev->priv;
+ struct bdx_priv *priv = netdev_priv(ndev);
u32 rxf_val =
GMAC_RX_FILTER_AM | GMAC_RX_FILTER_AB | GMAC_RX_FILTER_OSEN;
@@ -847,7 +846,7 @@ static void bdx_setmulti(struct net_device *ndev)
static int bdx_set_mac(struct net_device *ndev, void *p)
{
- struct bdx_priv *priv = ndev->priv;
+ struct bdx_priv *priv = netdev_priv(ndev);
struct sockaddr *addr = p;
ENTER;
@@ -929,7 +928,7 @@ static void bdx_update_stats(struct bdx_priv *priv)
static struct net_device_stats *bdx_get_stats(struct net_device *ndev)
{
- struct bdx_priv *priv = ndev->priv;
+ struct bdx_priv *priv = netdev_priv(ndev);
struct net_device_stats *net_stat = &priv->net_stats;
return net_stat;
}
@@ -1237,7 +1236,6 @@ static int bdx_rx_receive(struct bdx_priv *priv, struct rxd_fifo *f, int budget)
ENTER;
max_done = budget;
- priv->ndev->last_rx = jiffies;
f->m.wptr = READ_REG(priv, f->m.reg_WPTR) & TXF_WPTR_WR_PTR;
size = f->m.wptr - f->m.rptr;
@@ -1624,7 +1622,7 @@ static inline int bdx_tx_space(struct bdx_priv *priv)
*/
static int bdx_tx_transmit(struct sk_buff *skb, struct net_device *ndev)
{
- struct bdx_priv *priv = ndev->priv;
+ struct bdx_priv *priv = netdev_priv(ndev);
struct txd_fifo *f = &priv->txd_fifo0;
int txd_checksum = 7; /* full checksum */
int txd_lgsnd = 0;
@@ -1886,6 +1884,21 @@ static void bdx_tx_push_desc_safe(struct bdx_priv *priv, void *data, int size)
RET();
}
+static const struct net_device_ops bdx_netdev_ops = {
+ .ndo_open = bdx_open,
+ .ndo_stop = bdx_close,
+ .ndo_start_xmit = bdx_tx_transmit,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_do_ioctl = bdx_ioctl,
+ .ndo_set_multicast_list = bdx_setmulti,
+ .ndo_get_stats = bdx_get_stats,
+ .ndo_change_mtu = bdx_change_mtu,
+ .ndo_set_mac_address = bdx_set_mac,
+ .ndo_vlan_rx_register = bdx_vlan_rx_register,
+ .ndo_vlan_rx_add_vid = bdx_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = bdx_vlan_rx_kill_vid,
+};
+
/**
* bdx_probe - Device Initialization Routine
* @pdev: PCI device information struct
@@ -1995,18 +2008,8 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_iomap;
}
- ndev->open = bdx_open;
- ndev->stop = bdx_close;
- ndev->hard_start_xmit = bdx_tx_transmit;
- ndev->do_ioctl = bdx_ioctl;
- ndev->set_multicast_list = bdx_setmulti;
- ndev->get_stats = bdx_get_stats;
- ndev->change_mtu = bdx_change_mtu;
- ndev->set_mac_address = bdx_set_mac;
+ ndev->netdev_ops = &bdx_netdev_ops;
ndev->tx_queue_len = BDX_NDEV_TXQ_LEN;
- ndev->vlan_rx_register = bdx_vlan_rx_register;
- ndev->vlan_rx_add_vid = bdx_vlan_rx_add_vid;
- ndev->vlan_rx_kill_vid = bdx_vlan_rx_kill_vid;
bdx_ethtool_ops(ndev); /* ethtool interface */
@@ -2027,7 +2030,7 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ndev->features |= NETIF_F_HIGHDMA;
/************** priv ****************/
- priv = nic->priv[port] = ndev->priv;
+ priv = nic->priv[port] = netdev_priv(ndev);
memset(priv, 0, sizeof(struct bdx_priv));
priv->pBdxRegs = nic->regs + port * 0x8000;
@@ -2150,7 +2153,7 @@ static int bdx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
{
u32 rdintcm;
u32 tdintcm;
- struct bdx_priv *priv = netdev->priv;
+ struct bdx_priv *priv = netdev_priv(netdev);
rdintcm = priv->rdintcm;
tdintcm = priv->tdintcm;
@@ -2181,7 +2184,7 @@ static int bdx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
static void
bdx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
{
- struct bdx_priv *priv = netdev->priv;
+ struct bdx_priv *priv = netdev_priv(netdev);
strlcat(drvinfo->driver, BDX_DRV_NAME, sizeof(drvinfo->driver));
strlcat(drvinfo->version, BDX_DRV_VERSION, sizeof(drvinfo->version));
@@ -2223,7 +2226,7 @@ bdx_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *ecoal)
{
u32 rdintcm;
u32 tdintcm;
- struct bdx_priv *priv = netdev->priv;
+ struct bdx_priv *priv = netdev_priv(netdev);
rdintcm = priv->rdintcm;
tdintcm = priv->tdintcm;
@@ -2252,7 +2255,7 @@ bdx_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *ecoal)
{
u32 rdintcm;
u32 tdintcm;
- struct bdx_priv *priv = netdev->priv;
+ struct bdx_priv *priv = netdev_priv(netdev);
int rx_coal;
int tx_coal;
int rx_max_coal;
@@ -2310,7 +2313,7 @@ static inline int bdx_tx_fifo_size_to_packets(int tx_size)
static void
bdx_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring)
{
- struct bdx_priv *priv = netdev->priv;
+ struct bdx_priv *priv = netdev_priv(netdev);
/*max_pending - the maximum-sized FIFO we allow */
ring->rx_max_pending = bdx_rx_fifo_size_to_packets(3);
@@ -2327,7 +2330,7 @@ bdx_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring)
static int
bdx_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring)
{
- struct bdx_priv *priv = netdev->priv;
+ struct bdx_priv *priv = netdev_priv(netdev);
int rx_size = 0;
int tx_size = 0;
@@ -2388,7 +2391,7 @@ static void bdx_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
*/
static int bdx_get_stats_count(struct net_device *netdev)
{
- struct bdx_priv *priv = netdev->priv;
+ struct bdx_priv *priv = netdev_priv(netdev);
BDX_ASSERT(ARRAY_SIZE(bdx_stat_names)
!= sizeof(struct bdx_stats) / sizeof(u64));
return ((priv->stats_flag) ? ARRAY_SIZE(bdx_stat_names) : 0);
@@ -2403,7 +2406,7 @@ static int bdx_get_stats_count(struct net_device *netdev)
static void bdx_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, u64 *data)
{
- struct bdx_priv *priv = netdev->priv;
+ struct bdx_priv *priv = netdev_priv(netdev);
if (priv->stats_flag) {
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index eb9f8f3638e1..04ae1e86aeaa 100644
--- a/drivers/net/tg3.c
+++ b/drivers/net/tg3.c
@@ -54,20 +54,21 @@
#include <asm/prom.h>
#endif
+#define BAR_0 0
+#define BAR_2 2
+
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
#define TG3_VLAN_TAG_USED 1
#else
#define TG3_VLAN_TAG_USED 0
#endif
-#define TG3_TSO_SUPPORT 1
-
#include "tg3.h"
#define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "3.94"
-#define DRV_MODULE_RELDATE "August 14, 2008"
+#define DRV_MODULE_VERSION "3.97"
+#define DRV_MODULE_RELDATE "December 10, 2008"
#define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0
@@ -129,6 +130,8 @@
/* minimum number of free TX descriptors required to wake up TX process */
#define TG3_TX_WAKEUP_THRESH(tp) ((tp)->tx_pending / 4)
+#define TG3_RAW_IP_ALIGN 2
+
/* number of ETHTOOL_GSTATS u64's */
#define TG3_NUM_STATS (sizeof(struct tg3_ethtool_stats)/sizeof(u64))
@@ -205,7 +208,13 @@ static struct pci_device_id tg3_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5723)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761E)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5761S)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5761SE)},
{PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5785)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57760)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57790)},
+ {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57720)},
{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)},
{PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)},
{PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)},
@@ -872,13 +881,48 @@ static int tg3_mdio_reset(struct mii_bus *bp)
return 0;
}
-static void tg3_mdio_config(struct tg3 *tp)
+static void tg3_mdio_config_5785(struct tg3 *tp)
{
u32 val;
+ struct phy_device *phydev;
- if (tp->mdio_bus->phy_map[PHY_ADDR]->interface !=
- PHY_INTERFACE_MODE_RGMII)
+ phydev = tp->mdio_bus->phy_map[PHY_ADDR];
+ switch (phydev->drv->phy_id & phydev->drv->phy_id_mask) {
+ case TG3_PHY_ID_BCM50610:
+ val = MAC_PHYCFG2_50610_LED_MODES;
+ break;
+ case TG3_PHY_ID_BCMAC131:
+ val = MAC_PHYCFG2_AC131_LED_MODES;
+ break;
+ case TG3_PHY_ID_RTL8211C:
+ val = MAC_PHYCFG2_RTL8211C_LED_MODES;
+ break;
+ case TG3_PHY_ID_RTL8201E:
+ val = MAC_PHYCFG2_RTL8201E_LED_MODES;
+ break;
+ default:
return;
+ }
+
+ if (phydev->interface != PHY_INTERFACE_MODE_RGMII) {
+ tw32(MAC_PHYCFG2, val);
+
+ val = tr32(MAC_PHYCFG1);
+ val &= ~MAC_PHYCFG1_RGMII_INT;
+ tw32(MAC_PHYCFG1, val);
+
+ return;
+ }
+
+ if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE))
+ val |= MAC_PHYCFG2_EMODE_MASK_MASK |
+ MAC_PHYCFG2_FMODE_MASK_MASK |
+ MAC_PHYCFG2_GMODE_MASK_MASK |
+ MAC_PHYCFG2_ACT_MASK_MASK |
+ MAC_PHYCFG2_QUAL_MASK_MASK |
+ MAC_PHYCFG2_INBAND_ENABLE;
+
+ tw32(MAC_PHYCFG2, val);
val = tr32(MAC_PHYCFG1) & ~(MAC_PHYCFG1_RGMII_EXT_RX_DEC |
MAC_PHYCFG1_RGMII_SND_STAT_EN);
@@ -890,11 +934,6 @@ static void tg3_mdio_config(struct tg3 *tp)
}
tw32(MAC_PHYCFG1, val | MAC_PHYCFG1_RGMII_INT | MAC_PHYCFG1_TXC_DRV);
- val = tr32(MAC_PHYCFG2) & ~(MAC_PHYCFG2_INBAND_ENABLE);
- if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE))
- val |= MAC_PHYCFG2_INBAND_ENABLE;
- tw32(MAC_PHYCFG2, val);
-
val = tr32(MAC_EXT_RGMII_MODE);
val &= ~(MAC_RGMII_MODE_RX_INT_B |
MAC_RGMII_MODE_RX_QUALITY |
@@ -903,7 +942,7 @@ static void tg3_mdio_config(struct tg3 *tp)
MAC_RGMII_MODE_TX_ENABLE |
MAC_RGMII_MODE_TX_LOWPWR |
MAC_RGMII_MODE_TX_RESET);
- if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE) {
+ if (!(tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE)) {
if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN)
val |= MAC_RGMII_MODE_RX_INT_B |
MAC_RGMII_MODE_RX_QUALITY |
@@ -929,8 +968,9 @@ static void tg3_mdio_start(struct tg3 *tp)
tw32_f(MAC_MI_MODE, tp->mi_mode);
udelay(80);
- if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED)
- tg3_mdio_config(tp);
+ if ((tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+ tg3_mdio_config_5785(tp);
}
static void tg3_mdio_stop(struct tg3 *tp)
@@ -984,29 +1024,44 @@ static int tg3_mdio_init(struct tg3 *tp)
if (i) {
printk(KERN_WARNING "%s: mdiobus_reg failed (0x%x)\n",
tp->dev->name, i);
+ mdiobus_free(tp->mdio_bus);
return i;
}
- tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_INITED;
-
phydev = tp->mdio_bus->phy_map[PHY_ADDR];
- switch (phydev->phy_id) {
+ if (!phydev || !phydev->drv) {
+ printk(KERN_WARNING "%s: No PHY devices\n", tp->dev->name);
+ mdiobus_unregister(tp->mdio_bus);
+ mdiobus_free(tp->mdio_bus);
+ return -ENODEV;
+ }
+
+ switch (phydev->drv->phy_id & phydev->drv->phy_id_mask) {
+ case TG3_PHY_ID_BCM57780:
+ phydev->interface = PHY_INTERFACE_MODE_GMII;
+ break;
case TG3_PHY_ID_BCM50610:
- phydev->interface = PHY_INTERFACE_MODE_RGMII;
if (tp->tg3_flags3 & TG3_FLG3_RGMII_STD_IBND_DISABLE)
phydev->dev_flags |= PHY_BRCM_STD_IBND_DISABLE;
if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_RX_EN)
phydev->dev_flags |= PHY_BRCM_EXT_IBND_RX_ENABLE;
if (tp->tg3_flags3 & TG3_FLG3_RGMII_EXT_IBND_TX_EN)
phydev->dev_flags |= PHY_BRCM_EXT_IBND_TX_ENABLE;
+ /* fallthru */
+ case TG3_PHY_ID_RTL8211C:
+ phydev->interface = PHY_INTERFACE_MODE_RGMII;
break;
+ case TG3_PHY_ID_RTL8201E:
case TG3_PHY_ID_BCMAC131:
phydev->interface = PHY_INTERFACE_MODE_MII;
break;
}
- tg3_mdio_config(tp);
+ tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_INITED;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+ tg3_mdio_config_5785(tp);
return 0;
}
@@ -1130,9 +1185,9 @@ static void tg3_link_report(struct tg3 *tp)
printk(KERN_INFO PFX
"%s: Flow control is %s for TX and %s for RX.\n",
tp->dev->name,
- (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_TX) ?
+ (tp->link_config.active_flowctrl & FLOW_CTRL_TX) ?
"on" : "off",
- (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_RX) ?
+ (tp->link_config.active_flowctrl & FLOW_CTRL_RX) ?
"on" : "off");
tg3_ump_link_report(tp);
}
@@ -1142,11 +1197,11 @@ static u16 tg3_advert_flowctrl_1000T(u8 flow_ctrl)
{
u16 miireg;
- if ((flow_ctrl & TG3_FLOW_CTRL_TX) && (flow_ctrl & TG3_FLOW_CTRL_RX))
+ if ((flow_ctrl & FLOW_CTRL_TX) && (flow_ctrl & FLOW_CTRL_RX))
miireg = ADVERTISE_PAUSE_CAP;
- else if (flow_ctrl & TG3_FLOW_CTRL_TX)
+ else if (flow_ctrl & FLOW_CTRL_TX)
miireg = ADVERTISE_PAUSE_ASYM;
- else if (flow_ctrl & TG3_FLOW_CTRL_RX)
+ else if (flow_ctrl & FLOW_CTRL_RX)
miireg = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
else
miireg = 0;
@@ -1158,11 +1213,11 @@ static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl)
{
u16 miireg;
- if ((flow_ctrl & TG3_FLOW_CTRL_TX) && (flow_ctrl & TG3_FLOW_CTRL_RX))
+ if ((flow_ctrl & FLOW_CTRL_TX) && (flow_ctrl & FLOW_CTRL_RX))
miireg = ADVERTISE_1000XPAUSE;
- else if (flow_ctrl & TG3_FLOW_CTRL_TX)
+ else if (flow_ctrl & FLOW_CTRL_TX)
miireg = ADVERTISE_1000XPSE_ASYM;
- else if (flow_ctrl & TG3_FLOW_CTRL_RX)
+ else if (flow_ctrl & FLOW_CTRL_RX)
miireg = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM;
else
miireg = 0;
@@ -1170,28 +1225,6 @@ static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl)
return miireg;
}
-static u8 tg3_resolve_flowctrl_1000T(u16 lcladv, u16 rmtadv)
-{
- u8 cap = 0;
-
- if (lcladv & ADVERTISE_PAUSE_CAP) {
- if (lcladv & ADVERTISE_PAUSE_ASYM) {
- if (rmtadv & LPA_PAUSE_CAP)
- cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
- else if (rmtadv & LPA_PAUSE_ASYM)
- cap = TG3_FLOW_CTRL_RX;
- } else {
- if (rmtadv & LPA_PAUSE_CAP)
- cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
- }
- } else if (lcladv & ADVERTISE_PAUSE_ASYM) {
- if ((rmtadv & LPA_PAUSE_CAP) && (rmtadv & LPA_PAUSE_ASYM))
- cap = TG3_FLOW_CTRL_TX;
- }
-
- return cap;
-}
-
static u8 tg3_resolve_flowctrl_1000X(u16 lcladv, u16 rmtadv)
{
u8 cap = 0;
@@ -1199,16 +1232,16 @@ static u8 tg3_resolve_flowctrl_1000X(u16 lcladv, u16 rmtadv)
if (lcladv & ADVERTISE_1000XPAUSE) {
if (lcladv & ADVERTISE_1000XPSE_ASYM) {
if (rmtadv & LPA_1000XPAUSE)
- cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
+ cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
else if (rmtadv & LPA_1000XPAUSE_ASYM)
- cap = TG3_FLOW_CTRL_RX;
+ cap = FLOW_CTRL_RX;
} else {
if (rmtadv & LPA_1000XPAUSE)
- cap = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
+ cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
}
} else if (lcladv & ADVERTISE_1000XPSE_ASYM) {
if ((rmtadv & LPA_1000XPAUSE) && (rmtadv & LPA_1000XPAUSE_ASYM))
- cap = TG3_FLOW_CTRL_TX;
+ cap = FLOW_CTRL_TX;
}
return cap;
@@ -1231,13 +1264,13 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 lcladv, u32 rmtadv)
if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES)
flowctrl = tg3_resolve_flowctrl_1000X(lcladv, rmtadv);
else
- flowctrl = tg3_resolve_flowctrl_1000T(lcladv, rmtadv);
+ flowctrl = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
} else
flowctrl = tp->link_config.flowctrl;
tp->link_config.active_flowctrl = flowctrl;
- if (flowctrl & TG3_FLOW_CTRL_RX)
+ if (flowctrl & FLOW_CTRL_RX)
tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE;
else
tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE;
@@ -1245,7 +1278,7 @@ static void tg3_setup_flow_control(struct tg3 *tp, u32 lcladv, u32 rmtadv)
if (old_rx_mode != tp->rx_mode)
tw32_f(MAC_RX_MODE, tp->rx_mode);
- if (flowctrl & TG3_FLOW_CTRL_TX)
+ if (flowctrl & FLOW_CTRL_TX)
tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE;
else
tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE;
@@ -1299,6 +1332,15 @@ static void tg3_adjust_link(struct net_device *dev)
udelay(40);
}
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+ if (phydev->speed == SPEED_10)
+ tw32(MAC_MI_STAT,
+ MAC_MI_STAT_10MBPS_MODE |
+ MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
+ else
+ tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
+ }
+
if (phydev->speed == SPEED_1000 && phydev->duplex == DUPLEX_HALF)
tw32(MAC_TX_LENGTHS,
((2 << TX_LENGTHS_IPG_CRS_SHIFT) |
@@ -1339,25 +1381,37 @@ static int tg3_phy_init(struct tg3 *tp)
phydev = tp->mdio_bus->phy_map[PHY_ADDR];
/* Attach the MAC to the PHY. */
- phydev = phy_connect(tp->dev, phydev->dev.bus_id, tg3_adjust_link,
+ phydev = phy_connect(tp->dev, dev_name(&phydev->dev), tg3_adjust_link,
phydev->dev_flags, phydev->interface);
if (IS_ERR(phydev)) {
printk(KERN_ERR "%s: Could not attach to PHY\n", tp->dev->name);
return PTR_ERR(phydev);
}
- tp->tg3_flags3 |= TG3_FLG3_PHY_CONNECTED;
-
/* Mask with MAC supported features. */
- phydev->supported &= (PHY_GBIT_FEATURES |
- SUPPORTED_Pause |
- SUPPORTED_Asym_Pause);
+ switch (phydev->interface) {
+ case PHY_INTERFACE_MODE_GMII:
+ case PHY_INTERFACE_MODE_RGMII:
+ if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) {
+ phydev->supported &= (PHY_GBIT_FEATURES |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
+ break;
+ }
+ /* fallthru */
+ case PHY_INTERFACE_MODE_MII:
+ phydev->supported &= (PHY_BASIC_FEATURES |
+ SUPPORTED_Pause |
+ SUPPORTED_Asym_Pause);
+ break;
+ default:
+ phy_disconnect(tp->mdio_bus->phy_map[PHY_ADDR]);
+ return -EINVAL;
+ }
- phydev->advertising = phydev->supported;
+ tp->tg3_flags3 |= TG3_FLG3_PHY_CONNECTED;
- printk(KERN_INFO
- "%s: attached PHY driver [%s] (mii_bus:phy_addr=%s)\n",
- tp->dev->name, phydev->drv->name, phydev->dev.bus_id);
+ phydev->advertising = phydev->supported;
return 0;
}
@@ -1406,6 +1460,34 @@ static void tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val)
tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val);
}
+static void tg3_phy_toggle_apd(struct tg3 *tp, bool enable)
+{
+ u32 reg;
+
+ if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
+ return;
+
+ reg = MII_TG3_MISC_SHDW_WREN |
+ MII_TG3_MISC_SHDW_SCR5_SEL |
+ MII_TG3_MISC_SHDW_SCR5_LPED |
+ MII_TG3_MISC_SHDW_SCR5_DLPTLM |
+ MII_TG3_MISC_SHDW_SCR5_SDTL |
+ MII_TG3_MISC_SHDW_SCR5_C125OE;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 || !enable)
+ reg |= MII_TG3_MISC_SHDW_SCR5_DLLAPD;
+
+ tg3_writephy(tp, MII_TG3_MISC_SHDW, reg);
+
+
+ reg = MII_TG3_MISC_SHDW_WREN |
+ MII_TG3_MISC_SHDW_APD_SEL |
+ MII_TG3_MISC_SHDW_APD_WKTM_84MS;
+ if (enable)
+ reg |= MII_TG3_MISC_SHDW_APD_ENABLE;
+
+ tg3_writephy(tp, MII_TG3_MISC_SHDW, reg);
+}
+
static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable)
{
u32 phy;
@@ -1737,7 +1819,8 @@ static int tg3_phy_reset(struct tg3 *tp)
tw32(TG3_CPMU_CTRL, cpmuctrl);
}
- if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
+ GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) {
u32 val;
val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
@@ -1747,16 +1830,15 @@ static int tg3_phy_reset(struct tg3 *tp)
udelay(40);
tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
}
-
- /* Disable GPHY autopowerdown. */
- tg3_writephy(tp, MII_TG3_MISC_SHDW,
- MII_TG3_MISC_SHDW_WREN |
- MII_TG3_MISC_SHDW_APD_SEL |
- MII_TG3_MISC_SHDW_APD_WKTM_84MS);
}
tg3_phy_apply_otp(tp);
+ if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD)
+ tg3_phy_toggle_apd(tp, true);
+ else
+ tg3_phy_toggle_apd(tp, false);
+
out:
if (tp->tg3_flags2 & TG3_FLG2_PHY_ADC_BUG) {
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0c00);
@@ -1961,7 +2043,7 @@ static int tg3_halt_cpu(struct tg3 *, u32);
static int tg3_nvram_lock(struct tg3 *);
static void tg3_nvram_unlock(struct tg3 *);
-static void tg3_power_down_phy(struct tg3 *tp)
+static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power)
{
u32 val;
@@ -1984,10 +2066,15 @@ static void tg3_power_down_phy(struct tg3 *tp)
tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ);
udelay(40);
return;
- } else if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) {
+ } else if (do_low_power) {
tg3_writephy(tp, MII_TG3_EXT_CTRL,
MII_TG3_EXT_CTRL_FORCE_LED_OFF);
- tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2);
+
+ tg3_writephy(tp, MII_TG3_AUX_CTRL,
+ MII_TG3_AUXCTL_SHDWSEL_PWRCTL |
+ MII_TG3_AUXCTL_PCTL_100TX_LPWR |
+ MII_TG3_AUXCTL_PCTL_SPR_ISOLATE |
+ MII_TG3_AUXCTL_PCTL_VREG_11V);
}
/* The PHY should not be powered down on some chips because
@@ -1999,7 +2086,8 @@ static void tg3_power_down_phy(struct tg3 *tp)
(tp->tg3_flags2 & TG3_FLG2_MII_SERDES)))
return;
- if (tp->tg3_flags3 & TG3_FLG3_5761_5784_AX_FIXES) {
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
+ GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) {
val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
val |= CPMU_LSPD_1000MB_MACCLK_12_5;
@@ -2009,9 +2097,47 @@ static void tg3_power_down_phy(struct tg3 *tp)
tg3_writephy(tp, MII_BMCR, BMCR_PDOWN);
}
+/* tp->lock is held. */
+static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1)
+{
+ u32 addr_high, addr_low;
+ int i;
+
+ addr_high = ((tp->dev->dev_addr[0] << 8) |
+ tp->dev->dev_addr[1]);
+ addr_low = ((tp->dev->dev_addr[2] << 24) |
+ (tp->dev->dev_addr[3] << 16) |
+ (tp->dev->dev_addr[4] << 8) |
+ (tp->dev->dev_addr[5] << 0));
+ for (i = 0; i < 4; i++) {
+ if (i == 1 && skip_mac_1)
+ continue;
+ tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
+ tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
+ }
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
+ for (i = 0; i < 12; i++) {
+ tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high);
+ tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low);
+ }
+ }
+
+ addr_high = (tp->dev->dev_addr[0] +
+ tp->dev->dev_addr[1] +
+ tp->dev->dev_addr[2] +
+ tp->dev->dev_addr[3] +
+ tp->dev->dev_addr[4] +
+ tp->dev->dev_addr[5]) &
+ TX_BACKOFF_SEED_MASK;
+ tw32(MAC_TX_BACKOFF_SEED, addr_high);
+}
+
static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
{
u32 misc_host_ctrl;
+ bool device_should_wake, do_low_power;
/* Make sure register accesses (indirect or otherwise)
* will function correctly.
@@ -2041,15 +2167,34 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
tp->dev->name, state);
return -EINVAL;
}
+
+ /* Restore the CLKREQ setting. */
+ if (tp->tg3_flags3 & TG3_FLG3_CLKREQ_BUG) {
+ u16 lnkctl;
+
+ pci_read_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_LNKCTL,
+ &lnkctl);
+ lnkctl |= PCI_EXP_LNKCTL_CLKREQ_EN;
+ pci_write_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_LNKCTL,
+ lnkctl);
+ }
+
misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL);
tw32(TG3PCI_MISC_HOST_CTRL,
misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT);
+ device_should_wake = pci_pme_capable(tp->pdev, state) &&
+ device_may_wakeup(&tp->pdev->dev) &&
+ (tp->tg3_flags & TG3_FLAG_WOL_ENABLE);
+
if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) {
+ do_low_power = false;
if ((tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED) &&
!tp->link_config.phy_is_low_power) {
struct phy_device *phydev;
- u32 advertising;
+ u32 phyid, advertising;
phydev = tp->mdio_bus->phy_map[PHY_ADDR];
@@ -2066,7 +2211,7 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
ADVERTISED_10baseT_Half;
if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
- (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)) {
+ device_should_wake) {
if (tp->tg3_flags & TG3_FLAG_WOL_SPEED_100MB)
advertising |=
ADVERTISED_100baseT_Half |
@@ -2079,8 +2224,19 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
phydev->advertising = advertising;
phy_start_aneg(phydev);
+
+ phyid = phydev->drv->phy_id & phydev->drv->phy_id_mask;
+ if (phyid != TG3_PHY_ID_BCMAC131) {
+ phyid &= TG3_PHY_OUI_MASK;
+ if (phyid == TG3_PHY_OUI_1 &&
+ phyid == TG3_PHY_OUI_2 &&
+ phyid == TG3_PHY_OUI_3)
+ do_low_power = true;
+ }
}
} else {
+ do_low_power = true;
+
if (tp->link_config.phy_is_low_power == 0) {
tp->link_config.phy_is_low_power = 1;
tp->link_config.orig_speed = tp->link_config.speed;
@@ -2096,6 +2252,8 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
}
}
+ __tg3_set_mac_addr(tp, 0);
+
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
u32 val;
@@ -2118,11 +2276,11 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
WOL_DRV_WOL |
WOL_SET_MAGIC_PKT);
- if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE) {
+ if (device_should_wake) {
u32 mac_mode;
if (!(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES)) {
- if (!(tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)) {
+ if (do_low_power) {
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x5a);
udelay(40);
}
@@ -2150,9 +2308,12 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
if (!(tp->tg3_flags2 & TG3_FLG2_5750_PLUS))
tw32(MAC_LED_CTRL, tp->led_ctrl);
- if (pci_pme_capable(tp->pdev, state) &&
- (tp->tg3_flags & TG3_FLAG_WOL_ENABLE))
- mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE;
+ mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE;
+ if (((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
+ !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) &&
+ ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) ||
+ (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)))
+ mac_mode |= MAC_MODE_KEEP_FRAME_IN_WOL;
if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
mac_mode |= tp->mac_mode &
@@ -2224,10 +2385,9 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
}
}
- if (!(tp->tg3_flags & TG3_FLAG_WOL_ENABLE) &&
- !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) &&
- !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE))
- tg3_power_down_phy(tp);
+ if (!(device_should_wake) &&
+ !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF))
+ tg3_power_down_phy(tp, do_low_power);
tg3_frob_aux_power(tp);
@@ -2250,7 +2410,7 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state)
tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
- if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)
+ if (device_should_wake)
pci_enable_wake(tp->pdev, state, true);
/* Finally, set the new power state. */
@@ -2789,6 +2949,24 @@ relink:
NIC_SRAM_FIRMWARE_MBOX_MAGIC2);
}
+ /* Prevent send BD corruption. */
+ if (tp->tg3_flags3 & TG3_FLG3_CLKREQ_BUG) {
+ u16 oldlnkctl, newlnkctl;
+
+ pci_read_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_LNKCTL,
+ &oldlnkctl);
+ if (tp->link_config.active_speed == SPEED_100 ||
+ tp->link_config.active_speed == SPEED_10)
+ newlnkctl = oldlnkctl & ~PCI_EXP_LNKCTL_CLKREQ_EN;
+ else
+ newlnkctl = oldlnkctl | PCI_EXP_LNKCTL_CLKREQ_EN;
+ if (newlnkctl != oldlnkctl)
+ pci_write_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_LNKCTL,
+ newlnkctl);
+ }
+
if (current_link_up != netif_carrier_ok(tp->dev)) {
if (current_link_up)
netif_carrier_on(tp->dev);
@@ -3765,8 +3943,7 @@ static int tg3_setup_phy(struct tg3 *tp, int force_reset)
err = tg3_setup_copper_phy(tp, force_reset);
}
- if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
- tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) {
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX) {
u32 val, scale;
val = tr32(TG3_CPMU_CLCK_STAT) & CPMU_CLCK_STAT_MAC_CLCK_MASK;
@@ -4100,12 +4277,15 @@ static int tg3_rx(struct tg3 *tp, int budget)
goto next_pkt;
}
- len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) - 4; /* omit crc */
+ len = ((desc->idx_len & RXD_LEN_MASK) >> RXD_LEN_SHIFT) -
+ ETH_FCS_LEN;
if (len > RX_COPY_THRESHOLD
- && tp->rx_offset == 2
- /* rx_offset != 2 iff this is a 5701 card running
- * in PCI-X mode [see tg3_get_invariants()] */
+ && tp->rx_offset == NET_IP_ALIGN
+ /* rx_offset will likely not equal NET_IP_ALIGN
+ * if this is a 5701 card running in PCI-X mode
+ * [see tg3_get_invariants()]
+ */
) {
int skb_size;
@@ -4125,11 +4305,12 @@ static int tg3_rx(struct tg3 *tp, int budget)
tg3_recycle_rx(tp, opaque_key,
desc_idx, *post_ptr);
- copy_skb = netdev_alloc_skb(tp->dev, len + 2);
+ copy_skb = netdev_alloc_skb(tp->dev,
+ len + TG3_RAW_IP_ALIGN);
if (copy_skb == NULL)
goto drop_it_no_recycle;
- skb_reserve(copy_skb, 2);
+ skb_reserve(copy_skb, TG3_RAW_IP_ALIGN);
skb_put(copy_skb, len);
pci_dma_sync_single_for_cpu(tp->pdev, dma_addr, len, PCI_DMA_FROMDEVICE);
skb_copy_from_linear_data(skb, copy_skb->data, len);
@@ -4157,7 +4338,6 @@ static int tg3_rx(struct tg3 *tp, int budget)
#endif
netif_receive_skb(skb);
- tp->dev->last_rx = jiffies;
received++;
budget--;
@@ -4271,7 +4451,7 @@ static int tg3_poll(struct napi_struct *napi, int budget)
sblk->status &= ~SD_STATUS_UPDATED;
if (likely(!tg3_has_work(tp))) {
- netif_rx_complete(tp->dev, napi);
+ netif_rx_complete(napi);
tg3_restart_ints(tp);
break;
}
@@ -4281,7 +4461,7 @@ static int tg3_poll(struct napi_struct *napi, int budget)
tx_recovery:
/* work_done is guaranteed to be less than budget. */
- netif_rx_complete(tp->dev, napi);
+ netif_rx_complete(napi);
schedule_work(&tp->reset_task);
return work_done;
}
@@ -4330,7 +4510,7 @@ static irqreturn_t tg3_msi_1shot(int irq, void *dev_id)
prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
if (likely(!tg3_irq_sync(tp)))
- netif_rx_schedule(dev, &tp->napi);
+ netif_rx_schedule(&tp->napi);
return IRQ_HANDLED;
}
@@ -4355,7 +4535,7 @@ static irqreturn_t tg3_msi(int irq, void *dev_id)
*/
tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
if (likely(!tg3_irq_sync(tp)))
- netif_rx_schedule(dev, &tp->napi);
+ netif_rx_schedule(&tp->napi);
return IRQ_RETVAL(1);
}
@@ -4397,7 +4577,7 @@ static irqreturn_t tg3_interrupt(int irq, void *dev_id)
sblk->status &= ~SD_STATUS_UPDATED;
if (likely(tg3_has_work(tp))) {
prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
- netif_rx_schedule(dev, &tp->napi);
+ netif_rx_schedule(&tp->napi);
} else {
/* No work, shared interrupt perhaps? re-enable
* interrupts, and flush that PCI write
@@ -4443,7 +4623,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id)
tw32_mailbox_f(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001);
if (tg3_irq_sync(tp))
goto out;
- if (netif_rx_schedule_prep(dev, &tp->napi)) {
+ if (netif_rx_schedule_prep(&tp->napi)) {
prefetch(&tp->rx_rcb[tp->rx_rcb_ptr]);
/* Update last_tag to mark that this status has been
* seen. Because interrupt may be shared, we may be
@@ -4451,7 +4631,7 @@ static irqreturn_t tg3_interrupt_tagged(int irq, void *dev_id)
* if tg3_poll() is not scheduled.
*/
tp->last_tag = sblk->status_tag;
- __netif_rx_schedule(dev, &tp->napi);
+ __netif_rx_schedule(&tp->napi);
}
out:
return IRQ_RETVAL(handled);
@@ -5557,6 +5737,13 @@ static void tg3_ape_driver_state_change(struct tg3 *tp, int kind)
event = APE_EVENT_STATUS_STATE_START;
break;
case RESET_KIND_SHUTDOWN:
+ /* With the interface we are currently using,
+ * APE does not track driver state. Wiping
+ * out the HOST SEGMENT SIGNATURE forces
+ * the APE to assume OS absent status.
+ */
+ tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG, 0x0);
+
event = APE_EVENT_STATUS_STATE_UNLOAD;
break;
case RESET_KIND_SUSPEND:
@@ -5721,17 +5908,19 @@ static void tg3_restore_pci_state(struct tg3 *tp)
pci_write_config_word(tp->pdev, PCI_COMMAND, tp->pci_cmd);
- if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)
- pcie_set_readrq(tp->pdev, 4096);
- else {
- pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
- tp->pci_cacheline_sz);
- pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
- tp->pci_lat_timer);
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785) {
+ if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)
+ pcie_set_readrq(tp->pdev, 4096);
+ else {
+ pci_write_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
+ tp->pci_cacheline_sz);
+ pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
+ tp->pci_lat_timer);
+ }
}
/* Make sure PCI-X relaxed ordering bit is clear. */
- if (tp->pcix_cap) {
+ if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) {
u16 pcix_cmd;
pci_read_config_word(tp->pdev, tp->pcix_cap + PCI_X_CMD,
@@ -5788,11 +5977,7 @@ static int tg3_chip_reset(struct tg3 *tp)
tg3_save_pci_state(tp);
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+ (tp->tg3_flags3 & TG3_FLG3_5755_PLUS))
tw32(GRC_FASTBOOT_PC, 0);
/*
@@ -5871,7 +6056,7 @@ static int tg3_chip_reset(struct tg3 *tp)
udelay(120);
- if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
+ if ((tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) && tp->pcie_cap) {
if (tp->pci_chip_rev_id == CHIPREV_ID_5750_A0) {
int i;
u32 cfg_val;
@@ -5884,8 +6069,23 @@ static int tg3_chip_reset(struct tg3 *tp)
pci_write_config_dword(tp->pdev, 0xc4,
cfg_val | (1 << 15));
}
- /* Set PCIE max payload size and clear error status. */
- pci_write_config_dword(tp->pdev, 0xd8, 0xf5000);
+
+ /* Set PCIE max payload size to 128 bytes and
+ * clear the "no snoop" and "relaxed ordering" bits.
+ */
+ pci_write_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_DEVCTL,
+ 0);
+
+ pcie_set_readrq(tp->pdev, 4096);
+
+ /* Clear error status */
+ pci_write_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_DEVSTA,
+ PCI_EXP_DEVSTA_CED |
+ PCI_EXP_DEVSTA_NFED |
+ PCI_EXP_DEVSTA_FED |
+ PCI_EXP_DEVSTA_URD);
}
tg3_restore_pci_state(tp);
@@ -6883,43 +7083,6 @@ static int tg3_load_tso_firmware(struct tg3 *tp)
}
-/* tp->lock is held. */
-static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1)
-{
- u32 addr_high, addr_low;
- int i;
-
- addr_high = ((tp->dev->dev_addr[0] << 8) |
- tp->dev->dev_addr[1]);
- addr_low = ((tp->dev->dev_addr[2] << 24) |
- (tp->dev->dev_addr[3] << 16) |
- (tp->dev->dev_addr[4] << 8) |
- (tp->dev->dev_addr[5] << 0));
- for (i = 0; i < 4; i++) {
- if (i == 1 && skip_mac_1)
- continue;
- tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
- tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
- }
-
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
- for (i = 0; i < 12; i++) {
- tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high);
- tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low);
- }
- }
-
- addr_high = (tp->dev->dev_addr[0] +
- tp->dev->dev_addr[1] +
- tp->dev->dev_addr[2] +
- tp->dev->dev_addr[3] +
- tp->dev->dev_addr[4] +
- tp->dev->dev_addr[5]) &
- TX_BACKOFF_SEED_MASK;
- tw32(MAC_TX_BACKOFF_SEED, addr_high);
-}
-
static int tg3_set_mac_addr(struct net_device *dev, void *p)
{
struct tg3 *tp = netdev_priv(dev);
@@ -7024,8 +7187,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
tg3_write_sig_legacy(tp, RESET_KIND_INIT);
- if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
- tp->pci_chip_rev_id == CHIPREV_ID_5784_A1) {
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX) {
val = tr32(TG3_CPMU_CTRL);
val &= ~(CPMU_CTRL_LINK_AWARE_MODE | CPMU_CTRL_LINK_IDLE_MODE);
tw32(TG3_CPMU_CTRL, val);
@@ -7091,8 +7253,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
return err;
if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785) {
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761) {
/* This value is determined during the probe time DMA
* engine test, tg3_test_dma.
*/
@@ -7332,7 +7493,8 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
RDMAC_MODE_LNGREAD_ENAB);
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
rdmac_mode |= RDMAC_MODE_BD_SBD_CRPT_ENAB |
RDMAC_MODE_MBUF_RBD_CRPT_ENAB |
RDMAC_MODE_MBUF_SBD_CRPT_ENAB;
@@ -7354,7 +7516,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
rdmac_mode |= RDMAC_MODE_FIFO_LONG_BURST;
if (tp->tg3_flags2 & TG3_FLG2_HW_TSO)
- rdmac_mode |= (1 << 27);
+ rdmac_mode |= RDMAC_MODE_IPV4_LSO_EN;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
+ rdmac_mode |= RDMAC_MODE_IPV6_LSO_EN;
/* Receive/send statistics. */
if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
@@ -7501,11 +7667,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
}
/* Enable host coalescing bug fix */
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755) ||
- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787) ||
- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784) ||
- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) ||
- (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785))
+ if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS)
val |= WDMAC_MODE_STATUS_TAG_FIX;
tw32_f(WDMAC_MODE, val);
@@ -7566,10 +7728,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy)
udelay(100);
tp->rx_mode = RX_MODE_ENABLE;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+ if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS)
tp->rx_mode |= RX_MODE_IPV6_CSUM_ENABLE;
tw32_f(MAC_RX_MODE, tp->rx_mode);
@@ -9066,7 +9225,8 @@ static void tg3_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
else
wol->supported = 0;
wol->wolopts = 0;
- if (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)
+ if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) &&
+ device_can_wakeup(&tp->pdev->dev))
wol->wolopts = WAKE_MAGIC;
memset(&wol->sopass, 0, sizeof(wol->sopass));
}
@@ -9116,14 +9276,15 @@ static int tg3_set_tso(struct net_device *dev, u32 value)
return -EINVAL;
return 0;
}
- if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) &&
- (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906)) {
+ if ((dev->features & NETIF_F_IPV6_CSUM) &&
+ (tp->tg3_flags2 & TG3_FLG2_HW_TSO_2)) {
if (value) {
dev->features |= NETIF_F_TSO6;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
dev->features |= NETIF_F_TSO_ECN;
} else
dev->features &= ~(NETIF_F_TSO6 | NETIF_F_TSO_ECN);
@@ -9238,12 +9399,12 @@ static void tg3_get_pauseparam(struct net_device *dev, struct ethtool_pauseparam
epause->autoneg = (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) != 0;
- if (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_RX)
+ if (tp->link_config.active_flowctrl & FLOW_CTRL_RX)
epause->rx_pause = 1;
else
epause->rx_pause = 0;
- if (tp->link_config.active_flowctrl & TG3_FLOW_CTRL_TX)
+ if (tp->link_config.active_flowctrl & FLOW_CTRL_TX)
epause->tx_pause = 1;
else
epause->tx_pause = 0;
@@ -9294,14 +9455,14 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
}
} else {
if (epause->rx_pause)
- tp->link_config.flowctrl |= TG3_FLOW_CTRL_RX;
+ tp->link_config.flowctrl |= FLOW_CTRL_RX;
else
- tp->link_config.flowctrl &= ~TG3_FLOW_CTRL_RX;
+ tp->link_config.flowctrl &= ~FLOW_CTRL_RX;
if (epause->tx_pause)
- tp->link_config.flowctrl |= TG3_FLOW_CTRL_TX;
+ tp->link_config.flowctrl |= FLOW_CTRL_TX;
else
- tp->link_config.flowctrl &= ~TG3_FLOW_CTRL_TX;
+ tp->link_config.flowctrl &= ~FLOW_CTRL_TX;
if (netif_running(dev))
tg3_setup_flow_control(tp, 0, 0);
@@ -9321,13 +9482,13 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam
else
tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG;
if (epause->rx_pause)
- tp->link_config.flowctrl |= TG3_FLOW_CTRL_RX;
+ tp->link_config.flowctrl |= FLOW_CTRL_RX;
else
- tp->link_config.flowctrl &= ~TG3_FLOW_CTRL_RX;
+ tp->link_config.flowctrl &= ~FLOW_CTRL_RX;
if (epause->tx_pause)
- tp->link_config.flowctrl |= TG3_FLOW_CTRL_TX;
+ tp->link_config.flowctrl |= FLOW_CTRL_TX;
else
- tp->link_config.flowctrl &= ~TG3_FLOW_CTRL_TX;
+ tp->link_config.flowctrl &= ~FLOW_CTRL_TX;
if (netif_running(dev)) {
tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
@@ -9378,11 +9539,7 @@ static int tg3_set_tx_csum(struct net_device *dev, u32 data)
return 0;
}
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+ if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS)
ethtool_op_set_tx_ipv6_csum(dev, data);
else
ethtool_op_set_tx_csum(dev, data);
@@ -9899,18 +10056,13 @@ static int tg3_test_memory(struct tg3 *tp)
int err = 0;
int i;
- if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
- mem_tbl = mem_tbl_5755;
- else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
- mem_tbl = mem_tbl_5906;
- else
- mem_tbl = mem_tbl_5705;
- } else
+ if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS)
+ mem_tbl = mem_tbl_5755;
+ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+ mem_tbl = mem_tbl_5906;
+ else if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS)
+ mem_tbl = mem_tbl_5705;
+ else
mem_tbl = mem_tbl_570x;
for (i = 0; mem_tbl[i].offset != 0xffffffff; i++) {
@@ -10110,9 +10262,11 @@ static int tg3_test_loopback(struct tg3 *tp)
if (err)
return TG3_LOOPBACK_FAILED;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+ /* Turn off gphy autopowerdown. */
+ if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD)
+ tg3_phy_toggle_apd(tp, false);
+
+ if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) {
int i;
u32 status;
@@ -10139,9 +10293,7 @@ static int tg3_test_loopback(struct tg3 *tp)
if (tg3_run_loopback(tp, TG3_MAC_LOOPBACK))
err |= TG3_MAC_LOOPBACK_FAILED;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+ if (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT) {
tw32(TG3_CPMU_CTRL, cpmuctrl);
/* Release the mutex */
@@ -10154,6 +10306,10 @@ static int tg3_test_loopback(struct tg3 *tp)
err |= TG3_PHY_LOOPBACK_FAILED;
}
+ /* Re-enable gphy autopowerdown. */
+ if (tp->tg3_flags3 & TG3_FLG3_PHY_ENABLE_APD)
+ tg3_phy_toggle_apd(tp, true);
+
return err;
}
@@ -10756,6 +10912,102 @@ static void __devinit tg3_get_5906_nvram_info(struct tg3 *tp)
tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
}
+static void __devinit tg3_get_57780_nvram_info(struct tg3 *tp)
+{
+ u32 nvcfg1;
+
+ nvcfg1 = tr32(NVRAM_CFG1);
+
+ switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+ case FLASH_5787VENDOR_ATMEL_EEPROM_376KHZ:
+ case FLASH_5787VENDOR_MICRO_EEPROM_376KHZ:
+ tp->nvram_jedecnum = JEDEC_ATMEL;
+ tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+ tp->nvram_pagesize = ATMEL_AT24C512_CHIP_SIZE;
+
+ nvcfg1 &= ~NVRAM_CFG1_COMPAT_BYPASS;
+ tw32(NVRAM_CFG1, nvcfg1);
+ return;
+ case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED:
+ case FLASH_57780VENDOR_ATMEL_AT45DB011D:
+ case FLASH_57780VENDOR_ATMEL_AT45DB011B:
+ case FLASH_57780VENDOR_ATMEL_AT45DB021D:
+ case FLASH_57780VENDOR_ATMEL_AT45DB021B:
+ case FLASH_57780VENDOR_ATMEL_AT45DB041D:
+ case FLASH_57780VENDOR_ATMEL_AT45DB041B:
+ tp->nvram_jedecnum = JEDEC_ATMEL;
+ tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+ tp->tg3_flags2 |= TG3_FLG2_FLASH;
+
+ switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+ case FLASH_5752VENDOR_ATMEL_FLASH_BUFFERED:
+ case FLASH_57780VENDOR_ATMEL_AT45DB011D:
+ case FLASH_57780VENDOR_ATMEL_AT45DB011B:
+ tp->nvram_size = TG3_NVRAM_SIZE_128KB;
+ break;
+ case FLASH_57780VENDOR_ATMEL_AT45DB021D:
+ case FLASH_57780VENDOR_ATMEL_AT45DB021B:
+ tp->nvram_size = TG3_NVRAM_SIZE_256KB;
+ break;
+ case FLASH_57780VENDOR_ATMEL_AT45DB041D:
+ case FLASH_57780VENDOR_ATMEL_AT45DB041B:
+ tp->nvram_size = TG3_NVRAM_SIZE_512KB;
+ break;
+ }
+ break;
+ case FLASH_5752VENDOR_ST_M45PE10:
+ case FLASH_5752VENDOR_ST_M45PE20:
+ case FLASH_5752VENDOR_ST_M45PE40:
+ tp->nvram_jedecnum = JEDEC_ST;
+ tp->tg3_flags |= TG3_FLAG_NVRAM_BUFFERED;
+ tp->tg3_flags2 |= TG3_FLG2_FLASH;
+
+ switch (nvcfg1 & NVRAM_CFG1_5752VENDOR_MASK) {
+ case FLASH_5752VENDOR_ST_M45PE10:
+ tp->nvram_size = TG3_NVRAM_SIZE_128KB;
+ break;
+ case FLASH_5752VENDOR_ST_M45PE20:
+ tp->nvram_size = TG3_NVRAM_SIZE_256KB;
+ break;
+ case FLASH_5752VENDOR_ST_M45PE40:
+ tp->nvram_size = TG3_NVRAM_SIZE_512KB;
+ break;
+ }
+ break;
+ default:
+ return;
+ }
+
+ switch (nvcfg1 & NVRAM_CFG1_5752PAGE_SIZE_MASK) {
+ case FLASH_5752PAGE_SIZE_256:
+ tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
+ tp->nvram_pagesize = 256;
+ break;
+ case FLASH_5752PAGE_SIZE_512:
+ tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
+ tp->nvram_pagesize = 512;
+ break;
+ case FLASH_5752PAGE_SIZE_1K:
+ tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
+ tp->nvram_pagesize = 1024;
+ break;
+ case FLASH_5752PAGE_SIZE_2K:
+ tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
+ tp->nvram_pagesize = 2048;
+ break;
+ case FLASH_5752PAGE_SIZE_4K:
+ tp->tg3_flags3 |= TG3_FLG3_NO_NVRAM_ADDR_TRANS;
+ tp->nvram_pagesize = 4096;
+ break;
+ case FLASH_5752PAGE_SIZE_264:
+ tp->nvram_pagesize = 264;
+ break;
+ case FLASH_5752PAGE_SIZE_528:
+ tp->nvram_pagesize = 528;
+ break;
+ }
+}
+
/* Chips other than 5700/5701 use the NVRAM for fetching info. */
static void __devinit tg3_nvram_init(struct tg3 *tp)
{
@@ -10796,6 +11048,8 @@ static void __devinit tg3_nvram_init(struct tg3 *tp)
tg3_get_5761_nvram_info(tp);
else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
tg3_get_5906_nvram_info(tp);
+ else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
+ tg3_get_57780_nvram_info(tp);
else
tg3_get_nvram_info(tp);
@@ -11116,12 +11370,8 @@ static int tg3_nvram_write_block_buffered(struct tg3 *tp, u32 offset, u32 len,
if (i == (len - 4))
nvram_cmd |= NVRAM_CMD_LAST;
- if ((GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752) &&
- (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5755) &&
- (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5787) &&
- (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784) &&
- (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5761) &&
- (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785) &&
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5752 &&
+ !(tp->tg3_flags3 & TG3_FLG3_5755_PLUS) &&
(tp->nvram_jedecnum == JEDEC_ST) &&
(nvram_cmd & NVRAM_CMD_FIRST)) {
@@ -11296,10 +11546,9 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
if (val & VCPU_CFGSHDW_ASPM_DBNC)
tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND;
if ((val & VCPU_CFGSHDW_WOL_ENABLE) &&
- (val & VCPU_CFGSHDW_WOL_MAGPKT) &&
- device_may_wakeup(&tp->pdev->dev))
+ (val & VCPU_CFGSHDW_WOL_MAGPKT))
tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
- return;
+ goto done;
}
tg3_read_mem(tp, NIC_SRAM_DATA_SIG, &val);
@@ -11421,15 +11670,17 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS)
tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE;
}
- if (nic_cfg & NIC_SRAM_DATA_CFG_APE_ENABLE)
+
+ if ((nic_cfg & NIC_SRAM_DATA_CFG_APE_ENABLE) &&
+ (tp->tg3_flags2 & TG3_FLG2_5750_PLUS))
tp->tg3_flags3 |= TG3_FLG3_ENABLE_APE;
+
if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES &&
!(nic_cfg & NIC_SRAM_DATA_CFG_FIBER_WOL))
tp->tg3_flags &= ~TG3_FLAG_WOL_CAP;
if ((tp->tg3_flags & TG3_FLAG_WOL_CAP) &&
- (nic_cfg & NIC_SRAM_DATA_CFG_WOL_ENABLE) &&
- device_may_wakeup(&tp->pdev->dev))
+ (nic_cfg & NIC_SRAM_DATA_CFG_WOL_ENABLE))
tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
if (cfg2 & (1 << 17))
@@ -11440,6 +11691,11 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
if (cfg2 & (1 << 18))
tp->tg3_flags2 |= TG3_FLG2_SERDES_PREEMPHASIS;
+ if (((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
+ GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX)) &&
+ (cfg2 & NIC_SRAM_DATA_CFG_2_APD_EN))
+ tp->tg3_flags3 |= TG3_FLG3_PHY_ENABLE_APD;
+
if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) {
u32 cfg3;
@@ -11455,6 +11711,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
if (cfg4 & NIC_SRAM_RGMII_EXT_IBND_TX_EN)
tp->tg3_flags3 |= TG3_FLG3_RGMII_EXT_IBND_TX_EN;
}
+done:
+ device_init_wakeup(&tp->pdev->dev, tp->tg3_flags & TG3_FLAG_WOL_CAP);
+ device_set_wakeup_enable(&tp->pdev->dev,
+ tp->tg3_flags & TG3_FLAG_WOL_ENABLE);
}
static int __devinit tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
@@ -11751,6 +12011,51 @@ static int __devinit tg3_fw_img_is_valid(struct tg3 *tp, u32 offset)
return 1;
}
+static void __devinit tg3_read_sb_ver(struct tg3 *tp, u32 val)
+{
+ u32 offset, major, minor, build;
+
+ tp->fw_ver[0] = 's';
+ tp->fw_ver[1] = 'b';
+ tp->fw_ver[2] = '\0';
+
+ if ((val & TG3_EEPROM_SB_FORMAT_MASK) != TG3_EEPROM_SB_FORMAT_1)
+ return;
+
+ switch (val & TG3_EEPROM_SB_REVISION_MASK) {
+ case TG3_EEPROM_SB_REVISION_0:
+ offset = TG3_EEPROM_SB_F1R0_EDH_OFF;
+ break;
+ case TG3_EEPROM_SB_REVISION_2:
+ offset = TG3_EEPROM_SB_F1R2_EDH_OFF;
+ break;
+ case TG3_EEPROM_SB_REVISION_3:
+ offset = TG3_EEPROM_SB_F1R3_EDH_OFF;
+ break;
+ default:
+ return;
+ }
+
+ if (tg3_nvram_read_swab(tp, offset, &val))
+ return;
+
+ build = (val & TG3_EEPROM_SB_EDH_BLD_MASK) >>
+ TG3_EEPROM_SB_EDH_BLD_SHFT;
+ major = (val & TG3_EEPROM_SB_EDH_MAJ_MASK) >>
+ TG3_EEPROM_SB_EDH_MAJ_SHFT;
+ minor = val & TG3_EEPROM_SB_EDH_MIN_MASK;
+
+ if (minor > 99 || build > 26)
+ return;
+
+ snprintf(&tp->fw_ver[2], 30, " v%d.%02d", major, minor);
+
+ if (build > 0) {
+ tp->fw_ver[8] = 'a' + build - 1;
+ tp->fw_ver[9] = '\0';
+ }
+}
+
static void __devinit tg3_read_fw_ver(struct tg3 *tp)
{
u32 val, offset, start;
@@ -11760,8 +12065,12 @@ static void __devinit tg3_read_fw_ver(struct tg3 *tp)
if (tg3_nvram_read_swab(tp, 0, &val))
return;
- if (val != TG3_EEPROM_MAGIC)
+ if (val != TG3_EEPROM_MAGIC) {
+ if ((val & TG3_EEPROM_MAGIC_FW_MSK) == TG3_EEPROM_MAGIC_FW)
+ tg3_read_sb_ver(tp, val);
+
return;
+ }
if (tg3_nvram_read_swab(tp, 0xc, &offset) ||
tg3_nvram_read_swab(tp, 0x4, &start))
@@ -11849,11 +12158,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
{ },
};
u32 misc_ctrl_reg;
- u32 cacheline_sz_reg;
u32 pci_state_reg, grc_misc_cfg;
u32 val;
u16 pci_cmd;
- int err, pcie_cap;
+ int err;
/* Force memory write invalidate off. If we leave it on,
* then on 5700_BX chips we have to enable a workaround.
@@ -11882,7 +12190,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
pci_read_config_dword(tp->pdev, TG3PCI_PRODID_ASICREV,
&prod_id_asic_rev);
- tp->pci_chip_rev_id = prod_id_asic_rev & PROD_ID_ASIC_REV_MASK;
+ tp->pci_chip_rev_id = prod_id_asic_rev;
}
/* Wrong chip ID in 5752 A0. This code can be removed later
@@ -12019,26 +12327,23 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
pci_write_config_dword(tp->pdev, TG3PCI_MISC_HOST_CTRL,
tp->misc_host_ctrl);
- pci_read_config_dword(tp->pdev, TG3PCI_CACHELINESZ,
- &cacheline_sz_reg);
-
- tp->pci_cacheline_sz = (cacheline_sz_reg >> 0) & 0xff;
- tp->pci_lat_timer = (cacheline_sz_reg >> 8) & 0xff;
- tp->pci_hdr_type = (cacheline_sz_reg >> 16) & 0xff;
- tp->pci_bist = (cacheline_sz_reg >> 24) & 0xff;
-
if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) ||
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714))
tp->pdev_peer = tg3_find_peer(tp);
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ /* Intentionally exclude ASIC_REV_5906 */
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
+ tp->tg3_flags3 |= TG3_FLG3_5755_PLUS;
+
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 ||
+ (tp->tg3_flags3 & TG3_FLG3_5755_PLUS) ||
(tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
tp->tg3_flags2 |= TG3_FLG2_5750_PLUS;
@@ -12046,6 +12351,18 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
(tp->tg3_flags2 & TG3_FLG2_5750_PLUS))
tp->tg3_flags2 |= TG3_FLG2_5705_PLUS;
+ /* 5700 B0 chips do not support checksumming correctly due
+ * to hardware bugs.
+ */
+ if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0)
+ tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS;
+ else {
+ tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
+ tp->dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+ if (tp->tg3_flags3 & TG3_FLG3_5755_PLUS)
+ tp->dev->features |= NETIF_F_IPV6_CSUM;
+ }
+
if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) {
tp->tg3_flags |= TG3_FLAG_SUPPORT_MSI;
if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX ||
@@ -12055,11 +12372,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tp->pdev_peer == tp->pdev))
tp->tg3_flags &= ~TG3_FLAG_SUPPORT_MSI;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+ if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
tp->tg3_flags2 |= TG3_FLG2_HW_TSO_2;
tp->tg3_flags2 |= TG3_FLG2_1SHOT_MSI;
@@ -12076,21 +12389,41 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
(tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
tp->tg3_flags2 |= TG3_FLG2_JUMBO_CAPABLE;
- pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
- if (pcie_cap != 0) {
+ pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
+ &pci_state_reg);
+
+ tp->pcie_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_EXP);
+ if (tp->pcie_cap != 0) {
+ u16 lnkctl;
+
tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
pcie_set_readrq(tp->pdev, 4096);
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
- u16 lnkctl;
-
- pci_read_config_word(tp->pdev,
- pcie_cap + PCI_EXP_LNKCTL,
- &lnkctl);
- if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN)
+ pci_read_config_word(tp->pdev,
+ tp->pcie_cap + PCI_EXP_LNKCTL,
+ &lnkctl);
+ if (lnkctl & PCI_EXP_LNKCTL_CLKREQ_EN) {
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
tp->tg3_flags2 &= ~TG3_FLG2_HW_TSO_2;
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
+ tp->tg3_flags3 |= TG3_FLG3_CLKREQ_BUG;
}
+ } else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+ tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
+ } else if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
+ (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
+ tp->pcix_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_PCIX);
+ if (!tp->pcix_cap) {
+ printk(KERN_ERR PFX "Cannot find PCI-X "
+ "capability, aborting.\n");
+ return -EIO;
+ }
+
+ if (!(pci_state_reg & PCISTATE_CONV_PCI_MODE))
+ tp->tg3_flags |= TG3_FLAG_PCIX_MODE;
}
/* If we have an AMD 762 or VIA K8T800 chipset, write
@@ -12103,42 +12436,29 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
!(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER;
+ pci_read_config_byte(tp->pdev, PCI_CACHE_LINE_SIZE,
+ &tp->pci_cacheline_sz);
+ pci_read_config_byte(tp->pdev, PCI_LATENCY_TIMER,
+ &tp->pci_lat_timer);
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 &&
tp->pci_lat_timer < 64) {
tp->pci_lat_timer = 64;
-
- cacheline_sz_reg = ((tp->pci_cacheline_sz & 0xff) << 0);
- cacheline_sz_reg |= ((tp->pci_lat_timer & 0xff) << 8);
- cacheline_sz_reg |= ((tp->pci_hdr_type & 0xff) << 16);
- cacheline_sz_reg |= ((tp->pci_bist & 0xff) << 24);
-
- pci_write_config_dword(tp->pdev, TG3PCI_CACHELINESZ,
- cacheline_sz_reg);
- }
-
- if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
- (tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
- tp->pcix_cap = pci_find_capability(tp->pdev, PCI_CAP_ID_PCIX);
- if (!tp->pcix_cap) {
- printk(KERN_ERR PFX "Cannot find PCI-X "
- "capability, aborting.\n");
- return -EIO;
- }
+ pci_write_config_byte(tp->pdev, PCI_LATENCY_TIMER,
+ tp->pci_lat_timer);
}
- pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE,
- &pci_state_reg);
-
- if (tp->pcix_cap && (pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0) {
- tp->tg3_flags |= TG3_FLAG_PCIX_MODE;
+ if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) {
+ /* 5700 BX chips need to have their TX producer index
+ * mailboxes written twice to workaround a bug.
+ */
+ tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG;
- /* If this is a 5700 BX chipset, and we are in PCI-X
- * mode, enable register write workaround.
+ /* If we are in PCI-X mode, enable register write workaround.
*
* The workaround is to use indirect register accesses
* for all chip writes not to mailbox registers.
*/
- if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX) {
+ if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) {
u32 pm_reg;
tp->tg3_flags |= TG3_FLAG_PCIX_TARGET_HWBUG;
@@ -12163,12 +12483,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
}
}
- /* 5700 BX chips need to have their TX producer index mailboxes
- * written twice to workaround a bug.
- */
- if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5700_BX)
- tp->tg3_flags |= TG3_FLAG_TXD_MBOX_HWBUG;
-
if ((pci_state_reg & PCISTATE_BUS_SPEED_HIGH) != 0)
tp->tg3_flags |= TG3_FLAG_PCI_HIGH_SPEED;
if ((pci_state_reg & PCISTATE_BUS_32BIT) != 0)
@@ -12263,16 +12577,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
tp->tg3_flags |= TG3_FLAG_CPMU_PRESENT;
- if (tp->pci_chip_rev_id == CHIPREV_ID_5784_A0 ||
- tp->pci_chip_rev_id == CHIPREV_ID_5784_A1 ||
- tp->pci_chip_rev_id == CHIPREV_ID_5761_A0 ||
- tp->pci_chip_rev_id == CHIPREV_ID_5761_A1)
- tp->tg3_flags3 |= TG3_FLG3_5761_5784_AX_FIXES;
- }
-
/* Set up tp->grc_local_ctrl before calling tg3_set_power_state().
* GPIO1 driven high will bring 5700's external PHY out of reset.
* It is also used as eeprom write protect on LOMs.
@@ -12288,7 +12596,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
else if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5752)
tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755)
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
tp->grc_local_ctrl |= GRC_LCLCTRL_GPIO_UART_SEL;
if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761) {
@@ -12308,12 +12617,6 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
return err;
}
- /* 5700 B0 chips do not support checksumming correctly due
- * to hardware bugs.
- */
- if (tp->pci_chip_rev_id == CHIPREV_ID_5700_B0)
- tp->tg3_flags |= TG3_FLAG_BROKEN_CHECKSUMS;
-
/* Derive initial jumbo mode from MTU assigned in
* ether_setup() via the alloc_etherdev() call
*/
@@ -12346,7 +12649,10 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (tp->pci_chip_rev_id == CHIPREV_ID_5704_A0)
tp->tg3_flags2 |= TG3_FLG2_PHY_5704_A0_BUG;
- if (tp->tg3_flags2 & TG3_FLG2_5705_PLUS) {
+ if ((tp->tg3_flags2 & TG3_FLG2_5705_PLUS) &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785 &&
+ GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_57780) {
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
@@ -12356,8 +12662,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
tp->tg3_flags2 |= TG3_FLG2_PHY_JITTER_BUG;
if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5755M)
tp->tg3_flags2 |= TG3_FLG2_PHY_ADJUST_TRIM;
- } else if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906 &&
- GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785)
+ } else
tp->tg3_flags2 |= TG3_FLG2_PHY_BER_BUG;
}
@@ -12378,7 +12683,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5700_BX)
tp->coalesce_mode |= HOSTCC_MODE_32BYTE;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+ if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
tp->tg3_flags3 |= TG3_FLG3_USE_PHYLIB;
err = tg3_mdio_init(tp);
@@ -12463,6 +12769,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
(tp->pdev->device == PCI_DEVICE_ID_TIGON3_5751F ||
tp->pdev->device == PCI_DEVICE_ID_TIGON3_5753F ||
tp->pdev->device == PCI_DEVICE_ID_TIGON3_5787F)) ||
+ tp->pdev->device == TG3PCI_DEVICE_TIGON3_57790 ||
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
tp->tg3_flags |= TG3_FLAG_10_100_ONLY;
@@ -12512,20 +12819,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
else
tp->tg3_flags &= ~TG3_FLAG_POLL_SERDES;
- /* All chips before 5787 can get confused if TX buffers
- * straddle the 4GB address boundary in some cases.
- */
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
- tp->dev->hard_start_xmit = tg3_start_xmit;
- else
- tp->dev->hard_start_xmit = tg3_start_xmit_dma_bug;
-
- tp->rx_offset = 2;
+ tp->rx_offset = NET_IP_ALIGN;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701 &&
(tp->tg3_flags & TG3_FLAG_PCIX_MODE) != 0)
tp->rx_offset = 0;
@@ -13241,18 +13535,53 @@ static void __devinit tg3_init_coal(struct tg3 *tp)
}
}
+static const struct net_device_ops tg3_netdev_ops = {
+ .ndo_open = tg3_open,
+ .ndo_stop = tg3_close,
+ .ndo_start_xmit = tg3_start_xmit,
+ .ndo_get_stats = tg3_get_stats,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_multicast_list = tg3_set_rx_mode,
+ .ndo_set_mac_address = tg3_set_mac_addr,
+ .ndo_do_ioctl = tg3_ioctl,
+ .ndo_tx_timeout = tg3_tx_timeout,
+ .ndo_change_mtu = tg3_change_mtu,
+#if TG3_VLAN_TAG_USED
+ .ndo_vlan_rx_register = tg3_vlan_rx_register,
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = tg3_poll_controller,
+#endif
+};
+
+static const struct net_device_ops tg3_netdev_ops_dma_bug = {
+ .ndo_open = tg3_open,
+ .ndo_stop = tg3_close,
+ .ndo_start_xmit = tg3_start_xmit_dma_bug,
+ .ndo_get_stats = tg3_get_stats,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_multicast_list = tg3_set_rx_mode,
+ .ndo_set_mac_address = tg3_set_mac_addr,
+ .ndo_do_ioctl = tg3_ioctl,
+ .ndo_tx_timeout = tg3_tx_timeout,
+ .ndo_change_mtu = tg3_change_mtu,
+#if TG3_VLAN_TAG_USED
+ .ndo_vlan_rx_register = tg3_vlan_rx_register,
+#endif
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = tg3_poll_controller,
+#endif
+};
+
static int __devinit tg3_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
static int tg3_version_printed = 0;
- resource_size_t tg3reg_base;
- unsigned long tg3reg_len;
struct net_device *dev;
struct tg3 *tp;
int err, pm_cap;
char str[40];
u64 dma_mask, persist_dma_mask;
- DECLARE_MAC_BUF(mac);
if (tg3_version_printed++ == 0)
printk(KERN_INFO "%s", version);
@@ -13264,13 +13593,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
return err;
}
- if (!(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
- printk(KERN_ERR PFX "Cannot find proper PCI device "
- "base address, aborting.\n");
- err = -ENODEV;
- goto err_out_disable_pdev;
- }
-
err = pci_request_regions(pdev, DRV_MODULE_NAME);
if (err) {
printk(KERN_ERR PFX "Cannot obtain PCI resources, "
@@ -13289,9 +13611,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
goto err_out_free_res;
}
- tg3reg_base = pci_resource_start(pdev, 0);
- tg3reg_len = pci_resource_len(pdev, 0);
-
dev = alloc_etherdev(sizeof(*tp));
if (!dev) {
printk(KERN_ERR PFX "Etherdev alloc failed, aborting.\n");
@@ -13303,7 +13622,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
#if TG3_VLAN_TAG_USED
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
- dev->vlan_rx_register = tg3_vlan_rx_register;
#endif
tp = netdev_priv(dev);
@@ -13343,7 +13661,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
spin_lock_init(&tp->indirect_lock);
INIT_WORK(&tp->reset_task, tg3_reset_task);
- tp->regs = ioremap_nocache(tg3reg_base, tg3reg_len);
+ tp->regs = pci_ioremap_bar(pdev, BAR_0);
if (!tp->regs) {
printk(KERN_ERR PFX "Cannot map device registers, "
"aborting.\n");
@@ -13357,21 +13675,10 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
tp->rx_jumbo_pending = TG3_DEF_RX_JUMBO_RING_PENDING;
tp->tx_pending = TG3_DEF_TX_RING_PENDING;
- dev->open = tg3_open;
- dev->stop = tg3_close;
- dev->get_stats = tg3_get_stats;
- dev->set_multicast_list = tg3_set_rx_mode;
- dev->set_mac_address = tg3_set_mac_addr;
- dev->do_ioctl = tg3_ioctl;
- dev->tx_timeout = tg3_tx_timeout;
netif_napi_add(dev, &tp->napi, tg3_poll, 64);
dev->ethtool_ops = &tg3_ethtool_ops;
dev->watchdog_timeo = TG3_TX_TIMEOUT;
- dev->change_mtu = tg3_change_mtu;
dev->irq = pdev->irq;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = tg3_poll_controller;
-#endif
err = tg3_get_invariants(tp);
if (err) {
@@ -13380,6 +13687,13 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
goto err_out_iounmap;
}
+ if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
+ dev->netdev_ops = &tg3_netdev_ops;
+ else
+ dev->netdev_ops = &tg3_netdev_ops_dma_bug;
+
+
/* The EPB bridge inside 5714, 5715, and 5780 and any
* device behind the EPB cannot support DMA addresses > 40-bit.
* On 64-bit systems with IOMMU, use 40-bit dma_mask.
@@ -13439,14 +13753,16 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
* is off by default, but can be enabled using ethtool.
*/
if (tp->tg3_flags2 & TG3_FLG2_HW_TSO) {
- dev->features |= NETIF_F_TSO;
- if ((tp->tg3_flags2 & TG3_FLG2_HW_TSO_2) &&
- (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906))
+ if (dev->features & NETIF_F_IP_CSUM)
+ dev->features |= NETIF_F_TSO;
+ if ((dev->features & NETIF_F_IPV6_CSUM) &&
+ (tp->tg3_flags2 & TG3_FLG2_HW_TSO_2))
dev->features |= NETIF_F_TSO6;
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
(GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785 ||
+ GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780)
dev->features |= NETIF_F_TSO_ECN;
}
@@ -13466,17 +13782,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
}
if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) {
- if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) {
- printk(KERN_ERR PFX "Cannot find proper PCI device "
- "base address for APE, aborting.\n");
- err = -ENODEV;
- goto err_out_iounmap;
- }
-
- tg3reg_base = pci_resource_start(pdev, 2);
- tg3reg_len = pci_resource_len(pdev, 2);
-
- tp->aperegs = ioremap_nocache(tg3reg_base, tg3reg_len);
+ tp->aperegs = pci_ioremap_bar(pdev, BAR_2);
if (!tp->aperegs) {
printk(KERN_ERR PFX "Cannot map APE registers, "
"aborting.\n");
@@ -13504,25 +13810,9 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
goto err_out_apeunmap;
}
- /* Tigon3 can do ipv4 only... and some chips have buggy
- * checksumming.
- */
- if ((tp->tg3_flags & TG3_FLAG_BROKEN_CHECKSUMS) == 0) {
- dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
- if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5755 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5787 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761 ||
- GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
- dev->features |= NETIF_F_IPV6_CSUM;
-
- tp->tg3_flags |= TG3_FLAG_RX_CHECKSUMS;
- } else
- tp->tg3_flags &= ~TG3_FLAG_RX_CHECKSUMS;
-
/* flow control autonegotiation is default behavior */
tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
- tp->link_config.flowctrl = TG3_FLOW_CTRL_TX | TG3_FLOW_CTRL_RX;
+ tp->link_config.flowctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
tg3_init_coal(tp);
@@ -13535,26 +13825,34 @@ static int __devinit tg3_init_one(struct pci_dev *pdev,
goto err_out_apeunmap;
}
- printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] "
- "(%s) %s Ethernet %s\n",
+ printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x] (%s) MAC address %pM\n",
dev->name,
tp->board_part_number,
tp->pci_chip_rev_id,
- tg3_phy_string(tp),
tg3_bus_string(tp, str),
- ((tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100Base-TX" :
- ((tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) ? "1000Base-SX" :
- "10/100/1000Base-T")),
- print_mac(mac, dev->dev_addr));
+ dev->dev_addr);
- printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] "
- "MIirq[%d] ASF[%d] WireSpeed[%d] TSOcap[%d]\n",
+ if (tp->tg3_flags3 & TG3_FLG3_PHY_CONNECTED)
+ printk(KERN_INFO
+ "%s: attached PHY driver [%s] (mii_bus:phy_addr=%s)\n",
+ tp->dev->name,
+ tp->mdio_bus->phy_map[PHY_ADDR]->drv->name,
+ dev_name(&tp->mdio_bus->phy_map[PHY_ADDR]->dev));
+ else
+ printk(KERN_INFO
+ "%s: attached PHY is %s (%s Ethernet) (WireSpeed[%d])\n",
+ tp->dev->name, tg3_phy_string(tp),
+ ((tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100Base-TX" :
+ ((tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) ? "1000Base-SX" :
+ "10/100/1000Base-T")),
+ (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0);
+
+ printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] MIirq[%d] ASF[%d] TSOcap[%d]\n",
dev->name,
(tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0,
(tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0,
(tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0,
(tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0,
- (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) == 0,
(tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) != 0);
printk(KERN_INFO "%s: dma_rwctrl[%08x] dma_mask[%d-bit]\n",
dev->name, tp->dma_rwctrl,
diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h
index be252abe8985..8936edfb0438 100644
--- a/drivers/net/tg3.h
+++ b/drivers/net/tg3.h
@@ -38,26 +38,13 @@
#define TG3PCI_DEVICE_TIGON3_2 0x1645 /* BCM5701 */
#define TG3PCI_DEVICE_TIGON3_3 0x1646 /* BCM5702 */
#define TG3PCI_DEVICE_TIGON3_4 0x1647 /* BCM5703 */
-#define TG3PCI_COMMAND 0x00000004
-#define TG3PCI_STATUS 0x00000006
-#define TG3PCI_CCREVID 0x00000008
-#define TG3PCI_CACHELINESZ 0x0000000c
-#define TG3PCI_LATTIMER 0x0000000d
-#define TG3PCI_HEADERTYPE 0x0000000e
-#define TG3PCI_BIST 0x0000000f
-#define TG3PCI_BASE0_LOW 0x00000010
-#define TG3PCI_BASE0_HIGH 0x00000014
-/* 0x18 --> 0x2c unused */
-#define TG3PCI_SUBSYSVENID 0x0000002c
-#define TG3PCI_SUBSYSID 0x0000002e
-#define TG3PCI_ROMADDR 0x00000030
-#define TG3PCI_CAPLIST 0x00000034
-/* 0x35 --> 0x3c unused */
-#define TG3PCI_IRQ_LINE 0x0000003c
-#define TG3PCI_IRQ_PIN 0x0000003d
-#define TG3PCI_MIN_GNT 0x0000003e
-#define TG3PCI_MAX_LAT 0x0000003f
-/* 0x40 --> 0x64 unused */
+#define TG3PCI_DEVICE_TIGON3_5761S 0x1688
+#define TG3PCI_DEVICE_TIGON3_5761SE 0x1689
+#define TG3PCI_DEVICE_TIGON3_57780 0x1692
+#define TG3PCI_DEVICE_TIGON3_57760 0x1690
+#define TG3PCI_DEVICE_TIGON3_57790 0x1694
+#define TG3PCI_DEVICE_TIGON3_57720 0x168c
+/* 0x04 --> 0x64 unused */
#define TG3PCI_MSI_DATA 0x00000064
/* 0x66 --> 0x68 unused */
#define TG3PCI_MISC_HOST_CTRL 0x00000068
@@ -108,10 +95,6 @@
#define CHIPREV_ID_5752_A1 0x6001
#define CHIPREV_ID_5714_A2 0x9002
#define CHIPREV_ID_5906_A1 0xc001
-#define CHIPREV_ID_5784_A0 0x5784000
-#define CHIPREV_ID_5784_A1 0x5784001
-#define CHIPREV_ID_5761_A0 0x5761000
-#define CHIPREV_ID_5761_A1 0x5761001
#define GET_ASIC_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 12)
#define ASIC_REV_5700 0x07
#define ASIC_REV_5701 0x00
@@ -129,6 +112,7 @@
#define ASIC_REV_5784 0x5784
#define ASIC_REV_5761 0x5761
#define ASIC_REV_5785 0x5785
+#define ASIC_REV_57780 0x57780
#define GET_CHIP_REV(CHIP_REV_ID) ((CHIP_REV_ID) >> 8)
#define CHIPREV_5700_AX 0x70
#define CHIPREV_5700_BX 0x71
@@ -325,6 +309,7 @@
#define MAC_MODE_TDE_ENABLE 0x00200000
#define MAC_MODE_RDE_ENABLE 0x00400000
#define MAC_MODE_FHDE_ENABLE 0x00800000
+#define MAC_MODE_KEEP_FRAME_IN_WOL 0x01000000
#define MAC_MODE_APE_RX_EN 0x08000000
#define MAC_MODE_APE_TX_EN 0x10000000
#define MAC_STATUS 0x00000404
@@ -414,6 +399,7 @@
#define MI_COM_DATA_MASK 0x0000ffff
#define MAC_MI_STAT 0x00000450
#define MAC_MI_STAT_LNKSTAT_ATTN_ENAB 0x00000001
+#define MAC_MI_STAT_10MBPS_MODE 0x00000002
#define MAC_MI_MODE 0x00000454
#define MAC_MI_MODE_CLK_10MHZ 0x00000001
#define MAC_MI_MODE_SHORT_PREAMBLE 0x00000002
@@ -539,6 +525,100 @@
#define MAC_PHYCFG1_TXC_DRV 0x20000000
#define MAC_PHYCFG2 0x000005a4
#define MAC_PHYCFG2_INBAND_ENABLE 0x00000001
+#define MAC_PHYCFG2_EMODE_MASK_MASK 0x000001c0
+#define MAC_PHYCFG2_EMODE_MASK_AC131 0x000000c0
+#define MAC_PHYCFG2_EMODE_MASK_50610 0x00000100
+#define MAC_PHYCFG2_EMODE_MASK_RT8211 0x00000000
+#define MAC_PHYCFG2_EMODE_MASK_RT8201 0x000001c0
+#define MAC_PHYCFG2_EMODE_COMP_MASK 0x00000e00
+#define MAC_PHYCFG2_EMODE_COMP_AC131 0x00000600
+#define MAC_PHYCFG2_EMODE_COMP_50610 0x00000400
+#define MAC_PHYCFG2_EMODE_COMP_RT8211 0x00000800
+#define MAC_PHYCFG2_EMODE_COMP_RT8201 0x00000000
+#define MAC_PHYCFG2_FMODE_MASK_MASK 0x00007000
+#define MAC_PHYCFG2_FMODE_MASK_AC131 0x00006000
+#define MAC_PHYCFG2_FMODE_MASK_50610 0x00004000
+#define MAC_PHYCFG2_FMODE_MASK_RT8211 0x00000000
+#define MAC_PHYCFG2_FMODE_MASK_RT8201 0x00007000
+#define MAC_PHYCFG2_FMODE_COMP_MASK 0x00038000
+#define MAC_PHYCFG2_FMODE_COMP_AC131 0x00030000
+#define MAC_PHYCFG2_FMODE_COMP_50610 0x00008000
+#define MAC_PHYCFG2_FMODE_COMP_RT8211 0x00038000
+#define MAC_PHYCFG2_FMODE_COMP_RT8201 0x00000000
+#define MAC_PHYCFG2_GMODE_MASK_MASK 0x001c0000
+#define MAC_PHYCFG2_GMODE_MASK_AC131 0x001c0000
+#define MAC_PHYCFG2_GMODE_MASK_50610 0x00100000
+#define MAC_PHYCFG2_GMODE_MASK_RT8211 0x00000000
+#define MAC_PHYCFG2_GMODE_MASK_RT8201 0x001c0000
+#define MAC_PHYCFG2_GMODE_COMP_MASK 0x00e00000
+#define MAC_PHYCFG2_GMODE_COMP_AC131 0x00e00000
+#define MAC_PHYCFG2_GMODE_COMP_50610 0x00000000
+#define MAC_PHYCFG2_GMODE_COMP_RT8211 0x00200000
+#define MAC_PHYCFG2_GMODE_COMP_RT8201 0x00000000
+#define MAC_PHYCFG2_ACT_MASK_MASK 0x03000000
+#define MAC_PHYCFG2_ACT_MASK_AC131 0x03000000
+#define MAC_PHYCFG2_ACT_MASK_50610 0x01000000
+#define MAC_PHYCFG2_ACT_MASK_RT8211 0x03000000
+#define MAC_PHYCFG2_ACT_MASK_RT8201 0x01000000
+#define MAC_PHYCFG2_ACT_COMP_MASK 0x0c000000
+#define MAC_PHYCFG2_ACT_COMP_AC131 0x00000000
+#define MAC_PHYCFG2_ACT_COMP_50610 0x00000000
+#define MAC_PHYCFG2_ACT_COMP_RT8211 0x00000000
+#define MAC_PHYCFG2_ACT_COMP_RT8201 0x08000000
+#define MAC_PHYCFG2_QUAL_MASK_MASK 0x30000000
+#define MAC_PHYCFG2_QUAL_MASK_AC131 0x30000000
+#define MAC_PHYCFG2_QUAL_MASK_50610 0x30000000
+#define MAC_PHYCFG2_QUAL_MASK_RT8211 0x30000000
+#define MAC_PHYCFG2_QUAL_MASK_RT8201 0x30000000
+#define MAC_PHYCFG2_QUAL_COMP_MASK 0xc0000000
+#define MAC_PHYCFG2_QUAL_COMP_AC131 0x00000000
+#define MAC_PHYCFG2_QUAL_COMP_50610 0x00000000
+#define MAC_PHYCFG2_QUAL_COMP_RT8211 0x00000000
+#define MAC_PHYCFG2_QUAL_COMP_RT8201 0x00000000
+#define MAC_PHYCFG2_50610_LED_MODES \
+ (MAC_PHYCFG2_EMODE_MASK_50610 | \
+ MAC_PHYCFG2_EMODE_COMP_50610 | \
+ MAC_PHYCFG2_FMODE_MASK_50610 | \
+ MAC_PHYCFG2_FMODE_COMP_50610 | \
+ MAC_PHYCFG2_GMODE_MASK_50610 | \
+ MAC_PHYCFG2_GMODE_COMP_50610 | \
+ MAC_PHYCFG2_ACT_MASK_50610 | \
+ MAC_PHYCFG2_ACT_COMP_50610 | \
+ MAC_PHYCFG2_QUAL_MASK_50610 | \
+ MAC_PHYCFG2_QUAL_COMP_50610)
+#define MAC_PHYCFG2_AC131_LED_MODES \
+ (MAC_PHYCFG2_EMODE_MASK_AC131 | \
+ MAC_PHYCFG2_EMODE_COMP_AC131 | \
+ MAC_PHYCFG2_FMODE_MASK_AC131 | \
+ MAC_PHYCFG2_FMODE_COMP_AC131 | \
+ MAC_PHYCFG2_GMODE_MASK_AC131 | \
+ MAC_PHYCFG2_GMODE_COMP_AC131 | \
+ MAC_PHYCFG2_ACT_MASK_AC131 | \
+ MAC_PHYCFG2_ACT_COMP_AC131 | \
+ MAC_PHYCFG2_QUAL_MASK_AC131 | \
+ MAC_PHYCFG2_QUAL_COMP_AC131)
+#define MAC_PHYCFG2_RTL8211C_LED_MODES \
+ (MAC_PHYCFG2_EMODE_MASK_RT8211 | \
+ MAC_PHYCFG2_EMODE_COMP_RT8211 | \
+ MAC_PHYCFG2_FMODE_MASK_RT8211 | \
+ MAC_PHYCFG2_FMODE_COMP_RT8211 | \
+ MAC_PHYCFG2_GMODE_MASK_RT8211 | \
+ MAC_PHYCFG2_GMODE_COMP_RT8211 | \
+ MAC_PHYCFG2_ACT_MASK_RT8211 | \
+ MAC_PHYCFG2_ACT_COMP_RT8211 | \
+ MAC_PHYCFG2_QUAL_MASK_RT8211 | \
+ MAC_PHYCFG2_QUAL_COMP_RT8211)
+#define MAC_PHYCFG2_RTL8201E_LED_MODES \
+ (MAC_PHYCFG2_EMODE_MASK_RT8201 | \
+ MAC_PHYCFG2_EMODE_COMP_RT8201 | \
+ MAC_PHYCFG2_FMODE_MASK_RT8201 | \
+ MAC_PHYCFG2_FMODE_COMP_RT8201 | \
+ MAC_PHYCFG2_GMODE_MASK_RT8201 | \
+ MAC_PHYCFG2_GMODE_COMP_RT8201 | \
+ MAC_PHYCFG2_ACT_MASK_RT8201 | \
+ MAC_PHYCFG2_ACT_COMP_RT8201 | \
+ MAC_PHYCFG2_QUAL_MASK_RT8201 | \
+ MAC_PHYCFG2_QUAL_COMP_RT8201)
#define MAC_EXT_RGMII_MODE 0x000005a8
#define MAC_RGMII_MODE_TX_ENABLE 0x00000001
#define MAC_RGMII_MODE_TX_LOWPWR 0x00000002
@@ -1104,6 +1184,8 @@
#define RDMAC_MODE_MBUF_SBD_CRPT_ENAB 0x00002000
#define RDMAC_MODE_FIFO_SIZE_128 0x00020000
#define RDMAC_MODE_FIFO_LONG_BURST 0x00030000
+#define RDMAC_MODE_IPV4_LSO_EN 0x08000000
+#define RDMAC_MODE_IPV6_LSO_EN 0x10000000
#define RDMAC_STATUS 0x00004804
#define RDMAC_STATUS_TGTABORT 0x00000004
#define RDMAC_STATUS_MSTABORT 0x00000008
@@ -1550,6 +1632,12 @@
#define FLASH_5761VENDOR_ST_A_M45PE40 0x02000000
#define FLASH_5761VENDOR_ST_A_M45PE80 0x02000002
#define FLASH_5761VENDOR_ST_A_M45PE16 0x02000003
+#define FLASH_57780VENDOR_ATMEL_AT45DB011D 0x00400000
+#define FLASH_57780VENDOR_ATMEL_AT45DB011B 0x03400000
+#define FLASH_57780VENDOR_ATMEL_AT45DB021D 0x00400002
+#define FLASH_57780VENDOR_ATMEL_AT45DB021B 0x03400002
+#define FLASH_57780VENDOR_ATMEL_AT45DB041D 0x00400001
+#define FLASH_57780VENDOR_ATMEL_AT45DB041B 0x03400001
#define NVRAM_CFG1_5752PAGE_SIZE_MASK 0x70000000
#define FLASH_5752PAGE_SIZE_256 0x00000000
#define FLASH_5752PAGE_SIZE_512 0x10000000
@@ -1557,6 +1645,7 @@
#define FLASH_5752PAGE_SIZE_2K 0x30000000
#define FLASH_5752PAGE_SIZE_4K 0x40000000
#define FLASH_5752PAGE_SIZE_264 0x50000000
+#define FLASH_5752PAGE_SIZE_528 0x60000000
#define NVRAM_CFG2 0x00007018
#define NVRAM_CFG3 0x0000701c
#define NVRAM_SWARB 0x00007020
@@ -1649,6 +1738,17 @@
#define TG3_NVM_DIRTYPE_SHIFT 24
#define TG3_NVM_DIRTYPE_ASFINI 1
+#define TG3_EEPROM_SB_F1R0_EDH_OFF 0x10
+#define TG3_EEPROM_SB_F1R2_EDH_OFF 0x14
+#define TG3_EEPROM_SB_F1R2_MBA_OFF 0x10
+#define TG3_EEPROM_SB_F1R3_EDH_OFF 0x18
+#define TG3_EEPROM_SB_EDH_MAJ_MASK 0x00000700
+#define TG3_EEPROM_SB_EDH_MAJ_SHFT 8
+#define TG3_EEPROM_SB_EDH_MIN_MASK 0x000000ff
+#define TG3_EEPROM_SB_EDH_BLD_MASK 0x0000f800
+#define TG3_EEPROM_SB_EDH_BLD_SHFT 11
+
+
/* 32K Window into NIC internal memory */
#define NIC_SRAM_WIN_BASE 0x00008000
@@ -1724,6 +1824,7 @@
#define NIC_SRAM_DATA_CFG_2 0x00000d38
+#define NIC_SRAM_DATA_CFG_2_APD_EN 0x00000400
#define SHASTA_EXT_LED_MODE_MASK 0x00018000
#define SHASTA_EXT_LED_LEGACY 0x00000000
#define SHASTA_EXT_LED_SHARED 0x00008000
@@ -1792,6 +1893,11 @@
#define MII_TG3_AUX_CTRL 0x18 /* auxilliary control register */
+#define MII_TG3_AUXCTL_PCTL_100TX_LPWR 0x0010
+#define MII_TG3_AUXCTL_PCTL_SPR_ISOLATE 0x0020
+#define MII_TG3_AUXCTL_PCTL_VREG_11V 0x0180
+#define MII_TG3_AUXCTL_SHDWSEL_PWRCTL 0x0002
+
#define MII_TG3_AUXCTL_MISC_WREN 0x8000
#define MII_TG3_AUXCTL_MISC_FORCE_AMDIX 0x0200
#define MII_TG3_AUXCTL_MISC_RDSEL_MISC 0x7000
@@ -1817,12 +1923,6 @@
#define MII_TG3_ISTAT 0x1a /* IRQ status register */
#define MII_TG3_IMASK 0x1b /* IRQ mask register */
-#define MII_TG3_MISC_SHDW 0x1c
-#define MII_TG3_MISC_SHDW_WREN 0x8000
-#define MII_TG3_MISC_SHDW_APD_SEL 0x2800
-
-#define MII_TG3_MISC_SHDW_APD_WKTM_84MS 0x0001
-
/* ISTAT/IMASK event bits */
#define MII_TG3_INT_LINKCHG 0x0002
#define MII_TG3_INT_SPEEDCHG 0x0004
@@ -1831,7 +1931,9 @@
#define MII_TG3_MISC_SHDW 0x1c
#define MII_TG3_MISC_SHDW_WREN 0x8000
-#define MII_TG3_MISC_SHDW_SCR5_SEL 0x1400
+
+#define MII_TG3_MISC_SHDW_APD_WKTM_84MS 0x0001
+#define MII_TG3_MISC_SHDW_APD_ENABLE 0x0020
#define MII_TG3_MISC_SHDW_APD_SEL 0x2800
#define MII_TG3_MISC_SHDW_SCR5_C125OE 0x0001
@@ -1839,9 +1941,8 @@
#define MII_TG3_MISC_SHDW_SCR5_SDTL 0x0004
#define MII_TG3_MISC_SHDW_SCR5_DLPTLM 0x0008
#define MII_TG3_MISC_SHDW_SCR5_LPED 0x0010
+#define MII_TG3_MISC_SHDW_SCR5_SEL 0x1400
-#define MII_TG3_MISC_SHDW_APD_WKTM_84MS 0x0001
-#define MII_TG3_MISC_SHDW_APD_ENABLE 0x0020
#define MII_TG3_EPHY_TEST 0x1f /* 5906 PHY register */
#define MII_TG3_EPHY_SHADOW_EN 0x80
@@ -2211,8 +2312,6 @@ struct tg3_link_config {
u8 duplex;
u8 autoneg;
u8 flowctrl;
-#define TG3_FLOW_CTRL_TX 0x01
-#define TG3_FLOW_CTRL_RX 0x02
/* Describes what we actually have. */
u8 active_flowctrl;
@@ -2507,7 +2606,6 @@ struct tg3 {
u32 tg3_flags3;
#define TG3_FLG3_NO_NVRAM_ADDR_TRANS 0x00000001
#define TG3_FLG3_ENABLE_APE 0x00000002
-#define TG3_FLG3_5761_5784_AX_FIXES 0x00000004
#define TG3_FLG3_5701_DMA_BUG 0x00000008
#define TG3_FLG3_USE_PHYLIB 0x00000010
#define TG3_FLG3_MDIOBUS_INITED 0x00000020
@@ -2516,6 +2614,9 @@ struct tg3 {
#define TG3_FLG3_RGMII_STD_IBND_DISABLE 0x00000100
#define TG3_FLG3_RGMII_EXT_IBND_RX_EN 0x00000200
#define TG3_FLG3_RGMII_EXT_IBND_TX_EN 0x00000400
+#define TG3_FLG3_CLKREQ_BUG 0x00000800
+#define TG3_FLG3_PHY_ENABLE_APD 0x00001000
+#define TG3_FLG3_5755_PLUS 0x00002000
struct timer_list timer;
u16 timer_counter;
@@ -2547,14 +2648,16 @@ struct tg3 {
/* PCI block */
u32 pci_chip_rev_id;
+ u16 pci_cmd;
u8 pci_cacheline_sz;
u8 pci_lat_timer;
- u8 pci_hdr_type;
- u8 pci_bist;
int pm_cap;
int msi_cap;
+ union {
int pcix_cap;
+ int pcie_cap;
+ };
struct mii_bus *mdio_bus;
int mdio_irq[PHY_MAX_ADDR];
@@ -2588,11 +2691,16 @@ struct tg3 {
#define PHY_REV_BCM5411_X0 0x1 /* Found on Netgear GA302T */
#define TG3_PHY_ID_BCM50610 0x143bd60
#define TG3_PHY_ID_BCMAC131 0x143bc70
-
+#define TG3_PHY_ID_RTL8211C 0x001cc910
+#define TG3_PHY_ID_RTL8201E 0x00008200
+#define TG3_PHY_ID_BCM57780 0x03625d90
+#define TG3_PHY_OUI_MASK 0xfffffc00
+#define TG3_PHY_OUI_1 0x00206000
+#define TG3_PHY_OUI_2 0x0143bc00
+#define TG3_PHY_OUI_3 0x03625c00
u32 led_ctrl;
u32 phy_otp;
- u16 pci_cmd;
char board_part_number[24];
#define TG3_VER_SIZE 32
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c
index c41d68761364..85ef8b744557 100644
--- a/drivers/net/tlan.c
+++ b/drivers/net/tlan.c
@@ -163,6 +163,11 @@
* v1.15 Apr 4, 2002 - Correct operation when aui=1 to be
* 10T half duplex no loopback
* Thanks to Gunnar Eikman
+ *
+ * Sakari Ailus <sakari.ailus@iki.fi>:
+ *
+ * v1.15a Dec 15 2008 - Remove bbuf support, it doesn't work anyway.
+ *
*******************************************************************************/
#include <linux/module.h>
@@ -213,12 +218,8 @@ static int debug;
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "ThunderLAN debug mask");
-static int bbuf;
-module_param(bbuf, int, 0);
-MODULE_PARM_DESC(bbuf, "ThunderLAN use big buffer (0-1)");
-
static const char TLanSignature[] = "TLAN";
-static const char tlan_banner[] = "ThunderLAN driver v1.15\n";
+static const char tlan_banner[] = "ThunderLAN driver v1.15a\n";
static int tlan_have_pci;
static int tlan_have_eisa;
@@ -859,13 +860,8 @@ static int TLan_Init( struct net_device *dev )
priv = netdev_priv(dev);
- if ( bbuf ) {
- dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS )
- * ( sizeof(TLanList) + TLAN_MAX_FRAME_SIZE );
- } else {
- dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS )
- * ( sizeof(TLanList) );
- }
+ dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS )
+ * ( sizeof(TLanList) );
priv->dmaStorage = pci_alloc_consistent(priv->pciDev,
dma_size, &priv->dmaStorageDMA);
priv->dmaSize = dma_size;
@@ -881,16 +877,6 @@ static int TLan_Init( struct net_device *dev )
priv->txList = priv->rxList + TLAN_NUM_RX_LISTS;
priv->txListDMA = priv->rxListDMA + sizeof(TLanList) * TLAN_NUM_RX_LISTS;
- if ( bbuf ) {
- priv->rxBuffer = (u8 *) ( priv->txList + TLAN_NUM_TX_LISTS );
- priv->rxBufferDMA =priv->txListDMA
- + sizeof(TLanList) * TLAN_NUM_TX_LISTS;
- priv->txBuffer = priv->rxBuffer
- + ( TLAN_NUM_RX_LISTS * TLAN_MAX_FRAME_SIZE );
- priv->txBufferDMA = priv->rxBufferDMA
- + ( TLAN_NUM_RX_LISTS * TLAN_MAX_FRAME_SIZE );
- }
-
err = 0;
for ( i = 0; i < 6 ; i++ )
err |= TLan_EeReadByte( dev,
@@ -1094,10 +1080,10 @@ static void TLan_tx_timeout_work(struct work_struct *work)
static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
{
TLanPrivateInfo *priv = netdev_priv(dev);
- TLanList *tail_list;
dma_addr_t tail_list_phys;
- u8 *tail_buffer;
+ TLanList *tail_list;
unsigned long flags;
+ unsigned int txlen;
if ( ! priv->phyOnline ) {
TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT: %s PHY is not ready\n",
@@ -1108,6 +1094,7 @@ static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
if (skb_padto(skb, TLAN_MIN_FRAME_SIZE))
return 0;
+ txlen = max(skb->len, (unsigned int)TLAN_MIN_FRAME_SIZE);
tail_list = priv->txList + priv->txTail;
tail_list_phys = priv->txListDMA + sizeof(TLanList) * priv->txTail;
@@ -1123,18 +1110,13 @@ static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
tail_list->forward = 0;
- if ( bbuf ) {
- tail_buffer = priv->txBuffer + ( priv->txTail * TLAN_MAX_FRAME_SIZE );
- skb_copy_from_linear_data(skb, tail_buffer, skb->len);
- } else {
- tail_list->buffer[0].address = pci_map_single(priv->pciDev,
- skb->data, skb->len,
- PCI_DMA_TODEVICE);
- TLan_StoreSKB(tail_list, skb);
- }
+ tail_list->buffer[0].address = pci_map_single(priv->pciDev,
+ skb->data, txlen,
+ PCI_DMA_TODEVICE);
+ TLan_StoreSKB(tail_list, skb);
- tail_list->frameSize = (u16) skb->len;
- tail_list->buffer[0].count = TLAN_LAST_BUFFER | (u32) skb->len;
+ tail_list->frameSize = (u16) txlen;
+ tail_list->buffer[0].count = TLAN_LAST_BUFFER | (u32) txlen;
tail_list->buffer[1].count = 0;
tail_list->buffer[1].address = 0;
@@ -1161,9 +1143,6 @@ static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
CIRC_INC( priv->txTail, TLAN_NUM_TX_LISTS );
- if ( bbuf )
- dev_kfree_skb_any(skb);
-
dev->trans_start = jiffies;
return 0;
@@ -1427,15 +1406,16 @@ static u32 TLan_HandleTxEOF( struct net_device *dev, u16 host_int )
head_list = priv->txList + priv->txHead;
while (((tmpCStat = head_list->cStat ) & TLAN_CSTAT_FRM_CMP) && (ack < 255)) {
+ struct sk_buff *skb = TLan_GetSKB(head_list);
+
ack++;
- if ( ! bbuf ) {
- struct sk_buff *skb = TLan_GetSKB(head_list);
- pci_unmap_single(priv->pciDev, head_list->buffer[0].address,
- skb->len, PCI_DMA_TODEVICE);
- dev_kfree_skb_any(skb);
- head_list->buffer[8].address = 0;
- head_list->buffer[9].address = 0;
- }
+ pci_unmap_single(priv->pciDev, head_list->buffer[0].address,
+ max(skb->len,
+ (unsigned int)TLAN_MIN_FRAME_SIZE),
+ PCI_DMA_TODEVICE);
+ dev_kfree_skb_any(skb);
+ head_list->buffer[8].address = 0;
+ head_list->buffer[9].address = 0;
if ( tmpCStat & TLAN_CSTAT_EOC )
eoc = 1;
@@ -1545,7 +1525,6 @@ static u32 TLan_HandleRxEOF( struct net_device *dev, u16 host_int )
TLanPrivateInfo *priv = netdev_priv(dev);
u32 ack = 0;
int eoc = 0;
- u8 *head_buffer;
TLanList *head_list;
struct sk_buff *skb;
TLanList *tail_list;
@@ -1560,53 +1539,33 @@ static u32 TLan_HandleRxEOF( struct net_device *dev, u16 host_int )
while (((tmpCStat = head_list->cStat) & TLAN_CSTAT_FRM_CMP) && (ack < 255)) {
dma_addr_t frameDma = head_list->buffer[0].address;
u32 frameSize = head_list->frameSize;
+ struct sk_buff *new_skb;
+
ack++;
if (tmpCStat & TLAN_CSTAT_EOC)
eoc = 1;
- if (bbuf) {
- skb = netdev_alloc_skb(dev, frameSize + 7);
- if ( !skb )
- goto drop_and_reuse;
-
- head_buffer = priv->rxBuffer
- + (priv->rxHead * TLAN_MAX_FRAME_SIZE);
- skb_reserve(skb, 2);
- pci_dma_sync_single_for_cpu(priv->pciDev,
- frameDma, frameSize,
- PCI_DMA_FROMDEVICE);
- skb_copy_from_linear_data(skb, head_buffer, frameSize);
- skb_put(skb, frameSize);
- dev->stats.rx_bytes += frameSize;
-
- skb->protocol = eth_type_trans( skb, dev );
- netif_rx( skb );
- } else {
- struct sk_buff *new_skb;
-
- new_skb = netdev_alloc_skb(dev, TLAN_MAX_FRAME_SIZE + 7 );
- if ( !new_skb )
- goto drop_and_reuse;
-
- skb = TLan_GetSKB(head_list);
- pci_unmap_single(priv->pciDev, frameDma,
- TLAN_MAX_FRAME_SIZE, PCI_DMA_FROMDEVICE);
- skb_put( skb, frameSize );
+ new_skb = netdev_alloc_skb(dev, TLAN_MAX_FRAME_SIZE + 7 );
+ if ( !new_skb )
+ goto drop_and_reuse;
- dev->stats.rx_bytes += frameSize;
+ skb = TLan_GetSKB(head_list);
+ pci_unmap_single(priv->pciDev, frameDma,
+ TLAN_MAX_FRAME_SIZE, PCI_DMA_FROMDEVICE);
+ skb_put( skb, frameSize );
- skb->protocol = eth_type_trans( skb, dev );
- netif_rx( skb );
+ dev->stats.rx_bytes += frameSize;
- skb_reserve( new_skb, NET_IP_ALIGN );
- head_list->buffer[0].address = pci_map_single(priv->pciDev,
- new_skb->data,
- TLAN_MAX_FRAME_SIZE,
- PCI_DMA_FROMDEVICE);
+ skb->protocol = eth_type_trans( skb, dev );
+ netif_rx( skb );
- TLan_StoreSKB(head_list, new_skb);
+ skb_reserve( new_skb, NET_IP_ALIGN );
+ head_list->buffer[0].address = pci_map_single(priv->pciDev,
+ new_skb->data,
+ TLAN_MAX_FRAME_SIZE,
+ PCI_DMA_FROMDEVICE);
- }
+ TLan_StoreSKB(head_list, new_skb);
drop_and_reuse:
head_list->forward = 0;
head_list->cStat = 0;
@@ -1649,8 +1608,6 @@ drop_and_reuse:
}
}
- dev->last_rx = jiffies;
-
return ack;
} /* TLan_HandleRxEOF */
@@ -1991,12 +1948,7 @@ static void TLan_ResetLists( struct net_device *dev )
for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ ) {
list = priv->txList + i;
list->cStat = TLAN_CSTAT_UNUSED;
- if ( bbuf ) {
- list->buffer[0].address = priv->txBufferDMA
- + ( i * TLAN_MAX_FRAME_SIZE );
- } else {
- list->buffer[0].address = 0;
- }
+ list->buffer[0].address = 0;
list->buffer[2].count = 0;
list->buffer[2].address = 0;
list->buffer[8].address = 0;
@@ -2011,23 +1963,18 @@ static void TLan_ResetLists( struct net_device *dev )
list->cStat = TLAN_CSTAT_READY;
list->frameSize = TLAN_MAX_FRAME_SIZE;
list->buffer[0].count = TLAN_MAX_FRAME_SIZE | TLAN_LAST_BUFFER;
- if ( bbuf ) {
- list->buffer[0].address = priv->rxBufferDMA
- + ( i * TLAN_MAX_FRAME_SIZE );
- } else {
- skb = netdev_alloc_skb(dev, TLAN_MAX_FRAME_SIZE + 7 );
- if ( !skb ) {
- pr_err("TLAN: out of memory for received data.\n" );
- break;
- }
-
- skb_reserve( skb, NET_IP_ALIGN );
- list->buffer[0].address = pci_map_single(priv->pciDev,
- skb->data,
- TLAN_MAX_FRAME_SIZE,
- PCI_DMA_FROMDEVICE);
- TLan_StoreSKB(list, skb);
+ skb = netdev_alloc_skb(dev, TLAN_MAX_FRAME_SIZE + 7 );
+ if ( !skb ) {
+ pr_err("TLAN: out of memory for received data.\n" );
+ break;
}
+
+ skb_reserve( skb, NET_IP_ALIGN );
+ list->buffer[0].address = pci_map_single(priv->pciDev,
+ skb->data,
+ TLAN_MAX_FRAME_SIZE,
+ PCI_DMA_FROMDEVICE);
+ TLan_StoreSKB(list, skb);
list->buffer[1].count = 0;
list->buffer[1].address = 0;
list->forward = list_phys + sizeof(TLanList);
@@ -2050,32 +1997,33 @@ static void TLan_FreeLists( struct net_device *dev )
TLanList *list;
struct sk_buff *skb;
- if ( ! bbuf ) {
- for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ ) {
- list = priv->txList + i;
- skb = TLan_GetSKB(list);
- if ( skb ) {
- pci_unmap_single(priv->pciDev,
- list->buffer[0].address, skb->len,
- PCI_DMA_TODEVICE);
- dev_kfree_skb_any( skb );
- list->buffer[8].address = 0;
- list->buffer[9].address = 0;
- }
+ for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ ) {
+ list = priv->txList + i;
+ skb = TLan_GetSKB(list);
+ if ( skb ) {
+ pci_unmap_single(
+ priv->pciDev,
+ list->buffer[0].address,
+ max(skb->len,
+ (unsigned int)TLAN_MIN_FRAME_SIZE),
+ PCI_DMA_TODEVICE);
+ dev_kfree_skb_any( skb );
+ list->buffer[8].address = 0;
+ list->buffer[9].address = 0;
}
+ }
- for ( i = 0; i < TLAN_NUM_RX_LISTS; i++ ) {
- list = priv->rxList + i;
- skb = TLan_GetSKB(list);
- if ( skb ) {
- pci_unmap_single(priv->pciDev,
- list->buffer[0].address,
- TLAN_MAX_FRAME_SIZE,
- PCI_DMA_FROMDEVICE);
- dev_kfree_skb_any( skb );
- list->buffer[8].address = 0;
- list->buffer[9].address = 0;
- }
+ for ( i = 0; i < TLAN_NUM_RX_LISTS; i++ ) {
+ list = priv->rxList + i;
+ skb = TLan_GetSKB(list);
+ if ( skb ) {
+ pci_unmap_single(priv->pciDev,
+ list->buffer[0].address,
+ TLAN_MAX_FRAME_SIZE,
+ PCI_DMA_FROMDEVICE);
+ dev_kfree_skb_any( skb );
+ list->buffer[8].address = 0;
+ list->buffer[9].address = 0;
}
}
} /* TLan_FreeLists */
diff --git a/drivers/net/tokenring/3c359.c b/drivers/net/tokenring/3c359.c
index bf621328b601..43853e3b210e 100644
--- a/drivers/net/tokenring/3c359.c
+++ b/drivers/net/tokenring/3c359.c
@@ -296,8 +296,9 @@ static int __devinit xl_probe(struct pci_dev *pdev,
} ;
/*
- * Allowing init_trdev to allocate the dev->priv structure will align xl_private
- * on a 32 bytes boundary which we need for the rx/tx descriptors
+ * Allowing init_trdev to allocate the private data will align
+ * xl_private on a 32 bytes boundary which we need for the rx/tx
+ * descriptors
*/
dev = alloc_trdev(sizeof(struct xl_private)) ;
@@ -638,13 +639,13 @@ static int xl_open(struct net_device *dev)
/* These MUST be on 8 byte boundaries */
xl_priv->xl_tx_ring = kzalloc((sizeof(struct xl_tx_desc) * XL_TX_RING_SIZE) + 7, GFP_DMA | GFP_KERNEL);
if (xl_priv->xl_tx_ring == NULL) {
- printk(KERN_WARNING "%s: Not enough memory to allocate rx buffers.\n",
+ printk(KERN_WARNING "%s: Not enough memory to allocate tx buffers.\n",
dev->name);
free_irq(dev->irq,dev);
return -ENOMEM;
}
xl_priv->xl_rx_ring = kzalloc((sizeof(struct xl_rx_desc) * XL_RX_RING_SIZE) +7, GFP_DMA | GFP_KERNEL);
- if (xl_priv->xl_tx_ring == NULL) {
+ if (xl_priv->xl_rx_ring == NULL) {
printk(KERN_WARNING "%s: Not enough memory to allocate rx buffers.\n",
dev->name);
free_irq(dev->irq,dev);
@@ -669,6 +670,8 @@ static int xl_open(struct net_device *dev)
if (i==0) {
printk(KERN_WARNING "%s: Not enough memory to allocate rx buffers. Adapter disabled \n",dev->name) ;
free_irq(dev->irq,dev) ;
+ kfree(xl_priv->xl_tx_ring);
+ kfree(xl_priv->xl_rx_ring);
return -EIO ;
}
@@ -974,7 +977,6 @@ static void xl_rx(struct net_device *dev)
netif_rx(skb2) ;
} /* if multiple buffers */
- dev->last_rx = jiffies ;
} /* while packet to do */
/* Clear the updComplete interrupt */
@@ -1571,7 +1573,6 @@ static void xl_arb_cmd(struct net_device *dev)
* anyway.
*/
- dev->last_rx = jiffies ;
/* Acknowledge interrupt, this tells nic we are done with the arb */
writel(ACK_INTERRUPT | ARBCACK | LATCH_ACK, xl_mmio + MMIO_COMMAND) ;
diff --git a/drivers/net/tokenring/Kconfig b/drivers/net/tokenring/Kconfig
index e6b2e06493e7..c4137b0f808e 100644
--- a/drivers/net/tokenring/Kconfig
+++ b/drivers/net/tokenring/Kconfig
@@ -4,7 +4,7 @@
# So far, we only have PCI, ISA, and MCA token ring devices
menuconfig TR
- bool "Token Ring driver support"
+ tristate "Token Ring driver support"
depends on NETDEVICES && !UML
depends on (PCI || ISA || MCA || CCW)
select LLC
diff --git a/drivers/net/tokenring/abyss.c b/drivers/net/tokenring/abyss.c
index 7a7de0469eae..b566d6d79ecd 100644
--- a/drivers/net/tokenring/abyss.c
+++ b/drivers/net/tokenring/abyss.c
@@ -99,7 +99,6 @@ static int __devinit abyss_attach(struct pci_dev *pdev, const struct pci_device_
struct net_local *tp;
int ret, pci_irq_line;
unsigned long pci_ioaddr;
- DECLARE_MAC_BUF(mac);
if (versionprinted++ == 0)
printk("%s", version);
@@ -147,8 +146,7 @@ static int __devinit abyss_attach(struct pci_dev *pdev, const struct pci_device_
abyss_read_eeprom(dev);
- printk("%s: Ring Station Address: %s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ printk("%s: Ring Station Address: %pM\n", dev->name, dev->dev_addr);
tp = netdev_priv(dev);
tp->setnselout = abyss_setnselout_pins;
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
index e494c63bfbd9..fa7bce6e0c6d 100644
--- a/drivers/net/tokenring/ibmtr.c
+++ b/drivers/net/tokenring/ibmtr.c
@@ -389,7 +389,6 @@ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr)
unsigned long timeout;
static int version_printed;
#endif
- DECLARE_MAC_BUF(mac);
/* Query the adapter PIO base port which will return
* indication of where MMIO was placed. We also have a
@@ -703,8 +702,7 @@ static int __devinit ibmtr_probe1(struct net_device *dev, int PIOaddr)
channel_def[cardpresent - 1], adapter_def(ti->adapter_type));
DPRINTK("using irq %d, PIOaddr %hx, %dK shared RAM.\n",
irq, PIOaddr, ti->mapped_ram_size / 2);
- DPRINTK("Hardware address : %s\n",
- print_mac(mac, dev->dev_addr));
+ DPRINTK("Hardware address : %pM\n", dev->dev_addr);
if (ti->page_mask)
DPRINTK("Shared RAM paging enabled. "
"Page size: %uK Shared Ram size %dK\n",
@@ -1741,8 +1739,6 @@ static void tr_rx(struct net_device *dev)
void __iomem *trhhdr = rbuf + offsetof(struct rec_buf, data);
u8 saddr[6];
u8 daddr[6];
- DECLARE_MAC_BUF(mac);
- DECLARE_MAC_BUF(mac2);
int i;
for (i = 0 ; i < 6 ; i++)
saddr[i] = readb(trhhdr + SADDR_OFST + i);
@@ -1750,9 +1746,9 @@ static void tr_rx(struct net_device *dev)
daddr[i] = readb(trhhdr + DADDR_OFST + i);
DPRINTK("Probably non-IP frame received.\n");
DPRINTK("ssap: %02X dsap: %02X "
- "saddr: %s daddr: %$s\n",
+ "saddr: %pM daddr: %pM\n",
readb(llc + SSAP_OFST), readb(llc + DSAP_OFST),
- print_mac(mac, saddr), print_mac(mac2, daddr));
+ saddr, daddr);
}
#endif
@@ -1826,7 +1822,6 @@ static void tr_rx(struct net_device *dev)
skb->ip_summed = CHECKSUM_COMPLETE;
}
netif_rx(skb);
- dev->last_rx = jiffies;
} /*tr_rx */
/*****************************************************************************/
@@ -1842,8 +1837,8 @@ static void ibmtr_reset_timer(struct timer_list *tmr, struct net_device *dev)
/*****************************************************************************/
-void tok_rerun(unsigned long dev_addr){
-
+static void tok_rerun(unsigned long dev_addr)
+{
struct net_device *dev = (struct net_device *)dev_addr;
struct tok_info *ti = netdev_priv(dev);
diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c
index 59d1673f9387..239c75217b12 100644
--- a/drivers/net/tokenring/lanstreamer.c
+++ b/drivers/net/tokenring/lanstreamer.c
@@ -446,9 +446,6 @@ static int streamer_reset(struct net_device *dev)
unsigned int uaa_addr;
struct sk_buff *skb = NULL;
__u16 misr;
-#if STREAMER_DEBUG
- DECLARE_MAC_BUF(mac);
-#endif
streamer_priv = netdev_priv(dev);
streamer_mmio = streamer_priv->streamer_mmio;
@@ -577,8 +574,7 @@ static int streamer_reset(struct net_device *dev)
dev->dev_addr[i+1]= addr & 0xff;
}
#if STREAMER_DEBUG
- printk("Adapter address: %s\n",
- print_mac(mac, dev->dev_addr));
+ printk("Adapter address: %pM\n", dev->dev_addr);
#endif
}
return 0;
@@ -1013,7 +1009,6 @@ static void streamer_rx(struct net_device *dev)
/* send up to the protocol */
netif_rx(skb);
}
- dev->last_rx = jiffies;
streamer_priv->streamer_stats.rx_packets++;
streamer_priv->streamer_stats.rx_bytes += length;
} /* if skb == null */
@@ -1538,7 +1533,6 @@ static void streamer_arb_cmd(struct net_device *dev)
#if STREAMER_NETWORK_MONITOR
struct trh_hdr *mac_hdr;
- DECLARE_MAC_BUF(mac);
#endif
writew(streamer_priv->arb, streamer_mmio + LAPA);
@@ -1611,11 +1605,11 @@ static void streamer_arb_cmd(struct net_device *dev)
dev->name);
mac_hdr = tr_hdr(mac_frame);
printk(KERN_WARNING
- "%s: MAC Frame Dest. Addr: %s\n",
- dev->name, print_mac(mac, mac_hdr->daddr));
+ "%s: MAC Frame Dest. Addr: %pM\n",
+ dev->name, mac_hdr->daddr);
printk(KERN_WARNING
- "%s: MAC Frame Srce. Addr: %s\n",
- dev->name, DEV->ADDR6(mac_hdr->saddr));
+ "%s: MAC Frame Srce. Addr: %pM\n",
+ dev->name, mac_hdr->saddr);
#endif
netif_rx(mac_frame);
@@ -1850,8 +1844,6 @@ static int sprintf_info(char *buffer, struct net_device *dev)
struct streamer_parameters_table spt;
int size = 0;
int i;
- DECLARE_MAC_BUF(mac);
- DECLARE_MAC_BUF(mac2);
writew(streamer_priv->streamer_addr_table_addr, streamer_mmio + LAPA);
for (i = 0; i < 14; i += 2) {
@@ -1873,9 +1865,8 @@ static int sprintf_info(char *buffer, struct net_device *dev)
size = sprintf(buffer, "\n%6s: Adapter Address : Node Address : Functional Addr\n", dev->name);
size += sprintf(buffer + size,
- "%6s: %s : %s : %02x:%02x:%02x:%02x\n",
- dev->name, print_mac(mac, dev->dev_addr),
- print_mac(mac2, sat.node_addr),
+ "%6s: %pM : %pM : %02x:%02x:%02x:%02x\n",
+ dev->name, dev->dev_addr, sat.node_addr,
sat.func_addr[0], sat.func_addr[1],
sat.func_addr[2], sat.func_addr[3]);
@@ -1884,19 +1875,18 @@ static int sprintf_info(char *buffer, struct net_device *dev)
size += sprintf(buffer + size, "%6s: Physical Addr : Up Node Address : Poll Address : AccPri : Auth Src : Att Code :\n", dev->name);
size += sprintf(buffer + size,
- "%6s: %02x:%02x:%02x:%02x : %s : %s : %04x : %04x : %04x :\n",
+ "%6s: %02x:%02x:%02x:%02x : %pM : %pM : %04x : %04x : %04x :\n",
dev->name, spt.phys_addr[0], spt.phys_addr[1],
spt.phys_addr[2], spt.phys_addr[3],
- print_mac(mac, spt.up_node_addr),
- print_mac(mac2, spt.poll_addr),
+ spt.up_node_addr, spt.poll_addr,
ntohs(spt.acc_priority), ntohs(spt.auth_source_class),
ntohs(spt.att_code));
size += sprintf(buffer + size, "%6s: Source Address : Bcn T : Maj. V : Lan St : Lcl Rg : Mon Err : Frame Correl : \n", dev->name);
size += sprintf(buffer + size,
- "%6s: %s : %04x : %04x : %04x : %04x : %04x : %04x : \n",
- dev->name, print_mac(mac, spt.source_addr),
+ "%6s: %pM : %04x : %04x : %04x : %04x : %04x : %04x : \n",
+ dev->name, spt.source_addr,
ntohs(spt.beacon_type), ntohs(spt.major_vector),
ntohs(spt.lan_status), ntohs(spt.local_ring),
ntohs(spt.mon_error), ntohs(spt.frame_correl));
@@ -1905,10 +1895,10 @@ static int sprintf_info(char *buffer, struct net_device *dev)
dev->name);
size += sprintf(buffer + size,
- "%6s: : %02x : %02x : %s : %02x:%02x:%02x:%02x : \n",
+ "%6s: : %02x : %02x : %pM : %02x:%02x:%02x:%02x : \n",
dev->name, ntohs(spt.beacon_transmit),
ntohs(spt.beacon_receive),
- print_mac(mac, spt.beacon_naun),
+ spt.beacon_naun,
spt.beacon_phys[0], spt.beacon_phys[1],
spt.beacon_phys[2], spt.beacon_phys[3]);
return size;
diff --git a/drivers/net/tokenring/madgemc.c b/drivers/net/tokenring/madgemc.c
index c9c5a2b1ed9e..917b4d201e09 100644
--- a/drivers/net/tokenring/madgemc.c
+++ b/drivers/net/tokenring/madgemc.c
@@ -152,7 +152,6 @@ static int __devinit madgemc_probe(struct device *device)
struct card_info *card;
struct mca_device *mdev = to_mca_device(device);
int ret = 0;
- DECLARE_MAC_BUF(mac);
if (versionprinted++ == 0)
printk("%s", version);
@@ -323,8 +322,8 @@ static int __devinit madgemc_probe(struct device *device)
mca_device_set_name(mdev, (card->cardtype == 0x08)?MADGEMC16_CARDNAME:MADGEMC32_CARDNAME);
mca_set_adapter_procfn(mdev->slot, madgemc_mcaproc, dev);
- printk("%s: Ring Station Address: %s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ printk("%s: Ring Station Address: %pM\n",
+ dev->name, dev->dev_addr);
if (tmsdev_init(dev, device)) {
printk("%s: unable to get memory for dev->priv.\n",
@@ -467,7 +466,7 @@ static irqreturn_t madgemc_interrupt(int irq, void *dev_id)
* zero to leave the TMS NSELOUT bits unaffected.
*
*/
-unsigned short madgemc_setnselout_pins(struct net_device *dev)
+static unsigned short madgemc_setnselout_pins(struct net_device *dev)
{
unsigned char reg1;
struct net_local *tp = netdev_priv(dev);
@@ -690,7 +689,6 @@ static int madgemc_mcaproc(char *buf, int slot, void *d)
struct net_local *tp = netdev_priv(dev);
struct card_info *curcard = tp->tmspriv;
int len = 0;
- DECLARE_MAC_BUF(mac);
len += sprintf(buf+len, "-------\n");
if (curcard) {
@@ -714,8 +712,8 @@ static int madgemc_mcaproc(char *buf, int slot, void *d)
}
len += sprintf(buf+len, " (%s)\n", (curcard->fairness)?"Unfair":"Fair");
- len += sprintf(buf+len, "Ring Station Address: %s\n",
- print_mac(mac, dev->dev_addr));
+ len += sprintf(buf+len, "Ring Station Address: %pM\n",
+ dev->dev_addr);
} else
len += sprintf(buf+len, "Card not configured\n");
diff --git a/drivers/net/tokenring/olympic.c b/drivers/net/tokenring/olympic.c
index 0ab51a0f35fc..ecb5c7c96910 100644
--- a/drivers/net/tokenring/olympic.c
+++ b/drivers/net/tokenring/olympic.c
@@ -421,10 +421,7 @@ static int olympic_init(struct net_device *dev)
memcpy_fromio(&dev->dev_addr[0], adapter_addr,6);
#if OLYMPIC_DEBUG
- {
- DECLARE_MAC_BUF(mac);
- printk("adapter address: %s\n", print_mac(mac, dev->dev_addr));
- }
+ printk("adapter address: %pM\n", dev->dev_addr);
#endif
olympic_priv->olympic_addr_table_addr = swab16(readw(init_srb + 12));
@@ -441,7 +438,6 @@ static int olympic_open(struct net_device *dev)
unsigned long flags, t;
int i, open_finished = 1 ;
u8 resp, err;
- DECLARE_MAC_BUF(mac);
DECLARE_WAITQUEUE(wait,current) ;
@@ -569,8 +565,8 @@ static int olympic_open(struct net_device *dev)
goto out;
case 0x32:
- printk(KERN_WARNING "%s: Invalid LAA: %s\n",
- dev->name, print_mac(mac, olympic_priv->olympic_laa));
+ printk(KERN_WARNING "%s: Invalid LAA: %pM\n",
+ dev->name, olympic_priv->olympic_laa);
goto out;
default:
@@ -704,13 +700,12 @@ static int olympic_open(struct net_device *dev)
u8 __iomem *opt;
int i;
u8 addr[6];
- DECLARE_MAC_BUF(mac);
oat = (olympic_priv->olympic_lap + olympic_priv->olympic_addr_table_addr);
opt = (olympic_priv->olympic_lap + olympic_priv->olympic_parms_addr);
for (i = 0; i < 6; i++)
addr[i] = readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr)+i);
- printk("%s: Node Address: %s\n",dev->name, print_mac(mac, addr));
+ printk("%s: Node Address: %pM\n", dev->name, addr);
printk("%s: Functional Address: %02x:%02x:%02x:%02x\n",dev->name,
readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)),
readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+1),
@@ -719,7 +714,7 @@ static int olympic_open(struct net_device *dev)
for (i = 0; i < 6; i++)
addr[i] = readb(opt+offsetof(struct olympic_parameters_table, up_node_addr)+i);
- printk("%s: NAUN Address: %s\n",dev->name, print_mac(mac, addr));
+ printk("%s: NAUN Address: %pM\n", dev->name, addr);
}
netif_start_queue(dev);
@@ -867,7 +862,6 @@ static void olympic_rx(struct net_device *dev)
skb->protocol = tr_type_trans(skb,dev);
netif_rx(skb) ;
}
- dev->last_rx = jiffies ;
olympic_priv->olympic_stats.rx_packets++ ;
olympic_priv->olympic_stats.rx_bytes += length ;
} /* if skb == null */
@@ -1440,19 +1434,12 @@ static void olympic_arb_cmd(struct net_device *dev)
struct trh_hdr *mac_hdr;
printk(KERN_WARNING "%s: Received MAC Frame, details: \n",dev->name);
mac_hdr = tr_hdr(mac_frame);
- printk(KERN_WARNING "%s: MAC Frame Dest. Addr: "
- MAC_FMT " \n", dev->name,
- mac_hdr->daddr[0], mac_hdr->daddr[1],
- mac_hdr->daddr[2], mac_hdr->daddr[3],
- mac_hdr->daddr[4], mac_hdr->daddr[5]);
- printk(KERN_WARNING "%s: MAC Frame Srce. Addr: "
- MAC_FMT " \n", dev->name,
- mac_hdr->saddr[0], mac_hdr->saddr[1],
- mac_hdr->saddr[2], mac_hdr->saddr[3],
- mac_hdr->saddr[4], mac_hdr->saddr[5]);
+ printk(KERN_WARNING "%s: MAC Frame Dest. Addr: %pM\n",
+ dev->name, mac_hdr->daddr);
+ printk(KERN_WARNING "%s: MAC Frame Srce. Addr: %pM\n",
+ dev->name, mac_hdr->saddr);
}
netif_rx(mac_frame);
- dev->last_rx = jiffies;
drop_frame:
/* Now tell the card we have dealt with the received frame */
@@ -1647,8 +1634,6 @@ static int olympic_proc_info(char *buffer, char **start, off_t offset, int lengt
u8 addr[6];
u8 addr2[6];
int i;
- DECLARE_MAC_BUF(mac);
- DECLARE_MAC_BUF(mac2);
size = sprintf(buffer,
"IBM Pit/Pit-Phy/Olympic Chipset Token Ring Adapter %s\n",dev->name);
@@ -1658,10 +1643,9 @@ static int olympic_proc_info(char *buffer, char **start, off_t offset, int lengt
for (i = 0 ; i < 6 ; i++)
addr[i] = readb(oat+offsetof(struct olympic_adapter_addr_table,node_addr) + i);
- size += sprintf(buffer+size, "%6s: %s : %s : %02x:%02x:%02x:%02x\n",
+ size += sprintf(buffer+size, "%6s: %pM : %pM : %02x:%02x:%02x:%02x\n",
dev->name,
- print_mac(mac, dev->dev_addr),
- print_mac(mac2, addr),
+ dev->dev_addr, addr,
readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)),
readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+1),
readb(oat+offsetof(struct olympic_adapter_addr_table,func_addr)+2),
@@ -1677,14 +1661,13 @@ static int olympic_proc_info(char *buffer, char **start, off_t offset, int lengt
for (i = 0 ; i < 6 ; i++)
addr2[i] = readb(opt+offsetof(struct olympic_parameters_table, poll_addr) + i);
- size += sprintf(buffer+size, "%6s: %02x:%02x:%02x:%02x : %s : %s : %04x : %04x : %04x :\n",
+ size += sprintf(buffer+size, "%6s: %02x:%02x:%02x:%02x : %pM : %pM : %04x : %04x : %04x :\n",
dev->name,
readb(opt+offsetof(struct olympic_parameters_table, phys_addr)),
readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+1),
readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+2),
readb(opt+offsetof(struct olympic_parameters_table, phys_addr)+3),
- print_mac(mac, addr),
- print_mac(mac2, addr2),
+ addr, addr2,
swab16(readw(opt+offsetof(struct olympic_parameters_table, acc_priority))),
swab16(readw(opt+offsetof(struct olympic_parameters_table, auth_source_class))),
swab16(readw(opt+offsetof(struct olympic_parameters_table, att_code))));
@@ -1694,9 +1677,8 @@ static int olympic_proc_info(char *buffer, char **start, off_t offset, int lengt
for (i = 0 ; i < 6 ; i++)
addr[i] = readb(opt+offsetof(struct olympic_parameters_table, source_addr) + i);
- size += sprintf(buffer+size, "%6s: %s : %04x : %04x : %04x : %04x : %04x : %04x : \n",
- dev->name,
- print_mac(mac, addr),
+ size += sprintf(buffer+size, "%6s: %pM : %04x : %04x : %04x : %04x : %04x : %04x : \n",
+ dev->name, addr,
swab16(readw(opt+offsetof(struct olympic_parameters_table, beacon_type))),
swab16(readw(opt+offsetof(struct olympic_parameters_table, major_vector))),
swab16(readw(opt+offsetof(struct olympic_parameters_table, lan_status))),
@@ -1709,11 +1691,11 @@ static int olympic_proc_info(char *buffer, char **start, off_t offset, int lengt
for (i = 0 ; i < 6 ; i++)
addr[i] = readb(opt+offsetof(struct olympic_parameters_table, beacon_naun) + i);
- size += sprintf(buffer+size, "%6s: : %02x : %02x : %s : %02x:%02x:%02x:%02x : \n",
+ size += sprintf(buffer+size, "%6s: : %02x : %02x : %pM : %02x:%02x:%02x:%02x : \n",
dev->name,
swab16(readw(opt+offsetof(struct olympic_parameters_table, beacon_transmit))),
swab16(readw(opt+offsetof(struct olympic_parameters_table, beacon_receive))),
- print_mac(mac, addr),
+ addr,
readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)),
readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+1),
readb(opt+offsetof(struct olympic_parameters_table, beacon_phys)+2),
diff --git a/drivers/net/tokenring/proteon.c b/drivers/net/tokenring/proteon.c
index 00ea94513460..b8c955f6d31a 100644
--- a/drivers/net/tokenring/proteon.c
+++ b/drivers/net/tokenring/proteon.c
@@ -122,7 +122,6 @@ static int __init setup_card(struct net_device *dev, struct device *pdev)
static int versionprinted;
const unsigned *port;
int j,err = 0;
- DECLARE_MAC_BUF(mac);
if (!dev)
return -ENOMEM;
@@ -153,8 +152,8 @@ static int __init setup_card(struct net_device *dev, struct device *pdev)
proteon_read_eeprom(dev);
- printk(KERN_DEBUG "proteon.c: Ring Station Address: %s\n",
- print_mac(mac, dev->dev_addr));
+ printk(KERN_DEBUG "proteon.c: Ring Station Address: %pM\n",
+ dev->dev_addr);
tp = netdev_priv(dev);
tp->setnselout = proteon_setnselout_pins;
@@ -284,7 +283,7 @@ static void proteon_read_eeprom(struct net_device *dev)
dev->dev_addr[i] = proteon_sifreadw(dev, SIFINC) >> 8;
}
-unsigned short proteon_setnselout_pins(struct net_device *dev)
+static unsigned short proteon_setnselout_pins(struct net_device *dev)
{
return 0;
}
diff --git a/drivers/net/tokenring/skisa.c b/drivers/net/tokenring/skisa.c
index 41b6999a0f33..c0f58f08782c 100644
--- a/drivers/net/tokenring/skisa.c
+++ b/drivers/net/tokenring/skisa.c
@@ -139,7 +139,6 @@ static int __init setup_card(struct net_device *dev, struct device *pdev)
static int versionprinted;
const unsigned *port;
int j, err = 0;
- DECLARE_MAC_BUF(mac);
if (!dev)
return -ENOMEM;
@@ -170,8 +169,8 @@ static int __init setup_card(struct net_device *dev, struct device *pdev)
sk_isa_read_eeprom(dev);
- printk(KERN_DEBUG "skisa.c: Ring Station Address: %s\n",
- print_mac(mac, dev->dev_addr));
+ printk(KERN_DEBUG "skisa.c: Ring Station Address: %pM\n",
+ dev->dev_addr);
tp = netdev_priv(dev);
tp->setnselout = sk_isa_setnselout_pins;
@@ -301,7 +300,7 @@ static void sk_isa_read_eeprom(struct net_device *dev)
dev->dev_addr[i] = sk_isa_sifreadw(dev, SIFINC) >> 8;
}
-unsigned short sk_isa_setnselout_pins(struct net_device *dev)
+static unsigned short sk_isa_setnselout_pins(struct net_device *dev)
{
return 0;
}
diff --git a/drivers/net/tokenring/smctr.c b/drivers/net/tokenring/smctr.c
index ed50d288e494..a011666342ff 100644
--- a/drivers/net/tokenring/smctr.c
+++ b/drivers/net/tokenring/smctr.c
@@ -3910,7 +3910,6 @@ static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
/* Kick the packet on up. */
skb->protocol = tr_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
err = 0;
}
@@ -4496,7 +4495,6 @@ static int smctr_rx_frame(struct net_device *dev)
/* Kick the packet on up. */
skb->protocol = tr_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
} else {
}
}
diff --git a/drivers/net/tokenring/tms380tr.c b/drivers/net/tokenring/tms380tr.c
index d07c4523c847..5be34c2fd483 100644
--- a/drivers/net/tokenring/tms380tr.c
+++ b/drivers/net/tokenring/tms380tr.c
@@ -180,10 +180,14 @@ void tms380tr_wait(unsigned long time);
static void tms380tr_write_rpl_status(RPL *rpl, unsigned int Status);
static void tms380tr_write_tpl_status(TPL *tpl, unsigned int Status);
-#define SIFREADB(reg) (((struct net_local *)dev->priv)->sifreadb(dev, reg))
-#define SIFWRITEB(val, reg) (((struct net_local *)dev->priv)->sifwriteb(dev, val, reg))
-#define SIFREADW(reg) (((struct net_local *)dev->priv)->sifreadw(dev, reg))
-#define SIFWRITEW(val, reg) (((struct net_local *)dev->priv)->sifwritew(dev, val, reg))
+#define SIFREADB(reg) \
+ (((struct net_local *)netdev_priv(dev))->sifreadb(dev, reg))
+#define SIFWRITEB(val, reg) \
+ (((struct net_local *)netdev_priv(dev))->sifwriteb(dev, val, reg))
+#define SIFREADW(reg) \
+ (((struct net_local *)netdev_priv(dev))->sifreadw(dev, reg))
+#define SIFWRITEW(val, reg) \
+ (((struct net_local *)netdev_priv(dev))->sifwritew(dev, val, reg))
@@ -2186,7 +2190,6 @@ static void tms380tr_rcv_status_irq(struct net_device *dev)
skb_trim(skb,Length);
skb->protocol = tr_type_trans(skb,dev);
netif_rx(skb);
- dev->last_rx = jiffies;
}
}
else /* Invalid frame */
@@ -2331,7 +2334,7 @@ int tmsdev_init(struct net_device *dev, struct device *pdev)
{
struct net_local *tms_local;
- memset(dev->priv, 0, sizeof(struct net_local));
+ memset(netdev_priv(dev), 0, sizeof(struct net_local));
tms_local = netdev_priv(dev);
init_waitqueue_head(&tms_local->wait_for_tok_int);
if (pdev->dma_mask)
diff --git a/drivers/net/tokenring/tmspci.c b/drivers/net/tokenring/tmspci.c
index 5f0ee880cfff..5f601773c260 100644
--- a/drivers/net/tokenring/tmspci.c
+++ b/drivers/net/tokenring/tmspci.c
@@ -100,7 +100,6 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic
unsigned int pci_irq_line;
unsigned long pci_ioaddr;
struct card_info *cardinfo = &card_info_table[ent->driver_data];
- DECLARE_MAC_BUF(mac);
if (versionprinted++ == 0)
printk("%s", version);
@@ -137,8 +136,8 @@ static int __devinit tms_pci_attach(struct pci_dev *pdev, const struct pci_devic
tms_pci_read_eeprom(dev);
- printk("%s: Ring Station Address: %s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ printk("%s: Ring Station Address: %pM\n",
+ dev->name, dev->dev_addr);
ret = tmsdev_init(dev, &pdev->dev);
if (ret) {
diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c
index eb1da6f0b086..75461dbd4876 100644
--- a/drivers/net/tsi108_eth.c
+++ b/drivers/net/tsi108_eth.c
@@ -788,7 +788,6 @@ static int tsi108_complete_rx(struct net_device *dev, int budget)
skb_put(skb, data->rxring[rx].len);
skb->protocol = eth_type_trans(skb, dev);
netif_receive_skb(skb);
- dev->last_rx = jiffies;
}
return done;
@@ -889,7 +888,7 @@ static int tsi108_poll(struct napi_struct *napi, int budget)
if (num_received < budget) {
data->rxpending = 0;
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
TSI_WRITE(TSI108_EC_INTMASK,
TSI_READ(TSI108_EC_INTMASK)
@@ -920,7 +919,7 @@ static void tsi108_rx_int(struct net_device *dev)
* from tsi108_check_rxring().
*/
- if (netif_rx_schedule_prep(dev, &data->napi)) {
+ if (netif_rx_schedule_prep(&data->napi)) {
/* Mask, rather than ack, the receive interrupts. The ack
* will happen in tsi108_poll().
*/
@@ -931,7 +930,7 @@ static void tsi108_rx_int(struct net_device *dev)
| TSI108_INT_RXTHRESH |
TSI108_INT_RXOVERRUN | TSI108_INT_RXERROR |
TSI108_INT_RXWAIT);
- __netif_rx_schedule(dev, &data->napi);
+ __netif_rx_schedule(&data->napi);
} else {
if (!netif_running(dev)) {
/* This can happen if an interrupt occurs while the
@@ -1569,7 +1568,6 @@ tsi108_init_one(struct platform_device *pdev)
struct tsi108_prv_data *data = NULL;
hw_info *einfo;
int err = 0;
- DECLARE_MAC_BUF(mac);
einfo = pdev->dev.platform_data;
@@ -1659,8 +1657,8 @@ tsi108_init_one(struct platform_device *pdev)
}
platform_set_drvdata(pdev, dev);
- printk(KERN_INFO "%s: Tsi108 Gigabit Ethernet, MAC: %s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "%s: Tsi108 Gigabit Ethernet, MAC: %pM\n",
+ dev->name, dev->dev_addr);
#ifdef DEBUG
data->msg_enable = DEBUG;
dump_eth_one(dev);
diff --git a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
index 124d5d690dde..5166be930a52 100644
--- a/drivers/net/tulip/de2104x.c
+++ b/drivers/net/tulip/de2104x.c
@@ -459,7 +459,6 @@ static void de_rx (struct de_private *de)
de->net_stats.rx_packets++;
de->net_stats.rx_bytes += skb->len;
- de->dev->last_rx = jiffies;
rc = netif_rx (skb);
if (rc == NET_RX_DROP)
drop = 1;
@@ -484,7 +483,7 @@ rx_next:
static irqreturn_t de_interrupt (int irq, void *dev_instance)
{
struct net_device *dev = dev_instance;
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
u32 status;
status = dr32(MacStatus);
@@ -590,7 +589,7 @@ next:
static int de_start_xmit (struct sk_buff *skb, struct net_device *dev)
{
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
unsigned int entry, tx_free;
u32 mapping, len, flags = FirstFrag | LastFrag;
struct de_desc *txd;
@@ -653,7 +652,7 @@ static int de_start_xmit (struct sk_buff *skb, struct net_device *dev)
static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev)
{
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
u16 hash_table[32];
struct dev_mc_list *mclist;
int i;
@@ -684,7 +683,7 @@ static void build_setup_frame_hash(u16 *setup_frm, struct net_device *dev)
static void build_setup_frame_perfect(u16 *setup_frm, struct net_device *dev)
{
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
struct dev_mc_list *mclist;
int i;
u16 *eaddrs;
@@ -712,7 +711,7 @@ static void build_setup_frame_perfect(u16 *setup_frm, struct net_device *dev)
static void __de_set_rx_mode (struct net_device *dev)
{
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
u32 macmode;
unsigned int entry;
u32 mapping;
@@ -797,7 +796,7 @@ out:
static void de_set_rx_mode (struct net_device *dev)
{
unsigned long flags;
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
spin_lock_irqsave (&de->lock, flags);
__de_set_rx_mode(dev);
@@ -821,7 +820,7 @@ static void __de_get_stats(struct de_private *de)
static struct net_device_stats *de_get_stats(struct net_device *dev)
{
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
/* The chip only need report frame silently dropped. */
spin_lock_irq(&de->lock);
@@ -1355,7 +1354,7 @@ static void de_free_rings (struct de_private *de)
static int de_open (struct net_device *dev)
{
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
int rc;
if (netif_msg_ifup(de))
@@ -1400,7 +1399,7 @@ err_out_free:
static int de_close (struct net_device *dev)
{
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
unsigned long flags;
if (netif_msg_ifdown(de))
@@ -1423,7 +1422,7 @@ static int de_close (struct net_device *dev)
static void de_tx_timeout (struct net_device *dev)
{
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
printk(KERN_DEBUG "%s: NIC status %08x mode %08x sia %08x desc %u/%u/%u\n",
dev->name, dr32(MacStatus), dr32(MacMode), dr32(SIAStatus),
@@ -1574,7 +1573,7 @@ static int __de_set_settings(struct de_private *de, struct ethtool_cmd *ecmd)
static void de_get_drvinfo (struct net_device *dev,struct ethtool_drvinfo *info)
{
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
strcpy (info->driver, DRV_NAME);
strcpy (info->version, DRV_VERSION);
@@ -1589,7 +1588,7 @@ static int de_get_regs_len(struct net_device *dev)
static int de_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
{
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
int rc;
spin_lock_irq(&de->lock);
@@ -1601,7 +1600,7 @@ static int de_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
static int de_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
{
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
int rc;
spin_lock_irq(&de->lock);
@@ -1613,14 +1612,14 @@ static int de_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
static u32 de_get_msglevel(struct net_device *dev)
{
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
return de->msg_enable;
}
static void de_set_msglevel(struct net_device *dev, u32 msglvl)
{
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
de->msg_enable = msglvl;
}
@@ -1628,7 +1627,7 @@ static void de_set_msglevel(struct net_device *dev, u32 msglvl)
static int de_get_eeprom(struct net_device *dev,
struct ethtool_eeprom *eeprom, u8 *data)
{
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
if (!de->ee_data)
return -EOPNOTSUPP;
@@ -1642,7 +1641,7 @@ static int de_get_eeprom(struct net_device *dev,
static int de_nway_reset(struct net_device *dev)
{
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
u32 status;
if (de->media_type != DE_MEDIA_TP_AUTO)
@@ -1661,7 +1660,7 @@ static int de_nway_reset(struct net_device *dev)
static void de_get_regs(struct net_device *dev, struct ethtool_regs *regs,
void *data)
{
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
regs->version = (DE_REGS_VER << 2) | de->de21040;
@@ -1692,9 +1691,9 @@ static void __devinit de21040_get_mac_address (struct de_private *de)
for (i = 0; i < 6; i++) {
int value, boguscnt = 100000;
- do
+ do {
value = dr32(ROMCmd);
- while (value < 0 && --boguscnt > 0);
+ } while (value < 0 && --boguscnt > 0);
de->dev->dev_addr[i] = value;
udelay(1);
if (boguscnt <= 0)
@@ -1932,7 +1931,6 @@ static int __devinit de_init_one (struct pci_dev *pdev,
void __iomem *regs;
unsigned long pciaddr;
static int board_idx = -1;
- DECLARE_MAC_BUF(mac);
board_idx++;
@@ -1956,7 +1954,7 @@ static int __devinit de_init_one (struct pci_dev *pdev,
dev->tx_timeout = de_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
- de = dev->priv;
+ de = netdev_priv(dev);
de->de21040 = ent->driver_data == 0 ? 1 : 0;
de->pdev = pdev;
de->dev = dev;
@@ -2046,11 +2044,11 @@ static int __devinit de_init_one (struct pci_dev *pdev,
goto err_out_iomap;
/* print info about board and interface just registered */
- printk (KERN_INFO "%s: %s at 0x%lx, %s, IRQ %d\n",
+ printk (KERN_INFO "%s: %s at 0x%lx, %pM, IRQ %d\n",
dev->name,
de->de21040 ? "21040" : "21041",
dev->base_addr,
- print_mac(mac, dev->dev_addr),
+ dev->dev_addr,
dev->irq);
pci_set_drvdata(pdev, dev);
@@ -2078,7 +2076,7 @@ err_out_free:
static void __devexit de_remove_one (struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
BUG_ON(!dev);
unregister_netdev(dev);
@@ -2095,7 +2093,7 @@ static void __devexit de_remove_one (struct pci_dev *pdev)
static int de_suspend (struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata (pdev);
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
rtnl_lock();
if (netif_running (dev)) {
@@ -2130,7 +2128,7 @@ static int de_suspend (struct pci_dev *pdev, pm_message_t state)
static int de_resume (struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata (pdev);
- struct de_private *de = dev->priv;
+ struct de_private *de = netdev_priv(dev);
int retval = 0;
rtnl_lock();
diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c
index 6444cbec0bdc..67bfd6f43366 100644
--- a/drivers/net/tulip/de4x5.c
+++ b/drivers/net/tulip/de4x5.c
@@ -1085,7 +1085,6 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
struct de4x5_private *lp = netdev_priv(dev);
struct pci_dev *pdev = NULL;
int i, status=0;
- DECLARE_MAC_BUF(mac);
gendev->driver_data = dev;
@@ -1119,10 +1118,10 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
}
dev->base_addr = iobase;
- printk ("%s: %s at 0x%04lx", gendev->bus_id, name, iobase);
+ printk ("%s: %s at 0x%04lx", dev_name(gendev), name, iobase);
status = get_hw_addr(dev);
- printk(", h/w address %s\n", print_mac(mac, dev->dev_addr));
+ printk(", h/w address %pM\n", dev->dev_addr);
if (status != 0) {
printk(" which has an Ethernet PROM CRC error.\n");
@@ -1154,7 +1153,7 @@ de4x5_hw_init(struct net_device *dev, u_long iobase, struct device *gendev)
}
}
lp->fdx = lp->params.fdx;
- sprintf(lp->adapter_name,"%s (%s)", name, gendev->bus_id);
+ sprintf(lp->adapter_name,"%s (%s)", name, dev_name(gendev));
lp->dma_size = (NUM_RX_DESC + NUM_TX_DESC) * sizeof(struct de4x5_desc);
#if defined(__alpha__) || defined(__powerpc__) || defined(CONFIG_SPARC) || defined(DE4X5_DO_MEMCPY)
@@ -1647,7 +1646,6 @@ de4x5_rx(struct net_device *dev)
netif_rx(skb);
/* Update stats */
- dev->last_rx = jiffies;
lp->stats.rx_packets++;
lp->stats.rx_bytes += pkt_len;
}
@@ -5401,7 +5399,6 @@ static void
de4x5_dbg_srom(struct de4x5_srom *p)
{
int i;
- DECLARE_MAC_BUF(mac);
if (de4x5_debug & DEBUG_SROM) {
printk("Sub-system Vendor ID: %04x\n", *((u_short *)p->sub_vendor_id));
@@ -5410,7 +5407,7 @@ de4x5_dbg_srom(struct de4x5_srom *p)
printk("SROM version: %02x\n", (u_char)(p->version));
printk("# controllers: %02x\n", (u_char)(p->num_controllers));
- printk("Hardware Address: %s\n", print_mac(mac, p->ieee_addr));
+ printk("Hardware Address: %pM\n", p->ieee_addr);
printk("CRC checksum: %04x\n", (u_short)(p->chksum));
for (i=0; i<64; i++) {
printk("%3d %04x\n", i<<1, (u_short)*((u_short *)p+i));
@@ -5424,12 +5421,10 @@ static void
de4x5_dbg_rx(struct sk_buff *skb, int len)
{
int i, j;
- DECLARE_MAC_BUF(mac);
- DECLARE_MAC_BUF(mac2);
if (de4x5_debug & DEBUG_RX) {
- printk("R: %s <- %s len/SAP:%02x%02x [%d]\n",
- print_mac(mac, skb->data), print_mac(mac2, &skb->data[6]),
+ printk("R: %pM <- %pM len/SAP:%02x%02x [%d]\n",
+ skb->data, &skb->data[6],
(u_char)skb->data[12],
(u_char)skb->data[13],
len);
diff --git a/drivers/net/tulip/dmfe.c b/drivers/net/tulip/dmfe.c
index c91852f49a48..28a5c51b43a0 100644
--- a/drivers/net/tulip/dmfe.c
+++ b/drivers/net/tulip/dmfe.c
@@ -362,7 +362,6 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
struct net_device *dev;
u32 pci_pmr;
int i, err;
- DECLARE_MAC_BUF(mac);
DMFE_DBUG(0, "dmfe_init_one()", 0);
@@ -475,12 +474,11 @@ static int __devinit dmfe_init_one (struct pci_dev *pdev,
if (err)
goto err_out_free_buf;
- printk(KERN_INFO "%s: Davicom DM%04lx at pci%s, "
- "%s, irq %d.\n",
+ printk(KERN_INFO "%s: Davicom DM%04lx at pci%s, %pM, irq %d.\n",
dev->name,
ent->driver_data >> 16,
pci_name(pdev),
- print_mac(mac, dev->dev_addr),
+ dev->dev_addr,
dev->irq);
pci_set_master(pdev);
@@ -1010,7 +1008,6 @@ static void dmfe_rx_packet(struct DEVICE *dev, struct dmfe_board_info * db)
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
db->stats.rx_packets++;
db->stats.rx_bytes += rxlen;
}
diff --git a/drivers/net/tulip/eeprom.c b/drivers/net/tulip/eeprom.c
index 0dcced1263b9..391acd32a6a5 100644
--- a/drivers/net/tulip/eeprom.c
+++ b/drivers/net/tulip/eeprom.c
@@ -337,7 +337,7 @@ int __devinit tulip_read_eeprom(struct net_device *dev, int location, int addr_l
{
int i;
unsigned retval = 0;
- struct tulip_private *tp = dev->priv;
+ struct tulip_private *tp = netdev_priv(dev);
void __iomem *ee_addr = tp->base_addr + CSR9;
int read_cmd = location | (EE_READ_CMD << addr_len);
diff --git a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c
index c6bad987d63e..6c3428a37c0b 100644
--- a/drivers/net/tulip/interrupt.c
+++ b/drivers/net/tulip/interrupt.c
@@ -103,7 +103,7 @@ void oom_timer(unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
struct tulip_private *tp = netdev_priv(dev);
- netif_rx_schedule(dev, &tp->napi);
+ netif_rx_schedule(&tp->napi);
}
int tulip_poll(struct napi_struct *napi, int budget)
@@ -231,7 +231,6 @@ int tulip_poll(struct napi_struct *napi, int budget)
netif_receive_skb(skb);
- dev->last_rx = jiffies;
tp->stats.rx_packets++;
tp->stats.rx_bytes += pkt_len;
}
@@ -301,7 +300,7 @@ int tulip_poll(struct napi_struct *napi, int budget)
/* Remove us from polling list and enable RX intr. */
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
iowrite32(tulip_tbl[tp->chip_id].valid_intrs, tp->base_addr+CSR7);
/* The last op happens after poll completion. Which means the following:
@@ -337,7 +336,7 @@ int tulip_poll(struct napi_struct *napi, int budget)
* before we did netif_rx_complete(). See? We would lose it. */
/* remove ourselves from the polling list */
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
return work_done;
}
@@ -444,7 +443,6 @@ static int tulip_rx(struct net_device *dev)
netif_rx(skb);
- dev->last_rx = jiffies;
tp->stats.rx_packets++;
tp->stats.rx_bytes += pkt_len;
}
@@ -521,7 +519,7 @@ irqreturn_t tulip_interrupt(int irq, void *dev_instance)
rxd++;
/* Mask RX intrs and add the device to poll list. */
iowrite32(tulip_tbl[tp->chip_id].valid_intrs&~RxPollInt, ioaddr + CSR7);
- netif_rx_schedule(dev, &tp->napi);
+ netif_rx_schedule(&tp->napi);
if (!(csr5&~(AbnormalIntr|NormalIntr|RxPollInt|TPLnkPass)))
break;
diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
index cafa89e60167..ff84babb3ff3 100644
--- a/drivers/net/tulip/tulip_core.c
+++ b/drivers/net/tulip/tulip_core.c
@@ -1050,13 +1050,11 @@ static void set_rx_mode(struct net_device *dev)
filterbit = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
filterbit &= 0x3f;
mc_filter[filterbit >> 5] |= 1 << (filterbit & 31);
- if (tulip_debug > 2) {
- DECLARE_MAC_BUF(mac);
- printk(KERN_INFO "%s: Added filter for %s"
+ if (tulip_debug > 2)
+ printk(KERN_INFO "%s: Added filter for %pM"
" %8.8x bit %d.\n",
- dev->name, print_mac(mac, mclist->dmi_addr),
+ dev->name, mclist->dmi_addr,
ether_crc(ETH_ALEN, mclist->dmi_addr), filterbit);
- }
}
if (mc_filter[0] == tp->mc_filter[0] &&
mc_filter[1] == tp->mc_filter[1])
@@ -1250,7 +1248,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
const char *chip_name = tulip_tbl[chip_idx].chip_name;
unsigned int eeprom_missing = 0;
unsigned int force_csr0 = 0;
- DECLARE_MAC_BUF(mac);
#ifndef MODULE
static int did_version; /* Already printed version info. */
@@ -1432,9 +1429,9 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
for (i = 0; i < 3; i++) {
int value, boguscnt = 100000;
iowrite32(0x600 | i, ioaddr + 0x98);
- do
+ do {
value = ioread32(ioaddr + CSR9);
- while (value < 0 && --boguscnt > 0);
+ } while (value < 0 && --boguscnt > 0);
put_unaligned_le16(value, ((__le16 *)dev->dev_addr) + i);
sum += value & 0xffff;
}
@@ -1635,7 +1632,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
if (eeprom_missing)
printk(" EEPROM not present,");
- printk(" %s", print_mac(mac, dev->dev_addr));
+ printk(" %pM", dev->dev_addr);
printk(", IRQ %d.\n", irq);
if (tp->chip_id == PNIC2)
diff --git a/drivers/net/tulip/uli526x.c b/drivers/net/tulip/uli526x.c
index e9e628621639..00cbc5251dcc 100644
--- a/drivers/net/tulip/uli526x.c
+++ b/drivers/net/tulip/uli526x.c
@@ -261,7 +261,6 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev,
struct uli526x_board_info *db; /* board information structure */
struct net_device *dev;
int i, err;
- DECLARE_MAC_BUF(mac);
ULI526X_DBUG(0, "uli526x_init_one()", 0);
@@ -379,9 +378,9 @@ static int __devinit uli526x_init_one (struct pci_dev *pdev,
if (err)
goto err_out_res;
- printk(KERN_INFO "%s: ULi M%04lx at pci%s, %s, irq %d.\n",
+ printk(KERN_INFO "%s: ULi M%04lx at pci%s, %pM, irq %d.\n",
dev->name,ent->driver_data >> 16,pci_name(pdev),
- print_mac(mac, dev->dev_addr), dev->irq);
+ dev->dev_addr, dev->irq);
pci_set_master(pdev);
@@ -855,7 +854,6 @@ static void uli526x_rx_packet(struct net_device *dev, struct uli526x_board_info
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
db->stats.rx_packets++;
db->stats.rx_bytes += rxlen;
@@ -892,7 +890,7 @@ static struct net_device_stats * uli526x_get_stats(struct net_device *dev)
static void uli526x_set_filter_mode(struct net_device * dev)
{
- struct uli526x_board_info *db = dev->priv;
+ struct uli526x_board_info *db = netdev_priv(dev);
unsigned long flags;
ULI526X_DBUG(0, "uli526x_set_filter_mode()", 0);
diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c
index 50068194c163..022d99af8646 100644
--- a/drivers/net/tulip/winbond-840.c
+++ b/drivers/net/tulip/winbond-840.c
@@ -355,7 +355,6 @@ static int __devinit w840_probe1 (struct pci_dev *pdev,
int irq;
int i, option = find_cnt < MAX_UNITS ? options[find_cnt] : 0;
void __iomem *ioaddr;
- DECLARE_MAC_BUF(mac);
i = pci_enable_device(pdev);
if (i) return i;
@@ -435,9 +434,9 @@ static int __devinit w840_probe1 (struct pci_dev *pdev,
if (i)
goto err_out_cleardev;
- printk(KERN_INFO "%s: %s at %p, %s, IRQ %d.\n",
+ printk(KERN_INFO "%s: %s at %p, %pM, IRQ %d.\n",
dev->name, pci_id_tbl[chip_idx].name, ioaddr,
- print_mac(mac, dev->dev_addr), irq);
+ dev->dev_addr, irq);
if (np->drv_flags & CanHaveMII) {
int phy, phy_idx = 0;
@@ -1245,20 +1244,15 @@ static int netdev_rx(struct net_device *dev)
}
#ifndef final_version /* Remove after testing. */
/* You will want this info for the initial debug. */
- if (debug > 5) {
- DECLARE_MAC_BUF(mac);
- DECLARE_MAC_BUF(mac2);
-
- printk(KERN_DEBUG " Rx data %s %s"
+ if (debug > 5)
+ printk(KERN_DEBUG " Rx data %pM %pM"
" %2.2x%2.2x %d.%d.%d.%d.\n",
- print_mac(mac, &skb->data[0]), print_mac(mac2, &skb->data[6]),
+ &skb->data[0], &skb->data[6],
skb->data[12], skb->data[13],
skb->data[14], skb->data[15], skb->data[16], skb->data[17]);
- }
#endif
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
np->stats.rx_packets++;
np->stats.rx_bytes += pkt_len;
}
diff --git a/drivers/net/tulip/xircom_cb.c b/drivers/net/tulip/xircom_cb.c
index 6b93d0169116..13c8703ecb9f 100644
--- a/drivers/net/tulip/xircom_cb.c
+++ b/drivers/net/tulip/xircom_cb.c
@@ -1072,7 +1072,6 @@ static void read_mac_address(struct xircom_private *card)
unsigned char j, tuple, link, data_id, data_count;
unsigned long flags;
int i;
- DECLARE_MAC_BUF(mac);
enter("read_mac_address");
@@ -1102,7 +1101,7 @@ static void read_mac_address(struct xircom_private *card)
}
}
spin_unlock_irqrestore(&card->lock, flags);
- pr_debug(" %s\n", print_mac(mac, card->dev->dev_addr));
+ pr_debug(" %pM\n", card->dev->dev_addr);
leave("read_mac_address");
}
@@ -1202,7 +1201,6 @@ static void investigate_read_descriptor(struct net_device *dev,struct xircom_pri
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
card->stats.rx_packets++;
card->stats.rx_bytes += pkt_len;
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 33b6d1b122fb..666c1d98cdaf 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -305,6 +305,23 @@ tun_net_change_mtu(struct net_device *dev, int new_mtu)
return 0;
}
+static const struct net_device_ops tun_netdev_ops = {
+ .ndo_open = tun_net_open,
+ .ndo_stop = tun_net_close,
+ .ndo_start_xmit = tun_net_xmit,
+ .ndo_change_mtu = tun_net_change_mtu,
+};
+
+static const struct net_device_ops tap_netdev_ops = {
+ .ndo_open = tun_net_open,
+ .ndo_stop = tun_net_close,
+ .ndo_start_xmit = tun_net_xmit,
+ .ndo_change_mtu = tun_net_change_mtu,
+ .ndo_set_multicast_list = tun_net_mclist,
+ .ndo_set_mac_address = eth_mac_addr,
+ .ndo_validate_addr = eth_validate_addr,
+};
+
/* Initialize net device. */
static void tun_net_init(struct net_device *dev)
{
@@ -312,11 +329,12 @@ static void tun_net_init(struct net_device *dev)
switch (tun->flags & TUN_TYPE_MASK) {
case TUN_TUN_DEV:
+ dev->netdev_ops = &tun_netdev_ops;
+
/* Point-to-Point TUN Device */
dev->hard_header_len = 0;
dev->addr_len = 0;
dev->mtu = 1500;
- dev->change_mtu = tun_net_change_mtu;
/* Zero header length */
dev->type = ARPHRD_NONE;
@@ -325,10 +343,9 @@ static void tun_net_init(struct net_device *dev)
break;
case TUN_TAP_DEV:
+ dev->netdev_ops = &tun_netdev_ops;
/* Ethernet TAP Device */
ether_setup(dev);
- dev->change_mtu = tun_net_change_mtu;
- dev->set_multicast_list = tun_net_mclist;
random_ether_addr(dev->dev_addr);
@@ -529,7 +546,6 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv,
}
netif_rx_ni(skb);
- tun->dev->last_rx = jiffies;
tun->dev->stats.rx_packets++;
tun->dev->stats.rx_bytes += len;
@@ -676,9 +692,6 @@ static void tun_setup(struct net_device *dev)
tun->owner = -1;
tun->group = -1;
- dev->open = tun_net_open;
- dev->hard_start_xmit = tun_net_xmit;
- dev->stop = tun_net_close;
dev->ethtool_ops = &tun_ethtool_ops;
dev->destructor = free_netdev;
dev->features |= NETIF_F_NETNS_LOCAL;
@@ -702,6 +715,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
struct tun_net *tn;
struct tun_struct *tun;
struct net_device *dev;
+ const struct cred *cred = current_cred();
int err;
tn = net_generic(net, tun_net_id);
@@ -712,11 +726,12 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
/* Check permissions */
if (((tun->owner != -1 &&
- current->euid != tun->owner) ||
+ cred->euid != tun->owner) ||
(tun->group != -1 &&
- current->egid != tun->group)) &&
- !capable(CAP_NET_ADMIN))
+ cred->egid != tun->group)) &&
+ !capable(CAP_NET_ADMIN)) {
return -EPERM;
+ }
}
else if (__dev_get_by_name(net, ifr->ifr_name))
return -EINVAL;
@@ -750,6 +765,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
return -ENOMEM;
dev_net_set(dev, net);
+
tun = netdev_priv(dev);
tun->dev = dev;
tun->flags = flags;
@@ -883,7 +899,6 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
void __user* argp = (void __user*)arg;
struct ifreq ifr;
int ret;
- DECLARE_MAC_BUF(mac);
if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89)
if (copy_from_user(&ifr, argp, sizeof ifr))
@@ -1011,8 +1026,8 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file,
case SIOCSIFHWADDR:
/* Set hw address */
- DBG(KERN_DEBUG "%s: set hw address: %s\n",
- tun->dev->name, print_mac(mac, ifr.ifr_hwaddr.sa_data));
+ DBG(KERN_DEBUG "%s: set hw address: %pM\n",
+ tun->dev->name, ifr.ifr_hwaddr.sa_data);
rtnl_lock();
ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr);
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 734ce0977f02..0009f4e34433 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -1729,7 +1729,6 @@ typhoon_rx(struct typhoon *tp, struct basic_ring *rxRing, volatile __le32 * read
netif_receive_skb(new_skb);
spin_unlock(&tp->state_lock);
- tp->dev->last_rx = jiffies;
received++;
budget--;
}
@@ -1756,7 +1755,6 @@ static int
typhoon_poll(struct napi_struct *napi, int budget)
{
struct typhoon *tp = container_of(napi, struct typhoon, napi);
- struct net_device *dev = tp->dev;
struct typhoon_indexes *indexes = tp->indexes;
int work_done;
@@ -1785,7 +1783,7 @@ typhoon_poll(struct napi_struct *napi, int budget)
}
if (work_done < budget) {
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
iowrite32(TYPHOON_INTR_NONE,
tp->ioaddr + TYPHOON_REG_INTR_MASK);
typhoon_post_pci_writes(tp->ioaddr);
@@ -1798,7 +1796,7 @@ static irqreturn_t
typhoon_interrupt(int irq, void *dev_instance)
{
struct net_device *dev = dev_instance;
- struct typhoon *tp = dev->priv;
+ struct typhoon *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->ioaddr;
u32 intr_status;
@@ -1808,10 +1806,10 @@ typhoon_interrupt(int irq, void *dev_instance)
iowrite32(intr_status, ioaddr + TYPHOON_REG_INTR_STATUS);
- if (netif_rx_schedule_prep(dev, &tp->napi)) {
+ if (netif_rx_schedule_prep(&tp->napi)) {
iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
typhoon_post_pci_writes(ioaddr);
- __netif_rx_schedule(dev, &tp->napi);
+ __netif_rx_schedule(&tp->napi);
} else {
printk(KERN_ERR "%s: Error, poll already scheduled\n",
dev->name);
@@ -2311,7 +2309,6 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
struct cmd_desc xp_cmd;
struct resp_desc xp_resp[3];
int err = 0;
- DECLARE_MAC_BUF(mac);
if(!did_version++)
printk(KERN_INFO "%s", version);
@@ -2526,11 +2523,11 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
pci_set_drvdata(pdev, dev);
- printk(KERN_INFO "%s: %s at %s 0x%llx, %s\n",
+ printk(KERN_INFO "%s: %s at %s 0x%llx, %pM\n",
dev->name, typhoon_card_info[card_id].name,
use_mmio ? "MMIO" : "IO",
(unsigned long long)pci_resource_start(pdev, use_mmio),
- print_mac(mac, dev->dev_addr));
+ dev->dev_addr);
/* xp_resp still contains the response to the READ_VERSIONS command.
* For debugging, let the user know what version he has.
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index c87747bb24c5..7d5a1303e30d 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -188,17 +188,6 @@ static void mem_disp(u8 *addr, int size)
}
#endif /* DEBUG */
-#ifdef CONFIG_UGETH_FILTERING
-static void enqueue(struct list_head *node, struct list_head *lh)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&ugeth_lock, flags);
- list_add_tail(node, lh);
- spin_unlock_irqrestore(&ugeth_lock, flags);
-}
-#endif /* CONFIG_UGETH_FILTERING */
-
static struct list_head *dequeue(struct list_head *lh)
{
unsigned long flags;
@@ -391,23 +380,6 @@ static int dump_init_enet_entries(struct ucc_geth_private *ugeth,
}
#endif
-#ifdef CONFIG_UGETH_FILTERING
-static struct enet_addr_container *get_enet_addr_container(void)
-{
- struct enet_addr_container *enet_addr_cont;
-
- /* allocate memory */
- enet_addr_cont = kmalloc(sizeof(struct enet_addr_container), GFP_KERNEL);
- if (!enet_addr_cont) {
- ugeth_err("%s: No memory for enet_addr_container object.",
- __func__);
- return NULL;
- }
-
- return enet_addr_cont;
-}
-#endif /* CONFIG_UGETH_FILTERING */
-
static void put_enet_addr_container(struct enet_addr_container *enet_addr_cont)
{
kfree(enet_addr_cont);
@@ -420,28 +392,6 @@ static void set_mac_addr(__be16 __iomem *reg, u8 *mac)
out_be16(&reg[2], ((u16)mac[1] << 8) | mac[0]);
}
-#ifdef CONFIG_UGETH_FILTERING
-static int hw_add_addr_in_paddr(struct ucc_geth_private *ugeth,
- u8 *p_enet_addr, u8 paddr_num)
-{
- struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt;
-
- if (!(paddr_num < NUM_OF_PADDRS)) {
- ugeth_warn("%s: Illegal paddr_num.", __func__);
- return -EINVAL;
- }
-
- p_82xx_addr_filt =
- (struct ucc_geth_82xx_address_filtering_pram *) ugeth->p_rx_glbl_pram->
- addressfiltering;
-
- /* Ethernet frames are defined in Little Endian mode, */
- /* therefore to insert the address we reverse the bytes. */
- set_mac_addr(&p_82xx_addr_filt->paddr[paddr_num].h, p_enet_addr);
- return 0;
-}
-#endif /* CONFIG_UGETH_FILTERING */
-
static int hw_clear_addr_in_paddr(struct ucc_geth_private *ugeth, u8 paddr_num)
{
struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt;
@@ -1615,8 +1565,8 @@ static int init_phy(struct net_device *dev)
priv->oldspeed = 0;
priv->oldduplex = -1;
- snprintf(phy_id, BUS_ID_SIZE, PHY_ID_FMT, priv->ug_info->mdio_bus,
- priv->ug_info->phy_address);
+ snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT, priv->ug_info->mdio_bus,
+ priv->ug_info->phy_address);
phydev = phy_connect(dev, phy_id, &adjust_link, 0, priv->phy_interface);
@@ -1647,6 +1597,7 @@ static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth)
struct ucc_fast_private *uccf;
u32 cecr_subblock;
u32 temp;
+ int i = 10;
uccf = ugeth->uccf;
@@ -1664,8 +1615,9 @@ static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth)
/* Wait for command to complete */
do {
+ msleep(10);
temp = in_be32(uccf->p_ucce);
- } while (!(temp & UCCE_GRA));
+ } while (!(temp & UCCE_GRA) && --i);
uccf->stopped_tx = 1;
@@ -1677,6 +1629,7 @@ static int ugeth_graceful_stop_rx(struct ucc_geth_private * ugeth)
struct ucc_fast_private *uccf;
u32 cecr_subblock;
u8 temp;
+ int i = 10;
uccf = ugeth->uccf;
@@ -1694,9 +1647,9 @@ static int ugeth_graceful_stop_rx(struct ucc_geth_private * ugeth)
ucc_num);
qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock,
QE_CR_PROTOCOL_ETHERNET, 0);
-
+ msleep(10);
temp = in_8(&ugeth->p_rx_glbl_pram->rxgstpack);
- } while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX));
+ } while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX) && --i);
uccf->stopped_rx = 1;
@@ -1799,196 +1752,6 @@ static void ugeth_dump_regs(struct ucc_geth_private *ugeth)
#endif
}
-#ifdef CONFIG_UGETH_FILTERING
-static int ugeth_ext_filtering_serialize_tad(struct ucc_geth_tad_params *
- p_UccGethTadParams,
- struct qe_fltr_tad *qe_fltr_tad)
-{
- u16 temp;
-
- /* Zero serialized TAD */
- memset(qe_fltr_tad, 0, QE_FLTR_TAD_SIZE);
-
- qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_V; /* Must have this */
- if (p_UccGethTadParams->rx_non_dynamic_extended_features_mode ||
- (p_UccGethTadParams->vtag_op != UCC_GETH_VLAN_OPERATION_TAGGED_NOP)
- || (p_UccGethTadParams->vnontag_op !=
- UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP)
- )
- qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_EF;
- if (p_UccGethTadParams->reject_frame)
- qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_REJ;
- temp =
- (u16) (((u16) p_UccGethTadParams->
- vtag_op) << UCC_GETH_TAD_VTAG_OP_SHIFT);
- qe_fltr_tad->serialized[0] |= (u8) (temp >> 8); /* upper bits */
-
- qe_fltr_tad->serialized[1] |= (u8) (temp & 0x00ff); /* lower bits */
- if (p_UccGethTadParams->vnontag_op ==
- UCC_GETH_VLAN_OPERATION_NON_TAGGED_Q_TAG_INSERT)
- qe_fltr_tad->serialized[1] |= UCC_GETH_TAD_V_NON_VTAG_OP;
- qe_fltr_tad->serialized[1] |=
- p_UccGethTadParams->rqos << UCC_GETH_TAD_RQOS_SHIFT;
-
- qe_fltr_tad->serialized[2] |=
- p_UccGethTadParams->vpri << UCC_GETH_TAD_V_PRIORITY_SHIFT;
- /* upper bits */
- qe_fltr_tad->serialized[2] |= (u8) (p_UccGethTadParams->vid >> 8);
- /* lower bits */
- qe_fltr_tad->serialized[3] |= (u8) (p_UccGethTadParams->vid & 0x00ff);
-
- return 0;
-}
-
-static struct enet_addr_container_t
- *ugeth_82xx_filtering_get_match_addr_in_hash(struct ucc_geth_private *ugeth,
- struct enet_addr *p_enet_addr)
-{
- struct enet_addr_container *enet_addr_cont;
- struct list_head *p_lh;
- u16 i, num;
- int32_t j;
- u8 *p_counter;
-
- if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {
- p_lh = &ugeth->group_hash_q;
- p_counter = &(ugeth->numGroupAddrInHash);
- } else {
- p_lh = &ugeth->ind_hash_q;
- p_counter = &(ugeth->numIndAddrInHash);
- }
-
- if (!p_lh)
- return NULL;
-
- num = *p_counter;
-
- for (i = 0; i < num; i++) {
- enet_addr_cont =
- (struct enet_addr_container *)
- ENET_ADDR_CONT_ENTRY(dequeue(p_lh));
- for (j = ENET_NUM_OCTETS_PER_ADDRESS - 1; j >= 0; j--) {
- if ((*p_enet_addr)[j] != (enet_addr_cont->address)[j])
- break;
- if (j == 0)
- return enet_addr_cont; /* Found */
- }
- enqueue(p_lh, &enet_addr_cont->node); /* Put it back */
- }
- return NULL;
-}
-
-static int ugeth_82xx_filtering_add_addr_in_hash(struct ucc_geth_private *ugeth,
- struct enet_addr *p_enet_addr)
-{
- enum ucc_geth_enet_address_recognition_location location;
- struct enet_addr_container *enet_addr_cont;
- struct list_head *p_lh;
- u8 i;
- u32 limit;
- u8 *p_counter;
-
- if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {
- p_lh = &ugeth->group_hash_q;
- limit = ugeth->ug_info->maxGroupAddrInHash;
- location =
- UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_GROUP_HASH;
- p_counter = &(ugeth->numGroupAddrInHash);
- } else {
- p_lh = &ugeth->ind_hash_q;
- limit = ugeth->ug_info->maxIndAddrInHash;
- location =
- UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_INDIVIDUAL_HASH;
- p_counter = &(ugeth->numIndAddrInHash);
- }
-
- if ((enet_addr_cont =
- ugeth_82xx_filtering_get_match_addr_in_hash(ugeth, p_enet_addr))) {
- list_add(p_lh, &enet_addr_cont->node); /* Put it back */
- return 0;
- }
- if ((!p_lh) || (!(*p_counter < limit)))
- return -EBUSY;
- if (!(enet_addr_cont = get_enet_addr_container()))
- return -ENOMEM;
- for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++)
- (enet_addr_cont->address)[i] = (*p_enet_addr)[i];
- enet_addr_cont->location = location;
- enqueue(p_lh, &enet_addr_cont->node); /* Put it back */
- ++(*p_counter);
-
- hw_add_addr_in_hash(ugeth, enet_addr_cont->address);
- return 0;
-}
-
-static int ugeth_82xx_filtering_clear_addr_in_hash(struct ucc_geth_private *ugeth,
- struct enet_addr *p_enet_addr)
-{
- struct ucc_geth_82xx_address_filtering_pram *p_82xx_addr_filt;
- struct enet_addr_container *enet_addr_cont;
- struct ucc_fast_private *uccf;
- enum comm_dir comm_dir;
- u16 i, num;
- struct list_head *p_lh;
- u32 *addr_h, *addr_l;
- u8 *p_counter;
-
- uccf = ugeth->uccf;
-
- p_82xx_addr_filt =
- (struct ucc_geth_82xx_address_filtering_pram *) ugeth->p_rx_glbl_pram->
- addressfiltering;
-
- if (!
- (enet_addr_cont =
- ugeth_82xx_filtering_get_match_addr_in_hash(ugeth, p_enet_addr)))
- return -ENOENT;
-
- /* It's been found and removed from the CQ. */
- /* Now destroy its container */
- put_enet_addr_container(enet_addr_cont);
-
- if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {
- addr_h = &(p_82xx_addr_filt->gaddr_h);
- addr_l = &(p_82xx_addr_filt->gaddr_l);
- p_lh = &ugeth->group_hash_q;
- p_counter = &(ugeth->numGroupAddrInHash);
- } else {
- addr_h = &(p_82xx_addr_filt->iaddr_h);
- addr_l = &(p_82xx_addr_filt->iaddr_l);
- p_lh = &ugeth->ind_hash_q;
- p_counter = &(ugeth->numIndAddrInHash);
- }
-
- comm_dir = 0;
- if (uccf->enabled_tx)
- comm_dir |= COMM_DIR_TX;
- if (uccf->enabled_rx)
- comm_dir |= COMM_DIR_RX;
- if (comm_dir)
- ugeth_disable(ugeth, comm_dir);
-
- /* Clear the hash table. */
- out_be32(addr_h, 0x00000000);
- out_be32(addr_l, 0x00000000);
-
- /* Add all remaining CQ elements back into hash */
- num = --(*p_counter);
- for (i = 0; i < num; i++) {
- enet_addr_cont =
- (struct enet_addr_container *)
- ENET_ADDR_CONT_ENTRY(dequeue(p_lh));
- hw_add_addr_in_hash(ugeth, enet_addr_cont->address);
- enqueue(p_lh, &enet_addr_cont->node); /* Put it back */
- }
-
- if (comm_dir)
- ugeth_enable(ugeth, comm_dir);
-
- return 0;
-}
-#endif /* CONFIG_UGETH_FILTERING */
-
static int ugeth_82xx_filtering_clear_all_addr_in_hash(struct ucc_geth_private *
ugeth,
enum enet_addr_type
@@ -2051,28 +1814,6 @@ static int ugeth_82xx_filtering_clear_all_addr_in_hash(struct ucc_geth_private *
return 0;
}
-#ifdef CONFIG_UGETH_FILTERING
-static int ugeth_82xx_filtering_add_addr_in_paddr(struct ucc_geth_private *ugeth,
- struct enet_addr *p_enet_addr,
- u8 paddr_num)
-{
- int i;
-
- if ((*p_enet_addr)[0] & ENET_GROUP_ADDR)
- ugeth_warn
- ("%s: multicast address added to paddr will have no "
- "effect - is this what you wanted?",
- __func__);
-
- ugeth->indAddrRegUsed[paddr_num] = 1; /* mark this paddr as used */
- /* store address in our database */
- for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++)
- ugeth->paddr[paddr_num][i] = (*p_enet_addr)[i];
- /* put in hardware */
- return hw_add_addr_in_paddr(ugeth, p_enet_addr, paddr_num);
-}
-#endif /* CONFIG_UGETH_FILTERING */
-
static int ugeth_82xx_filtering_clear_addr_in_paddr(struct ucc_geth_private *ugeth,
u8 paddr_num)
{
@@ -2215,7 +1956,10 @@ static void ucc_geth_memclean(struct ucc_geth_private *ugeth)
while (!list_empty(&ugeth->ind_hash_q))
put_enet_addr_container(ENET_ADDR_CONT_ENTRY
(dequeue(&ugeth->ind_hash_q)));
-
+ if (ugeth->ug_regs) {
+ iounmap(ugeth->ug_regs);
+ ugeth->ug_regs = NULL;
+ }
}
static void ucc_geth_set_multi(struct net_device *dev)
@@ -2297,8 +2041,6 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth)
tempval &= ~(MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX);
out_be32(&ug_regs->maccfg1, tempval);
- free_irq(ugeth->ug_info->uf_info.irq, ugeth->dev);
-
ucc_geth_memclean(ugeth);
}
@@ -2419,11 +2161,15 @@ static int ucc_struct_init(struct ucc_geth_private *ugeth)
if (ucc_fast_init(uf_info, &ugeth->uccf)) {
if (netif_msg_probe(ugeth))
ugeth_err("%s: Failed to init uccf.", __func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
- ugeth->ug_regs = (struct ucc_geth __iomem *) ioremap(uf_info->regs, sizeof(struct ucc_geth));
+ ugeth->ug_regs = ioremap(uf_info->regs, sizeof(*ugeth->ug_regs));
+ if (!ugeth->ug_regs) {
+ if (netif_msg_probe(ugeth))
+ ugeth_err("%s: Failed to ioremap regs.", __func__);
+ return -ENOMEM;
+ }
return 0;
}
@@ -2475,7 +2221,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Bad number of Rx threads value.",
__func__);
- ucc_geth_memclean(ugeth);
return -EINVAL;
break;
}
@@ -2500,7 +2245,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Bad number of Tx threads value.",
__func__);
- ucc_geth_memclean(ugeth);
return -EINVAL;
break;
}
@@ -2554,7 +2298,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: IPGIFG initialization parameter too large.",
__func__);
- ucc_geth_memclean(ugeth);
return ret_val;
}
@@ -2572,7 +2315,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Half Duplex initialization parameter too large.",
__func__);
- ucc_geth_memclean(ugeth);
return ret_val;
}
@@ -2627,7 +2369,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate memory for Tx bd rings.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
/* Zero unused end of bd ring, according to spec */
@@ -2663,7 +2404,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate memory for Rx bd rings.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
}
@@ -2679,7 +2419,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Could not allocate tx_skbuff",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2711,7 +2450,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Could not allocate rx_skbuff",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2745,7 +2483,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
ugeth->p_tx_glbl_pram =
@@ -2768,7 +2505,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for p_thread_data_tx.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2798,7 +2534,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for p_send_q_mem_reg.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2842,7 +2577,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for p_scheduler.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2893,7 +2627,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
("%s: Can not allocate DPRAM memory for"
" p_tx_fw_statistics_pram.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
ugeth->p_tx_fw_statistics_pram =
@@ -2933,7 +2666,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
ugeth->p_rx_glbl_pram =
@@ -2955,7 +2687,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for p_thread_data_rx.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -2979,7 +2710,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for"
" p_rx_fw_statistics_pram.", __func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
ugeth->p_rx_fw_statistics_pram =
@@ -3002,7 +2732,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for"
" p_rx_irq_coalescing_tbl.", __func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -3071,7 +2800,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for p_rx_bd_qs_tbl.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -3148,7 +2876,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Null Extended Filtering Chain Pointer.",
__func__);
- ucc_geth_memclean(ugeth);
return -EINVAL;
}
@@ -3162,7 +2889,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for"
" p_exf_glbl_param.", __func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
@@ -3210,7 +2936,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate memory for"
" p_UccInitEnetParamShadows.", __func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
/* Zero out *p_init_enet_param_shadow */
@@ -3245,7 +2970,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Invalid largest External Lookup Key Size.",
__func__);
- ucc_geth_memclean(ugeth);
return -EINVAL;
}
ugeth->p_init_enet_param_shadow->largestexternallookupkeysize =
@@ -3272,7 +2996,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Can not fill p_init_enet_param_shadow.",
__func__);
- ucc_geth_memclean(ugeth);
return ret_val;
}
@@ -3288,7 +3011,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Can not fill p_init_enet_param_shadow.",
__func__);
- ucc_geth_memclean(ugeth);
return ret_val;
}
@@ -3298,7 +3020,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Can not fill Rx bds with buffers.",
__func__);
- ucc_geth_memclean(ugeth);
return ret_val;
}
}
@@ -3310,7 +3031,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
ugeth_err
("%s: Can not allocate DPRAM memory for p_init_enet_pram.",
__func__);
- ucc_geth_memclean(ugeth);
return -ENOMEM;
}
p_init_enet_pram =
@@ -3352,28 +3072,6 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
return 0;
}
-/* ucc_geth_timeout gets called when a packet has not been
- * transmitted after a set amount of time.
- * For now, assume that clearing out all the structures, and
- * starting over will fix the problem. */
-static void ucc_geth_timeout(struct net_device *dev)
-{
- struct ucc_geth_private *ugeth = netdev_priv(dev);
-
- ugeth_vdbg("%s: IN", __func__);
-
- dev->stats.tx_errors++;
-
- ugeth_dump_regs(ugeth);
-
- if (dev->flags & IFF_UP) {
- ucc_geth_stop(ugeth);
- ucc_geth_startup(ugeth);
- }
-
- netif_tx_schedule_all(dev);
-}
-
/* This is called by the kernel when a frame is ready for transmission. */
/* It is pointed to by the dev->hard_start_xmit function pointer */
static int ucc_geth_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -3502,8 +3200,6 @@ static int ucc_geth_rx(struct ucc_geth_private *ugeth, u8 rxQ, int rx_work_limit
netif_receive_skb(skb);
}
- ugeth->dev->last_rx = jiffies;
-
skb = get_new_skb(ugeth, bd);
if (!skb) {
if (netif_msg_rx_err(ugeth))
@@ -3592,7 +3288,7 @@ static int ucc_geth_poll(struct napi_struct *napi, int budget)
struct ucc_fast_private *uccf;
u32 uccm;
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
uccf = ugeth->uccf;
uccm = in_be32(uccf->p_uccm);
uccm |= UCCE_RX_EVENTS;
@@ -3626,10 +3322,10 @@ static irqreturn_t ucc_geth_irq_handler(int irq, void *info)
/* check for receive events that require processing */
if (ucce & UCCE_RX_EVENTS) {
- if (netif_rx_schedule_prep(dev, &ugeth->napi)) {
+ if (netif_rx_schedule_prep(&ugeth->napi)) {
uccm &= ~UCCE_RX_EVENTS;
out_be32(uccf->p_uccm, uccm);
- __netif_rx_schedule(dev, &ugeth->napi);
+ __netif_rx_schedule(&ugeth->napi);
}
}
@@ -3697,7 +3393,7 @@ static int ucc_geth_open(struct net_device *dev)
if (err) {
if (netif_msg_ifup(ugeth))
ugeth_err("%s: Cannot configure internal struct, aborting.", dev->name);
- return err;
+ goto out_err_stop;
}
napi_enable(&ugeth->napi);
@@ -3738,22 +3434,19 @@ static int ucc_geth_open(struct net_device *dev)
phy_start(ugeth->phydev);
- err =
- request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler, 0,
- "UCC Geth", dev);
+ err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
if (err) {
if (netif_msg_ifup(ugeth))
- ugeth_err("%s: Cannot get IRQ for net device, aborting.",
- dev->name);
- ucc_geth_stop(ugeth);
+ ugeth_err("%s: Cannot enable net device, aborting.", dev->name);
goto out_err;
}
- err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
+ err = request_irq(ugeth->ug_info->uf_info.irq, ucc_geth_irq_handler,
+ 0, "UCC Geth", dev);
if (err) {
if (netif_msg_ifup(ugeth))
- ugeth_err("%s: Cannot enable net device, aborting.", dev->name);
- ucc_geth_stop(ugeth);
+ ugeth_err("%s: Cannot get IRQ for net device, aborting.",
+ dev->name);
goto out_err;
}
@@ -3763,7 +3456,8 @@ static int ucc_geth_open(struct net_device *dev)
out_err:
napi_disable(&ugeth->napi);
-
+out_err_stop:
+ ucc_geth_stop(ugeth);
return err;
}
@@ -3778,6 +3472,8 @@ static int ucc_geth_close(struct net_device *dev)
ucc_geth_stop(ugeth);
+ free_irq(ugeth->ug_info->uf_info.irq, ugeth->dev);
+
phy_disconnect(ugeth->phydev);
ugeth->phydev = NULL;
@@ -3786,6 +3482,45 @@ static int ucc_geth_close(struct net_device *dev)
return 0;
}
+/* Reopen device. This will reset the MAC and PHY. */
+static void ucc_geth_timeout_work(struct work_struct *work)
+{
+ struct ucc_geth_private *ugeth;
+ struct net_device *dev;
+
+ ugeth = container_of(work, struct ucc_geth_private, timeout_work);
+ dev = ugeth->dev;
+
+ ugeth_vdbg("%s: IN", __func__);
+
+ dev->stats.tx_errors++;
+
+ ugeth_dump_regs(ugeth);
+
+ if (dev->flags & IFF_UP) {
+ /*
+ * Must reset MAC *and* PHY. This is done by reopening
+ * the device.
+ */
+ ucc_geth_close(dev);
+ ucc_geth_open(dev);
+ }
+
+ netif_tx_schedule_all(dev);
+}
+
+/*
+ * ucc_geth_timeout gets called when a packet has not been
+ * transmitted after a set amount of time.
+ */
+static void ucc_geth_timeout(struct net_device *dev)
+{
+ struct ucc_geth_private *ugeth = netdev_priv(dev);
+
+ netif_carrier_off(dev);
+ schedule_work(&ugeth->timeout_work);
+}
+
static phy_interface_t to_phy_interface(const char *phy_connection_type)
{
if (strcasecmp(phy_connection_type, "mii") == 0)
@@ -4026,6 +3761,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma
dev->hard_start_xmit = ucc_geth_start_xmit;
dev->tx_timeout = ucc_geth_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
+ INIT_WORK(&ugeth->timeout_work, ucc_geth_timeout_work);
netif_napi_add(dev, &ugeth->napi, ucc_geth_poll, UCC_GETH_DEV_WEIGHT);
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = ucc_netpoll;
diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h
index abc0e2242634..d74d2f7cb739 100644
--- a/drivers/net/ucc_geth.h
+++ b/drivers/net/ucc_geth.h
@@ -1186,6 +1186,7 @@ struct ucc_geth_private {
struct ucc_fast_private *uccf;
struct net_device *dev;
struct napi_struct napi;
+ struct work_struct timeout_work;
struct ucc_geth __iomem *ug_regs;
struct ucc_geth_init_pram *p_init_enet_param_shadow;
struct ucc_geth_exf_global_pram __iomem *p_exf_glbl_param;
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index de57490103fc..e009481c606c 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -246,10 +246,11 @@ out:
static void asix_async_cmd_callback(struct urb *urb)
{
struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
+ int status = urb->status;
- if (urb->status < 0)
+ if (status < 0)
printk(KERN_DEBUG "asix_async_cmd_callback() failed with %d",
- urb->status);
+ status);
kfree(req);
usb_free_urb(urb);
diff --git a/drivers/net/usb/catc.c b/drivers/net/usb/catc.c
index 466a89e24444..cb7acbbb2798 100644
--- a/drivers/net/usb/catc.c
+++ b/drivers/net/usb/catc.c
@@ -229,14 +229,15 @@ static void catc_rx_done(struct urb *urb)
u8 *pkt_start = urb->transfer_buffer;
struct sk_buff *skb;
int pkt_len, pkt_offset = 0;
+ int status = urb->status;
if (!catc->is_f5u011) {
clear_bit(RX_RUNNING, &catc->flags);
pkt_offset = 2;
}
- if (urb->status) {
- dbg("rx_done, status %d, length %d", urb->status, urb->actual_length);
+ if (status) {
+ dbg("rx_done, status %d, length %d", status, urb->actual_length);
return;
}
@@ -271,16 +272,14 @@ static void catc_rx_done(struct urb *urb)
} while (pkt_start - (u8 *) urb->transfer_buffer < urb->actual_length);
- catc->netdev->last_rx = jiffies;
-
if (catc->is_f5u011) {
if (atomic_read(&catc->recq_sz)) {
- int status;
+ int state;
atomic_dec(&catc->recq_sz);
dbg("getting extra packet");
urb->dev = catc->usbdev;
- if ((status = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
- dbg("submit(rx_urb) status %d", status);
+ if ((state = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+ dbg("submit(rx_urb) status %d", state);
}
} else {
clear_bit(RX_RUNNING, &catc->flags);
@@ -292,8 +291,9 @@ static void catc_irq_done(struct urb *urb)
{
struct catc *catc = urb->context;
u8 *data = urb->transfer_buffer;
- int status;
+ int status = urb->status;
unsigned int hasdata = 0, linksts = LinkNoChange;
+ int res;
if (!catc->is_f5u011) {
hasdata = data[1] & 0x80;
@@ -309,7 +309,7 @@ static void catc_irq_done(struct urb *urb)
linksts = LinkBad;
}
- switch (urb->status) {
+ switch (status) {
case 0: /* success */
break;
case -ECONNRESET: /* unlink */
@@ -318,7 +318,7 @@ static void catc_irq_done(struct urb *urb)
return;
/* -EPIPE: should clear the halt */
default: /* error */
- dbg("irq_done, status %d, data %02x %02x.", urb->status, data[0], data[1]);
+ dbg("irq_done, status %d, data %02x %02x.", status, data[0], data[1]);
goto resubmit;
}
@@ -338,17 +338,17 @@ static void catc_irq_done(struct urb *urb)
atomic_inc(&catc->recq_sz);
} else {
catc->rx_urb->dev = catc->usbdev;
- if ((status = usb_submit_urb(catc->rx_urb, GFP_ATOMIC)) < 0) {
- err("submit(rx_urb) status %d", status);
+ if ((res = usb_submit_urb(catc->rx_urb, GFP_ATOMIC)) < 0) {
+ err("submit(rx_urb) status %d", res);
}
}
}
resubmit:
- status = usb_submit_urb (urb, GFP_ATOMIC);
- if (status)
+ res = usb_submit_urb (urb, GFP_ATOMIC);
+ if (res)
err ("can't resubmit intr, %s-%s, status %d",
catc->usbdev->bus->bus_name,
- catc->usbdev->devpath, status);
+ catc->usbdev->devpath, res);
}
/*
@@ -380,9 +380,9 @@ static void catc_tx_done(struct urb *urb)
{
struct catc *catc = urb->context;
unsigned long flags;
- int r;
+ int r, status = urb->status;
- if (urb->status == -ECONNRESET) {
+ if (status == -ECONNRESET) {
dbg("Tx Reset.");
urb->status = 0;
catc->netdev->trans_start = jiffies;
@@ -392,8 +392,8 @@ static void catc_tx_done(struct urb *urb)
return;
}
- if (urb->status) {
- dbg("tx_done, status %d, length %d", urb->status, urb->actual_length);
+ if (status) {
+ dbg("tx_done, status %d, length %d", status, urb->actual_length);
return;
}
@@ -504,9 +504,10 @@ static void catc_ctrl_done(struct urb *urb)
struct catc *catc = urb->context;
struct ctrl_queue *q;
unsigned long flags;
+ int status = urb->status;
- if (urb->status)
- dbg("ctrl_done, status %d, len %d.", urb->status, urb->actual_length);
+ if (status)
+ dbg("ctrl_done, status %d, len %d.", status, urb->actual_length);
spin_lock_irqsave(&catc->ctrl_lock, flags);
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c
index db3377dae9d5..edd244f3acb5 100644
--- a/drivers/net/usb/dm9601.c
+++ b/drivers/net/usb/dm9601.c
@@ -123,10 +123,11 @@ static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value)
static void dm_write_async_callback(struct urb *urb)
{
struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
+ int status = urb->status;
- if (urb->status < 0)
+ if (status < 0)
printk(KERN_DEBUG "dm_write_async_callback() failed with %d\n",
- urb->status);
+ status);
kfree(req);
usb_free_urb(urb);
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 8e90891f0e42..198ce3cf378a 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -417,6 +417,11 @@ static const struct usb_device_id hso_ids[] = {
{USB_DEVICE(0x0af0, 0x7401)}, /* GI 0401 */
{USB_DEVICE(0x0af0, 0x7501)}, /* GTM 382 */
{USB_DEVICE(0x0af0, 0x7601)}, /* GE40x */
+ {USB_DEVICE(0x0af0, 0x7701)},
+ {USB_DEVICE(0x0af0, 0x7801)},
+ {USB_DEVICE(0x0af0, 0x7901)},
+ {USB_DEVICE(0x0af0, 0x7361)},
+ {icon321_port_device(0x0af0, 0xd051)},
{}
};
MODULE_DEVICE_TABLE(usb, hso_ids);
@@ -658,10 +663,9 @@ static int hso_net_open(struct net_device *net)
odev->rx_buf_missing = sizeof(struct iphdr);
spin_unlock_irqrestore(&odev->net_lock, flags);
- hso_start_net_device(odev->parent);
-
/* We are up and running. */
set_bit(HSO_NET_RUNNING, &odev->flags);
+ hso_start_net_device(odev->parent);
/* Tell the kernel we are ready to start receiving from it */
netif_start_queue(net);
@@ -2750,18 +2754,21 @@ static int hso_resume(struct usb_interface *iface)
if (network_table[i] &&
(network_table[i]->interface == iface)) {
hso_net = dev2net(network_table[i]);
- /* First transmit any lingering data, then restart the
- * device. */
- if (hso_net->skb_tx_buf) {
- dev_dbg(&iface->dev,
- "Transmitting lingering data\n");
- hso_net_start_xmit(hso_net->skb_tx_buf,
- hso_net->net);
- hso_net->skb_tx_buf = NULL;
+ if (hso_net->flags & IFF_UP) {
+ /* First transmit any lingering data,
+ then restart the device. */
+ if (hso_net->skb_tx_buf) {
+ dev_dbg(&iface->dev,
+ "Transmitting"
+ " lingering data\n");
+ hso_net_start_xmit(hso_net->skb_tx_buf,
+ hso_net->net);
+ hso_net->skb_tx_buf = NULL;
+ }
+ result = hso_start_net_device(network_table[i]);
+ if (result)
+ goto out;
}
- result = hso_start_net_device(network_table[i]);
- if (result)
- goto out;
}
}
@@ -2894,6 +2901,7 @@ static struct usb_driver hso_driver = {
.id_table = hso_ids,
.suspend = hso_suspend,
.resume = hso_resume,
+ .reset_resume = hso_resume,
.supports_autosuspend = 1,
};
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index fdbf3be24fda..2ee034f70d1c 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -516,8 +516,9 @@ static void int_callback(struct urb *u)
{
struct kaweth_device *kaweth = u->context;
int act_state;
+ int status = u->status;
- switch (u->status) {
+ switch (status) {
case 0: /* success */
break;
case -ECONNRESET: /* unlink */
@@ -598,6 +599,7 @@ static void kaweth_usb_receive(struct urb *urb)
{
struct kaweth_device *kaweth = urb->context;
struct net_device *net = kaweth->net;
+ int status = urb->status;
int count = urb->actual_length;
int count2 = urb->transfer_buffer_length;
@@ -606,7 +608,7 @@ static void kaweth_usb_receive(struct urb *urb)
struct sk_buff *skb;
- if(unlikely(urb->status == -ECONNRESET || urb->status == -ESHUTDOWN))
+ if(unlikely(status == -ECONNRESET || status == -ESHUTDOWN))
/* we are killed - set a flag and wake the disconnect handler */
{
kaweth->end = 1;
@@ -621,10 +623,10 @@ static void kaweth_usb_receive(struct urb *urb)
}
spin_unlock(&kaweth->device_lock);
- if(urb->status && urb->status != -EREMOTEIO && count != 1) {
+ if(status && status != -EREMOTEIO && count != 1) {
err("%s RX status: %d count: %d packet_len: %d",
net->name,
- urb->status,
+ status,
count,
(int)pkt_len);
kaweth_resubmit_rx_urb(kaweth, GFP_ATOMIC);
@@ -775,10 +777,11 @@ static void kaweth_usb_transmit_complete(struct urb *urb)
{
struct kaweth_device *kaweth = urb->context;
struct sk_buff *skb = kaweth->tx_skb;
+ int status = urb->status;
- if (unlikely(urb->status != 0))
- if (urb->status != -ENOENT)
- dbg("%s: TX status %d.", kaweth->net->name, urb->status);
+ if (unlikely(status != 0))
+ if (status != -ENOENT)
+ dbg("%s: TX status %d.", kaweth->net->name, status);
netif_wake_queue(kaweth->net);
dev_kfree_skb_irq(skb);
diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c
index b5143509e8be..5385d66b306e 100644
--- a/drivers/net/usb/mcs7830.c
+++ b/drivers/net/usb/mcs7830.c
@@ -115,10 +115,11 @@ static int mcs7830_set_reg(struct usbnet *dev, u16 index, u16 size, void *data)
static void mcs7830_async_cmd_callback(struct urb *urb)
{
struct usb_ctrlrequest *req = (struct usb_ctrlrequest *)urb->context;
+ int status = urb->status;
- if (urb->status < 0)
+ if (status < 0)
printk(KERN_DEBUG "%s() failed with %d\n",
- __func__, urb->status);
+ __func__, status);
kfree(req);
usb_free_urb(urb);
@@ -344,14 +345,14 @@ out:
static int mcs7830_mdio_read(struct net_device *netdev, int phy_id,
int location)
{
- struct usbnet *dev = netdev->priv;
+ struct usbnet *dev = netdev_priv(netdev);
return mcs7830_read_phy(dev, location);
}
static void mcs7830_mdio_write(struct net_device *netdev, int phy_id,
int location, int val)
{
- struct usbnet *dev = netdev->priv;
+ struct usbnet *dev = netdev_priv(netdev);
mcs7830_write_phy(dev, location, val);
}
diff --git a/drivers/net/usb/pegasus.c b/drivers/net/usb/pegasus.c
index 7914867110ed..166880c113d6 100644
--- a/drivers/net/usb/pegasus.c
+++ b/drivers/net/usb/pegasus.c
@@ -99,11 +99,12 @@ static int update_eth_regs_async(pegasus_t *);
static void ctrl_callback(struct urb *urb)
{
pegasus_t *pegasus = urb->context;
+ int status = urb->status;
if (!pegasus)
return;
- switch (urb->status) {
+ switch (status) {
case 0:
if (pegasus->flags & ETH_REGS_CHANGE) {
pegasus->flags &= ~ETH_REGS_CHANGE;
@@ -119,7 +120,7 @@ static void ctrl_callback(struct urb *urb)
default:
if (netif_msg_drv(pegasus) && printk_ratelimit())
dev_dbg(&pegasus->intf->dev, "%s, status %d\n",
- __func__, urb->status);
+ __func__, status);
}
pegasus->flags &= ~ETH_REGS_CHANGED;
wake_up(&pegasus->ctrl_wait);
@@ -611,6 +612,7 @@ static void read_bulk_callback(struct urb *urb)
pegasus_t *pegasus = urb->context;
struct net_device *net;
int rx_status, count = urb->actual_length;
+ int status = urb->status;
u8 *buf = urb->transfer_buffer;
__u16 pkt_len;
@@ -621,7 +623,7 @@ static void read_bulk_callback(struct urb *urb)
if (!netif_device_present(net) || !netif_running(net))
return;
- switch (urb->status) {
+ switch (status) {
case 0:
break;
case -ETIME:
@@ -639,11 +641,11 @@ static void read_bulk_callback(struct urb *urb)
case -ECONNRESET:
case -ESHUTDOWN:
if (netif_msg_ifdown(pegasus))
- pr_debug("%s: rx unlink, %d\n", net->name, urb->status);
+ pr_debug("%s: rx unlink, %d\n", net->name, status);
return;
default:
if (netif_msg_rx_err(pegasus))
- pr_debug("%s: RX status %d\n", net->name, urb->status);
+ pr_debug("%s: RX status %d\n", net->name, status);
goto goon;
}
@@ -769,6 +771,7 @@ static void write_bulk_callback(struct urb *urb)
{
pegasus_t *pegasus = urb->context;
struct net_device *net;
+ int status = urb->status;
if (!pegasus)
return;
@@ -778,7 +781,7 @@ static void write_bulk_callback(struct urb *urb)
if (!netif_device_present(net) || !netif_running(net))
return;
- switch (urb->status) {
+ switch (status) {
case -EPIPE:
/* FIXME schedule_work() to clear the tx halt */
netif_stop_queue(net);
@@ -790,11 +793,11 @@ static void write_bulk_callback(struct urb *urb)
case -ECONNRESET:
case -ESHUTDOWN:
if (netif_msg_ifdown(pegasus))
- pr_debug("%s: tx unlink, %d\n", net->name, urb->status);
+ pr_debug("%s: tx unlink, %d\n", net->name, status);
return;
default:
if (netif_msg_tx_err(pegasus))
- pr_info("%s: TX status %d\n", net->name, urb->status);
+ pr_info("%s: TX status %d\n", net->name, status);
/* FALL THROUGH */
case 0:
break;
@@ -808,13 +811,13 @@ static void intr_callback(struct urb *urb)
{
pegasus_t *pegasus = urb->context;
struct net_device *net;
- int status;
+ int res, status = urb->status;
if (!pegasus)
return;
net = pegasus->net;
- switch (urb->status) {
+ switch (status) {
case 0:
break;
case -ECONNRESET: /* unlink */
@@ -827,7 +830,7 @@ static void intr_callback(struct urb *urb)
*/
if (netif_msg_timer(pegasus))
pr_debug("%s: intr status %d\n", net->name,
- urb->status);
+ status);
}
if (urb->actual_length >= 6) {
@@ -854,12 +857,12 @@ static void intr_callback(struct urb *urb)
pegasus->stats.rx_missed_errors += ((d[3] & 0x7f) << 8) | d[4];
}
- status = usb_submit_urb(urb, GFP_ATOMIC);
- if (status == -ENODEV)
+ res = usb_submit_urb(urb, GFP_ATOMIC);
+ if (res == -ENODEV)
netif_device_detach(pegasus->net);
- if (status && netif_msg_timer(pegasus))
+ if (res && netif_msg_timer(pegasus))
printk(KERN_ERR "%s: can't resubmit interrupt urb, %d\n",
- net->name, status);
+ net->name, res);
}
static void pegasus_tx_timeout(struct net_device *net)
@@ -1213,7 +1216,7 @@ static void pegasus_set_multicast(struct net_device *net)
pegasus->eth_regs[EthCtrl0] |= RX_MULTICAST;
pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
if (netif_msg_link(pegasus))
- pr_info("%s: set allmulti\n", net->name);
+ pr_debug("%s: set allmulti\n", net->name);
} else {
pegasus->eth_regs[EthCtrl0] &= ~RX_MULTICAST;
pegasus->eth_regs[EthCtrl2] &= ~RX_PROMISCUOUS;
@@ -1273,6 +1276,7 @@ static inline void setup_pegasus_II(pegasus_t * pegasus)
}
+static int pegasus_count;
static struct workqueue_struct *pegasus_workqueue = NULL;
#define CARRIER_CHECK_DELAY (2 * HZ)
@@ -1301,6 +1305,18 @@ static int pegasus_blacklisted(struct usb_device *udev)
return 0;
}
+/* we rely on probe() and remove() being serialized so we
+ * don't need extra locking on pegasus_count.
+ */
+static void pegasus_dec_workqueue(void)
+{
+ pegasus_count--;
+ if (pegasus_count == 0) {
+ destroy_workqueue(pegasus_workqueue);
+ pegasus_workqueue = NULL;
+ }
+}
+
static int pegasus_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -1309,14 +1325,18 @@ static int pegasus_probe(struct usb_interface *intf,
pegasus_t *pegasus;
int dev_index = id - pegasus_ids;
int res = -ENOMEM;
- DECLARE_MAC_BUF(mac);
- usb_get_dev(dev);
+ if (pegasus_blacklisted(dev))
+ return -ENODEV;
- if (pegasus_blacklisted(dev)) {
- res = -ENODEV;
- goto out;
+ if (pegasus_count == 0) {
+ pegasus_workqueue = create_singlethread_workqueue("pegasus");
+ if (!pegasus_workqueue)
+ return -ENOMEM;
}
+ pegasus_count++;
+
+ usb_get_dev(dev);
net = alloc_etherdev(sizeof(struct pegasus));
if (!net) {
@@ -1386,10 +1406,10 @@ static int pegasus_probe(struct usb_interface *intf,
queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
CARRIER_CHECK_DELAY);
- dev_info(&intf->dev, "%s, %s, %s\n",
+ dev_info(&intf->dev, "%s, %s, %pM\n",
net->name,
usb_dev_id[dev_index].name,
- print_mac(mac, net->dev_addr));
+ net->dev_addr);
return 0;
out3:
@@ -1401,6 +1421,7 @@ out1:
free_netdev(net);
out:
usb_put_dev(dev);
+ pegasus_dec_workqueue();
return res;
}
@@ -1426,6 +1447,7 @@ static void pegasus_disconnect(struct usb_interface *intf)
pegasus->rx_skb = NULL;
}
free_netdev(pegasus->net);
+ pegasus_dec_workqueue();
}
static int pegasus_suspend (struct usb_interface *intf, pm_message_t message)
@@ -1469,7 +1491,7 @@ static struct usb_driver pegasus_driver = {
.resume = pegasus_resume,
};
-static void parse_id(char *id)
+static void __init parse_id(char *id)
{
unsigned int vendor_id=0, device_id=0, flags=0, i=0;
char *token, *name=NULL;
@@ -1505,15 +1527,11 @@ static int __init pegasus_init(void)
pr_info("%s: %s, " DRIVER_DESC "\n", driver_name, DRIVER_VERSION);
if (devid)
parse_id(devid);
- pegasus_workqueue = create_singlethread_workqueue("pegasus");
- if (!pegasus_workqueue)
- return -ENOMEM;
return usb_register(&pegasus_driver);
}
static void __exit pegasus_exit(void)
{
- destroy_workqueue(pegasus_workqueue);
usb_deregister(&pegasus_driver);
}
diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c
index 6133401ebc67..d8664bf18c00 100644
--- a/drivers/net/usb/rtl8150.c
+++ b/drivers/net/usb/rtl8150.c
@@ -212,8 +212,9 @@ static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
static void ctrl_callback(struct urb *urb)
{
rtl8150_t *dev;
+ int status = urb->status;
- switch (urb->status) {
+ switch (status) {
case 0:
break;
case -EINPROGRESS:
@@ -221,7 +222,7 @@ static void ctrl_callback(struct urb *urb)
case -ENOENT:
break;
default:
- dev_warn(&urb->dev->dev, "ctrl urb status %d\n", urb->status);
+ dev_warn(&urb->dev->dev, "ctrl urb status %d\n", status);
}
dev = urb->context;
clear_bit(RX_REG_SET, &dev->flags);
@@ -424,7 +425,8 @@ static void read_bulk_callback(struct urb *urb)
struct sk_buff *skb;
struct net_device *netdev;
u16 rx_stat;
- int status;
+ int status = urb->status;
+ int result;
dev = urb->context;
if (!dev)
@@ -435,7 +437,7 @@ static void read_bulk_callback(struct urb *urb)
if (!netif_device_present(netdev))
return;
- switch (urb->status) {
+ switch (status) {
case 0:
break;
case -ENOENT:
@@ -444,7 +446,7 @@ static void read_bulk_callback(struct urb *urb)
dev_warn(&urb->dev->dev, "may be reset is needed?..\n");
goto goon;
default:
- dev_warn(&urb->dev->dev, "Rx status %d\n", urb->status);
+ dev_warn(&urb->dev->dev, "Rx status %d\n", status);
goto goon;
}
@@ -474,10 +476,10 @@ static void read_bulk_callback(struct urb *urb)
goon:
usb_fill_bulk_urb(dev->rx_urb, dev->udev, usb_rcvbulkpipe(dev->udev, 1),
dev->rx_skb->data, RTL8150_MTU, read_bulk_callback, dev);
- status = usb_submit_urb(dev->rx_urb, GFP_ATOMIC);
- if (status == -ENODEV)
+ result = usb_submit_urb(dev->rx_urb, GFP_ATOMIC);
+ if (result == -ENODEV)
netif_device_detach(dev->netdev);
- else if (status) {
+ else if (result) {
set_bit(RX_URB_FAIL, &dev->flags);
goto resched;
} else {
@@ -530,6 +532,7 @@ tlsched:
static void write_bulk_callback(struct urb *urb)
{
rtl8150_t *dev;
+ int status = urb->status;
dev = urb->context;
if (!dev)
@@ -537,9 +540,9 @@ static void write_bulk_callback(struct urb *urb)
dev_kfree_skb_irq(dev->tx_skb);
if (!netif_device_present(dev->netdev))
return;
- if (urb->status)
+ if (status)
dev_info(&urb->dev->dev, "%s: Tx status %d\n",
- dev->netdev->name, urb->status);
+ dev->netdev->name, status);
dev->netdev->trans_start = jiffies;
netif_wake_queue(dev->netdev);
}
@@ -548,12 +551,13 @@ static void intr_callback(struct urb *urb)
{
rtl8150_t *dev;
__u8 *d;
- int status;
+ int status = urb->status;
+ int res;
dev = urb->context;
if (!dev)
return;
- switch (urb->status) {
+ switch (status) {
case 0: /* success */
break;
case -ECONNRESET: /* unlink */
@@ -563,7 +567,7 @@ static void intr_callback(struct urb *urb)
/* -EPIPE: should clear the halt */
default:
dev_info(&urb->dev->dev, "%s: intr status %d\n",
- dev->netdev->name, urb->status);
+ dev->netdev->name, status);
goto resubmit;
}
@@ -591,13 +595,13 @@ static void intr_callback(struct urb *urb)
}
resubmit:
- status = usb_submit_urb (urb, GFP_ATOMIC);
- if (status == -ENODEV)
+ res = usb_submit_urb (urb, GFP_ATOMIC);
+ if (res == -ENODEV)
netif_device_detach(dev->netdev);
- else if (status)
+ else if (res)
err ("can't resubmit intr, %s-%s/input0, status %d",
dev->udev->bus->bus_name,
- dev->udev->devpath, status);
+ dev->udev->devpath, res);
}
static int rtl8150_suspend(struct usb_interface *intf, pm_message_t message)
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 51e2f5d7d14e..5574abe29c73 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -31,7 +31,7 @@
#include "smsc95xx.h"
#define SMSC_CHIPNAME "smsc95xx"
-#define SMSC_DRIVER_VERSION "1.0.3"
+#define SMSC_DRIVER_VERSION "1.0.4"
#define HS_USB_PKT_SIZE (512)
#define FS_USB_PKT_SIZE (64)
#define DEFAULT_HS_BURST_CAP_SIZE (16 * 1024 + 5 * HS_USB_PKT_SIZE)
@@ -40,15 +40,16 @@
#define MAX_SINGLE_PACKET_SIZE (2048)
#define LAN95XX_EEPROM_MAGIC (0x9500)
#define EEPROM_MAC_OFFSET (0x01)
+#define DEFAULT_TX_CSUM_ENABLE (true)
#define DEFAULT_RX_CSUM_ENABLE (true)
#define SMSC95XX_INTERNAL_PHY_ID (1)
#define SMSC95XX_TX_OVERHEAD (8)
-#define FLOW_CTRL_TX (1)
-#define FLOW_CTRL_RX (2)
+#define SMSC95XX_TX_OVERHEAD_CSUM (12)
struct smsc95xx_priv {
u32 mac_cr;
spinlock_t mac_cr_lock;
+ bool use_tx_csum;
bool use_rx_csum;
};
@@ -310,9 +311,10 @@ static void smsc95xx_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
{
struct usb_context *usb_context = urb->context;
struct usbnet *dev = usb_context->dev;
+ int status = urb->status;
- if (urb->status < 0)
- devwarn(dev, "async callback failed with %d", urb->status);
+ if (status < 0)
+ devwarn(dev, "async callback failed with %d", status);
complete(&usb_context->notify);
@@ -434,28 +436,6 @@ static void smsc95xx_set_multicast(struct net_device *netdev)
smsc95xx_write_reg_async(dev, MAC_CR, &pdata->mac_cr);
}
-static u8 smsc95xx_resolve_flowctrl_fulldplx(u16 lcladv, u16 rmtadv)
-{
- u8 cap = 0;
-
- if (lcladv & ADVERTISE_PAUSE_CAP) {
- if (lcladv & ADVERTISE_PAUSE_ASYM) {
- if (rmtadv & LPA_PAUSE_CAP)
- cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
- else if (rmtadv & LPA_PAUSE_ASYM)
- cap = FLOW_CTRL_RX;
- } else {
- if (rmtadv & LPA_PAUSE_CAP)
- cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
- }
- } else if (lcladv & ADVERTISE_PAUSE_ASYM) {
- if ((rmtadv & LPA_PAUSE_CAP) && (rmtadv & LPA_PAUSE_ASYM))
- cap = FLOW_CTRL_TX;
- }
-
- return cap;
-}
-
static void smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex,
u16 lcladv, u16 rmtadv)
{
@@ -468,7 +448,7 @@ static void smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex,
}
if (duplex == DUPLEX_FULL) {
- u8 cap = smsc95xx_resolve_flowctrl_fulldplx(lcladv, rmtadv);
+ u8 cap = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
if (cap & FLOW_CTRL_RX)
flow = 0xFFFF0002;
@@ -556,9 +536,10 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
devwarn(dev, "unexpected interrupt, intdata=0x%08X", intdata);
}
-/* Enable or disable Rx checksum offload engine */
-static int smsc95xx_set_rx_csum(struct usbnet *dev, bool enable)
+/* Enable or disable Tx & Rx checksum offload engines */
+static int smsc95xx_set_csums(struct usbnet *dev)
{
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
u32 read_buf;
int ret = smsc95xx_read_reg(dev, COE_CR, &read_buf);
if (ret < 0) {
@@ -566,7 +547,12 @@ static int smsc95xx_set_rx_csum(struct usbnet *dev, bool enable)
return ret;
}
- if (enable)
+ if (pdata->use_tx_csum)
+ read_buf |= Tx_COE_EN_;
+ else
+ read_buf &= ~Tx_COE_EN_;
+
+ if (pdata->use_rx_csum)
read_buf |= Rx_COE_EN_;
else
read_buf &= ~Rx_COE_EN_;
@@ -626,7 +612,26 @@ static int smsc95xx_ethtool_set_rx_csum(struct net_device *netdev, u32 val)
pdata->use_rx_csum = !!val;
- return smsc95xx_set_rx_csum(dev, pdata->use_rx_csum);
+ return smsc95xx_set_csums(dev);
+}
+
+static u32 smsc95xx_ethtool_get_tx_csum(struct net_device *netdev)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+
+ return pdata->use_tx_csum;
+}
+
+static int smsc95xx_ethtool_set_tx_csum(struct net_device *netdev, u32 val)
+{
+ struct usbnet *dev = netdev_priv(netdev);
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+
+ pdata->use_tx_csum = !!val;
+
+ ethtool_op_set_tx_hw_csum(netdev, pdata->use_tx_csum);
+ return smsc95xx_set_csums(dev);
}
static struct ethtool_ops smsc95xx_ethtool_ops = {
@@ -640,6 +645,8 @@ static struct ethtool_ops smsc95xx_ethtool_ops = {
.get_eeprom_len = smsc95xx_ethtool_get_eeprom_len,
.get_eeprom = smsc95xx_ethtool_get_eeprom,
.set_eeprom = smsc95xx_ethtool_set_eeprom,
+ .get_tx_csum = smsc95xx_ethtool_get_tx_csum,
+ .set_tx_csum = smsc95xx_ethtool_set_tx_csum,
.get_rx_csum = smsc95xx_ethtool_get_rx_csum,
.set_rx_csum = smsc95xx_ethtool_set_rx_csum,
};
@@ -757,9 +764,9 @@ static int smsc95xx_phy_initialize(struct usbnet *dev)
static int smsc95xx_reset(struct usbnet *dev)
{
struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ struct net_device *netdev = dev->net;
u32 read_buf, write_buf, burst_cap;
int ret = 0, timeout;
- DECLARE_MAC_BUF(mac);
if (netif_msg_ifup(dev))
devdbg(dev, "entering smsc95xx_reset");
@@ -818,8 +825,7 @@ static int smsc95xx_reset(struct usbnet *dev)
return ret;
if (netif_msg_ifup(dev))
- devdbg(dev, "MAC Address: %s",
- print_mac(mac, dev->net->dev_addr));
+ devdbg(dev, "MAC Address: %pM", dev->net->dev_addr);
ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf);
if (ret < 0) {
@@ -970,10 +976,11 @@ static int smsc95xx_reset(struct usbnet *dev)
return ret;
}
- /* Enable or disable Rx checksum offload engine */
- ret = smsc95xx_set_rx_csum(dev, pdata->use_rx_csum);
+ /* Enable or disable checksum offload engines */
+ ethtool_op_set_tx_hw_csum(netdev, pdata->use_tx_csum);
+ ret = smsc95xx_set_csums(dev);
if (ret < 0) {
- devwarn(dev, "Failed to set Rx csum offload: %d", ret);
+ devwarn(dev, "Failed to set csum offload: %d", ret);
return ret;
}
@@ -1029,6 +1036,7 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)
spin_lock_init(&pdata->mac_cr_lock);
+ pdata->use_tx_csum = DEFAULT_TX_CSUM_ENABLE;
pdata->use_rx_csum = DEFAULT_RX_CSUM_ENABLE;
/* Init all registers */
@@ -1148,22 +1156,44 @@ static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
return 1;
}
+static u32 smsc95xx_calc_csum_preamble(struct sk_buff *skb)
+{
+ int len = skb->data - skb->head;
+ u16 high_16 = (u16)(skb->csum_offset + skb->csum_start - len);
+ u16 low_16 = (u16)(skb->csum_start - len);
+ return (high_16 << 16) | low_16;
+}
+
static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev,
struct sk_buff *skb, gfp_t flags)
{
+ struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
+ bool csum = pdata->use_tx_csum && (skb->ip_summed == CHECKSUM_PARTIAL);
+ int overhead = csum ? SMSC95XX_TX_OVERHEAD_CSUM : SMSC95XX_TX_OVERHEAD;
u32 tx_cmd_a, tx_cmd_b;
- if (skb_headroom(skb) < SMSC95XX_TX_OVERHEAD) {
+ /* We do not advertise SG, so skbs should be already linearized */
+ BUG_ON(skb_shinfo(skb)->nr_frags);
+
+ if (skb_headroom(skb) < overhead) {
struct sk_buff *skb2 = skb_copy_expand(skb,
- SMSC95XX_TX_OVERHEAD, 0, flags);
+ overhead, 0, flags);
dev_kfree_skb_any(skb);
skb = skb2;
if (!skb)
return NULL;
}
+ if (csum) {
+ u32 csum_preamble = smsc95xx_calc_csum_preamble(skb);
+ skb_push(skb, 4);
+ memcpy(skb->data, &csum_preamble, 4);
+ }
+
skb_push(skb, 4);
tx_cmd_b = (u32)(skb->len - 4);
+ if (csum)
+ tx_cmd_b |= TX_CMD_B_CSUM_ENABLE;
cpu_to_le32s(&tx_cmd_b);
memcpy(skb->data, &tx_cmd_b, 4);
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 02d25c743994..aa3149078888 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1125,7 +1125,6 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
struct usb_device *xdev;
int status;
const char *name;
- DECLARE_MAC_BUF(mac);
name = udev->dev.driver->name;
info = (struct driver_info *) prod->driver_info;
@@ -1236,11 +1235,11 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
if (status)
goto out3;
if (netif_msg_probe (dev))
- devinfo (dev, "register '%s' at usb-%s-%s, %s, %s",
+ devinfo (dev, "register '%s' at usb-%s-%s, %s, %pM",
udev->dev.driver->name,
xdev->bus->bus_name, xdev->devpath,
dev->driver_info->description,
- print_mac(mac, net->dev_addr));
+ net->dev_addr);
// ok, it's ready to go.
usb_set_intfdata (udev, dev);
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 31cd817f33f9..852d0e7c4e62 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -8,7 +8,6 @@
*
*/
-#include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/ethtool.h>
#include <linux/etherdevice.h>
@@ -30,14 +29,10 @@ struct veth_net_stats {
struct veth_priv {
struct net_device *peer;
- struct net_device *dev;
- struct list_head list;
struct veth_net_stats *stats;
unsigned ip_summed;
};
-static LIST_HEAD(veth_list);
-
/*
* ethtool interface
*/
@@ -267,16 +262,20 @@ static void veth_dev_free(struct net_device *dev)
free_netdev(dev);
}
+static const struct net_device_ops veth_netdev_ops = {
+ .ndo_init = veth_dev_init,
+ .ndo_open = veth_open,
+ .ndo_start_xmit = veth_xmit,
+ .ndo_get_stats = veth_get_stats,
+};
+
static void veth_setup(struct net_device *dev)
{
ether_setup(dev);
- dev->hard_start_xmit = veth_xmit;
- dev->get_stats = veth_get_stats;
- dev->open = veth_open;
+ dev->netdev_ops = &veth_netdev_ops;
dev->ethtool_ops = &veth_ethtool_ops;
dev->features |= NETIF_F_LLTX;
- dev->init = veth_dev_init;
dev->destructor = veth_dev_free;
}
@@ -302,7 +301,7 @@ static int veth_device_event(struct notifier_block *unused,
{
struct net_device *dev = ptr;
- if (dev->open != veth_open)
+ if (dev->netdev_ops->ndo_open != veth_open)
goto out;
switch (event) {
@@ -420,14 +419,10 @@ static int veth_newlink(struct net_device *dev,
*/
priv = netdev_priv(dev);
- priv->dev = dev;
priv->peer = peer;
- list_add(&priv->list, &veth_list);
priv = netdev_priv(peer);
- priv->dev = peer;
priv->peer = dev;
- INIT_LIST_HEAD(&priv->list);
return 0;
err_register_dev:
@@ -449,13 +444,6 @@ static void veth_dellink(struct net_device *dev)
priv = netdev_priv(dev);
peer = priv->peer;
- if (!list_empty(&priv->list))
- list_del(&priv->list);
-
- priv = netdev_priv(peer);
- if (!list_empty(&priv->list))
- list_del(&priv->list);
-
unregister_netdevice(dev);
unregister_netdevice(peer);
}
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
index 5b7870080c56..ac07cc6e3cb2 100644
--- a/drivers/net/via-rhine.c
+++ b/drivers/net/via-rhine.c
@@ -191,12 +191,13 @@ IIId. Synchronization
The driver runs as two independent, single-threaded flows of control. One
is the send-packet routine, which enforces single-threaded use by the
-dev->priv->lock spinlock. The other thread is the interrupt handler, which
-is single threaded by the hardware and interrupt handling software.
+netdev_priv(dev)->lock spinlock. The other thread is the interrupt handler,
+which is single threaded by the hardware and interrupt handling software.
The send packet thread has partial control over the Tx ring. It locks the
-dev->priv->lock whenever it's queuing a Tx packet. If the next slot in the ring
-is not available it stops the transmit queue by calling netif_stop_queue.
+netdev_priv(dev)->lock whenever it's queuing a Tx packet. If the next slot in
+the ring is not available it stops the transmit queue by
+calling netif_stop_queue.
The interrupt handler has exclusive control over the Rx ring and records stats
from the Tx ring. After reaping the stats, it marks the Tx queue entry as
@@ -588,7 +589,7 @@ static int rhine_napipoll(struct napi_struct *napi, int budget)
work_done = rhine_rx(dev, budget);
if (work_done < budget) {
- netif_rx_complete(dev, napi);
+ netif_rx_complete(napi);
iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow |
IntrRxDropped | IntrRxNoBuf | IntrTxAborted |
@@ -614,6 +615,20 @@ static void __devinit rhine_hw_init(struct net_device *dev, long pioaddr)
rhine_reload_eeprom(pioaddr, dev);
}
+static const struct net_device_ops rhine_netdev_ops = {
+ .ndo_open = rhine_open,
+ .ndo_stop = rhine_close,
+ .ndo_start_xmit = rhine_start_tx,
+ .ndo_get_stats = rhine_get_stats,
+ .ndo_set_multicast_list = rhine_set_rx_mode,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_do_ioctl = netdev_ioctl,
+ .ndo_tx_timeout = rhine_tx_timeout,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = rhine_poll,
+#endif
+};
+
static int __devinit rhine_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -631,7 +646,6 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
#else
int bar = 0;
#endif
- DECLARE_MAC_BUF(mac);
/* when built into the kernel, we only print version if device is found */
#ifndef MODULE
@@ -765,18 +779,10 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
rp->mii_if.reg_num_mask = 0x1f;
/* The chip-specific entries in the device structure. */
- dev->open = rhine_open;
- dev->hard_start_xmit = rhine_start_tx;
- dev->stop = rhine_close;
- dev->get_stats = rhine_get_stats;
- dev->set_multicast_list = rhine_set_rx_mode;
- dev->do_ioctl = netdev_ioctl;
- dev->ethtool_ops = &netdev_ethtool_ops;
- dev->tx_timeout = rhine_tx_timeout;
+ dev->netdev_ops = &rhine_netdev_ops;
+ dev->ethtool_ops = &netdev_ethtool_ops,
dev->watchdog_timeo = TX_TIMEOUT;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = rhine_poll;
-#endif
+
netif_napi_add(dev, &rp->napi, rhine_napipoll, 64);
if (rp->quirks & rqRhineI)
@@ -787,14 +793,14 @@ static int __devinit rhine_init_one(struct pci_dev *pdev,
if (rc)
goto err_out_unmap;
- printk(KERN_INFO "%s: VIA %s at 0x%lx, %s, IRQ %d.\n",
+ printk(KERN_INFO "%s: VIA %s at 0x%lx, %pM, IRQ %d.\n",
dev->name, name,
#ifdef USE_MMIO
memaddr,
#else
(long)ioaddr,
#endif
- print_mac(mac, dev->dev_addr), pdev->irq);
+ dev->dev_addr, pdev->irq);
pci_set_drvdata(pdev, dev);
@@ -1312,7 +1318,7 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance)
IntrPCIErr | IntrStatsMax | IntrLinkChange,
ioaddr + IntrEnable);
- netif_rx_schedule(dev, &rp->napi);
+ netif_rx_schedule(&rp->napi);
}
if (intr_status & (IntrTxErrSummary | IntrTxDone)) {
@@ -1505,7 +1511,6 @@ static int rhine_rx(struct net_device *dev, int limit)
}
skb->protocol = eth_type_trans(skb, dev);
netif_receive_skb(skb);
- dev->last_rx = jiffies;
rp->stats.rx_bytes += pkt_len;
rp->stats.rx_packets++;
}
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
index 11cb3e504e1c..58e25d090ae0 100644
--- a/drivers/net/via-velocity.c
+++ b/drivers/net/via-velocity.c
@@ -849,6 +849,20 @@ static int velocity_soft_reset(struct velocity_info *vptr)
return 0;
}
+static const struct net_device_ops velocity_netdev_ops = {
+ .ndo_open = velocity_open,
+ .ndo_stop = velocity_close,
+ .ndo_start_xmit = velocity_xmit,
+ .ndo_get_stats = velocity_get_stats,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_multicast_list = velocity_set_multi,
+ .ndo_change_mtu = velocity_change_mtu,
+ .ndo_do_ioctl = velocity_ioctl,
+ .ndo_vlan_rx_add_vid = velocity_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = velocity_vlan_rx_kill_vid,
+ .ndo_vlan_rx_register = velocity_vlan_rx_register,
+};
+
/**
* velocity_found1 - set up discovered velocity card
* @pdev: PCI device
@@ -958,18 +972,8 @@ 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->open = velocity_open;
- dev->hard_start_xmit = velocity_xmit;
- dev->stop = velocity_close;
- dev->get_stats = velocity_get_stats;
- dev->set_multicast_list = velocity_set_multi;
- dev->do_ioctl = velocity_ioctl;
+ dev->netdev_ops = &velocity_netdev_ops;
dev->ethtool_ops = &velocity_ethtool_ops;
- dev->change_mtu = velocity_change_mtu;
-
- dev->vlan_rx_add_vid = velocity_vlan_rx_add_vid;
- dev->vlan_rx_kill_vid = velocity_vlan_rx_kill_vid;
- dev->vlan_rx_register = velocity_vlan_rx_register;
#ifdef VELOCITY_ZERO_COPY_SUPPORT
dev->features |= NETIF_F_SG;
@@ -1412,8 +1416,6 @@ static int velocity_rx_srv(struct velocity_info *vptr, int status)
rd->size |= RX_INTEN;
- vptr->dev->last_rx = jiffies;
-
rd_curr++;
if (rd_curr >= vptr->options.numrx)
rd_curr = 0;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 0196a0df9021..b7004ff36451 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -34,6 +34,7 @@ module_param(gso, bool, 0444);
/* FIXME: MTU in config. */
#define MAX_PACKET_LEN (ETH_HLEN+ETH_DATA_LEN)
+#define GOOD_COPY_LEN 128
struct virtnet_info
{
@@ -58,6 +59,9 @@ struct virtnet_info
/* I like... big packets and I cannot lie! */
bool big_packets;
+ /* Host will merge rx buffers for big packets (shake it! shake it!) */
+ bool mergeable_rx_bufs;
+
/* Receive & send queues. */
struct sk_buff_head recv;
struct sk_buff_head send;
@@ -66,22 +70,27 @@ struct virtnet_info
struct page *pages;
};
-static inline struct virtio_net_hdr *skb_vnet_hdr(struct sk_buff *skb)
+static inline void *skb_vnet_hdr(struct sk_buff *skb)
{
return (struct virtio_net_hdr *)skb->cb;
}
-static inline void vnet_hdr_to_sg(struct scatterlist *sg, struct sk_buff *skb)
-{
- sg_init_one(sg, skb_vnet_hdr(skb), sizeof(struct virtio_net_hdr));
-}
-
static void give_a_page(struct virtnet_info *vi, struct page *page)
{
page->private = (unsigned long)vi->pages;
vi->pages = page;
}
+static void trim_pages(struct virtnet_info *vi, struct sk_buff *skb)
+{
+ unsigned int i;
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
+ give_a_page(vi, skb_shinfo(skb)->frags[i].page);
+ skb_shinfo(skb)->nr_frags = 0;
+ skb->data_len = 0;
+}
+
static struct page *get_a_page(struct virtnet_info *vi, gfp_t gfp_mask)
{
struct page *p = vi->pages;
@@ -111,31 +120,97 @@ static void skb_xmit_done(struct virtqueue *svq)
static void receive_skb(struct net_device *dev, struct sk_buff *skb,
unsigned len)
{
+ struct virtnet_info *vi = netdev_priv(dev);
struct virtio_net_hdr *hdr = skb_vnet_hdr(skb);
int err;
+ int i;
if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) {
pr_debug("%s: short packet %i\n", dev->name, len);
dev->stats.rx_length_errors++;
goto drop;
}
- len -= sizeof(struct virtio_net_hdr);
- if (len <= MAX_PACKET_LEN) {
- unsigned int i;
+ if (vi->mergeable_rx_bufs) {
+ struct virtio_net_hdr_mrg_rxbuf *mhdr = skb_vnet_hdr(skb);
+ unsigned int copy;
+ char *p = page_address(skb_shinfo(skb)->frags[0].page);
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
- give_a_page(dev->priv, skb_shinfo(skb)->frags[i].page);
- skb->data_len = 0;
- skb_shinfo(skb)->nr_frags = 0;
- }
+ if (len > PAGE_SIZE)
+ len = PAGE_SIZE;
+ len -= sizeof(struct virtio_net_hdr_mrg_rxbuf);
- err = pskb_trim(skb, len);
- if (err) {
- pr_debug("%s: pskb_trim failed %i %d\n", dev->name, len, err);
- dev->stats.rx_dropped++;
- goto drop;
+ memcpy(hdr, p, sizeof(*mhdr));
+ p += sizeof(*mhdr);
+
+ copy = len;
+ if (copy > skb_tailroom(skb))
+ copy = skb_tailroom(skb);
+
+ memcpy(skb_put(skb, copy), p, copy);
+
+ len -= copy;
+
+ if (!len) {
+ give_a_page(vi, skb_shinfo(skb)->frags[0].page);
+ skb_shinfo(skb)->nr_frags--;
+ } else {
+ skb_shinfo(skb)->frags[0].page_offset +=
+ sizeof(*mhdr) + copy;
+ skb_shinfo(skb)->frags[0].size = len;
+ skb->data_len += len;
+ skb->len += len;
+ }
+
+ while (--mhdr->num_buffers) {
+ struct sk_buff *nskb;
+
+ i = skb_shinfo(skb)->nr_frags;
+ if (i >= MAX_SKB_FRAGS) {
+ pr_debug("%s: packet too long %d\n", dev->name,
+ len);
+ dev->stats.rx_length_errors++;
+ goto drop;
+ }
+
+ nskb = vi->rvq->vq_ops->get_buf(vi->rvq, &len);
+ if (!nskb) {
+ pr_debug("%s: rx error: %d buffers missing\n",
+ dev->name, mhdr->num_buffers);
+ dev->stats.rx_length_errors++;
+ goto drop;
+ }
+
+ __skb_unlink(nskb, &vi->recv);
+ vi->num--;
+
+ skb_shinfo(skb)->frags[i] = skb_shinfo(nskb)->frags[0];
+ skb_shinfo(nskb)->nr_frags = 0;
+ kfree_skb(nskb);
+
+ if (len > PAGE_SIZE)
+ len = PAGE_SIZE;
+
+ skb_shinfo(skb)->frags[i].size = len;
+ skb_shinfo(skb)->nr_frags++;
+ skb->data_len += len;
+ skb->len += len;
+ }
+ } else {
+ len -= sizeof(struct virtio_net_hdr);
+
+ if (len <= MAX_PACKET_LEN)
+ trim_pages(vi, skb);
+
+ err = pskb_trim(skb, len);
+ if (err) {
+ pr_debug("%s: pskb_trim failed %i %d\n", dev->name,
+ len, err);
+ dev->stats.rx_dropped++;
+ goto drop;
+ }
}
+
skb->truesize += skb->data_len;
dev->stats.rx_bytes += skb->len;
dev->stats.rx_packets++;
@@ -194,7 +269,7 @@ drop:
dev_kfree_skb(skb);
}
-static void try_fill_recv(struct virtnet_info *vi)
+static void try_fill_recv_maxbufs(struct virtnet_info *vi)
{
struct sk_buff *skb;
struct scatterlist sg[2+MAX_SKB_FRAGS];
@@ -202,12 +277,16 @@ static void try_fill_recv(struct virtnet_info *vi)
sg_init_table(sg, 2+MAX_SKB_FRAGS);
for (;;) {
+ struct virtio_net_hdr *hdr;
+
skb = netdev_alloc_skb(vi->dev, MAX_PACKET_LEN);
if (unlikely(!skb))
break;
skb_put(skb, MAX_PACKET_LEN);
- vnet_hdr_to_sg(sg, skb);
+
+ hdr = skb_vnet_hdr(skb);
+ sg_init_one(sg, hdr, sizeof(*hdr));
if (vi->big_packets) {
for (i = 0; i < MAX_SKB_FRAGS; i++) {
@@ -232,6 +311,55 @@ static void try_fill_recv(struct virtnet_info *vi)
err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, num, skb);
if (err) {
skb_unlink(skb, &vi->recv);
+ trim_pages(vi, skb);
+ kfree_skb(skb);
+ break;
+ }
+ vi->num++;
+ }
+ if (unlikely(vi->num > vi->max))
+ vi->max = vi->num;
+ vi->rvq->vq_ops->kick(vi->rvq);
+}
+
+static void try_fill_recv(struct virtnet_info *vi)
+{
+ struct sk_buff *skb;
+ struct scatterlist sg[1];
+ int err;
+
+ if (!vi->mergeable_rx_bufs) {
+ try_fill_recv_maxbufs(vi);
+ return;
+ }
+
+ for (;;) {
+ skb_frag_t *f;
+
+ skb = netdev_alloc_skb(vi->dev, GOOD_COPY_LEN + NET_IP_ALIGN);
+ if (unlikely(!skb))
+ break;
+
+ skb_reserve(skb, NET_IP_ALIGN);
+
+ f = &skb_shinfo(skb)->frags[0];
+ f->page = get_a_page(vi, GFP_ATOMIC);
+ if (!f->page) {
+ kfree_skb(skb);
+ break;
+ }
+
+ f->page_offset = 0;
+ f->size = PAGE_SIZE;
+
+ skb_shinfo(skb)->nr_frags++;
+
+ sg_init_one(sg, page_address(f->page), PAGE_SIZE);
+ skb_queue_head(&vi->recv, skb);
+
+ err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, 1, skb);
+ if (err) {
+ skb_unlink(skb, &vi->recv);
kfree_skb(skb);
break;
}
@@ -246,9 +374,9 @@ static void skb_recv_done(struct virtqueue *rvq)
{
struct virtnet_info *vi = rvq->vdev->priv;
/* Schedule NAPI, Suppress further interrupts if successful. */
- if (netif_rx_schedule_prep(vi->dev, &vi->napi)) {
+ if (netif_rx_schedule_prep(&vi->napi)) {
rvq->vq_ops->disable_cb(rvq);
- __netif_rx_schedule(vi->dev, &vi->napi);
+ __netif_rx_schedule(&vi->napi);
}
}
@@ -274,11 +402,11 @@ again:
/* Out of packets? */
if (received < budget) {
- netif_rx_complete(vi->dev, napi);
+ netif_rx_complete(napi);
if (unlikely(!vi->rvq->vq_ops->enable_cb(vi->rvq))
&& napi_schedule_prep(napi)) {
vi->rvq->vq_ops->disable_cb(vi->rvq);
- __netif_rx_schedule(vi->dev, napi);
+ __netif_rx_schedule(napi);
goto again;
}
}
@@ -320,17 +448,14 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
{
int num, err;
struct scatterlist sg[2+MAX_SKB_FRAGS];
- struct virtio_net_hdr *hdr;
+ struct virtio_net_hdr_mrg_rxbuf *mhdr = skb_vnet_hdr(skb);
+ struct virtio_net_hdr *hdr = skb_vnet_hdr(skb);
const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest;
sg_init_table(sg, 2+MAX_SKB_FRAGS);
- pr_debug("%s: xmit %p " MAC_FMT "\n", vi->dev->name, skb,
- dest[0], dest[1], dest[2],
- dest[3], dest[4], dest[5]);
+ pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest);
- /* Encode metadata header at front. */
- hdr = skb_vnet_hdr(skb);
if (skb->ip_summed == CHECKSUM_PARTIAL) {
hdr->flags = VIRTIO_NET_HDR_F_NEEDS_CSUM;
hdr->csum_start = skb->csum_start - skb_headroom(skb);
@@ -358,7 +483,14 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb)
hdr->gso_size = hdr->hdr_len = 0;
}
- vnet_hdr_to_sg(sg, skb);
+ mhdr->num_buffers = 0;
+
+ /* Encode metadata header at front. */
+ if (vi->mergeable_rx_bufs)
+ sg_init_one(sg, mhdr, sizeof(*mhdr));
+ else
+ sg_init_one(sg, hdr, sizeof(*hdr));
+
num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1;
err = vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb);
@@ -448,9 +580,9 @@ static int virtnet_open(struct net_device *dev)
* won't get another interrupt, so process any outstanding packets
* now. virtnet_poll wants re-enable the queue, so we disable here.
* We synchronize against interrupts via NAPI_STATE_SCHED */
- if (netif_rx_schedule_prep(dev, &vi->napi)) {
+ if (netif_rx_schedule_prep(&vi->napi)) {
vi->rvq->vq_ops->disable_cb(vi->rvq);
- __netif_rx_schedule(dev, &vi->napi);
+ __netif_rx_schedule(&vi->napi);
}
return 0;
}
@@ -478,8 +610,20 @@ static int virtnet_set_tx_csum(struct net_device *dev, u32 data)
static struct ethtool_ops virtnet_ethtool_ops = {
.set_tx_csum = virtnet_set_tx_csum,
.set_sg = ethtool_op_set_sg,
+ .set_tso = ethtool_op_set_tso,
};
+#define MIN_MTU 68
+#define MAX_MTU 65535
+
+static int virtnet_change_mtu(struct net_device *dev, int new_mtu)
+{
+ if (new_mtu < MIN_MTU || new_mtu > MAX_MTU)
+ return -EINVAL;
+ dev->mtu = new_mtu;
+ return 0;
+}
+
static int virtnet_probe(struct virtio_device *vdev)
{
int err;
@@ -495,6 +639,7 @@ static int virtnet_probe(struct virtio_device *vdev)
dev->open = virtnet_open;
dev->stop = virtnet_close;
dev->hard_start_xmit = start_xmit;
+ dev->change_mtu = virtnet_change_mtu;
dev->features = NETIF_F_HIGHDMA;
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = virtnet_netpoll;
@@ -547,6 +692,9 @@ static int virtnet_probe(struct virtio_device *vdev)
|| virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN))
vi->big_packets = true;
+ if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF))
+ vi->mergeable_rx_bufs = true;
+
/* We expect two virtqueues, receive then send. */
vi->rvq = vdev->config->find_vq(vdev, 0, skb_recv_done);
if (IS_ERR(vi->rvq)) {
@@ -639,6 +787,7 @@ static unsigned int features[] = {
VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6,
VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
VIRTIO_NET_F_GUEST_ECN, /* We don't yet handle UFO input. */
+ VIRTIO_NET_F_MRG_RXBUF,
VIRTIO_F_NOTIFY_ON_EMPTY,
};
diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
index 21efd99b9294..d08ce6a264cb 100644
--- a/drivers/net/wan/Kconfig
+++ b/drivers/net/wan/Kconfig
@@ -207,6 +207,8 @@ config PC300
tristate "Cyclades-PC300 support (RS-232/V.35, X.21, T1/E1 boards)"
depends on HDLC && PCI && BROKEN
---help---
+ This driver is broken because of struct tty_driver change.
+
Driver for the Cyclades-PC300 synchronous communication boards.
These boards provide synchronous serial interfaces to your
@@ -333,6 +335,13 @@ config DSCC4_PCI_RST
Say Y if your card supports this feature.
+config IXP4XX_HSS
+ tristate "Intel IXP4xx HSS (synchronous serial port) support"
+ depends on HDLC && ARM && ARCH_IXP4XX && IXP4XX_NPE && IXP4XX_QMGR
+ help
+ Say Y here if you want to use built-in HSS ports
+ on IXP4xx processor.
+
config DLCI
tristate "Frame Relay DLCI support"
---help---
diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile
index 102549605d09..19d14bc28356 100644
--- a/drivers/net/wan/Makefile
+++ b/drivers/net/wan/Makefile
@@ -14,7 +14,7 @@ obj-$(CONFIG_HDLC_RAW) += hdlc_raw.o
obj-$(CONFIG_HDLC_RAW_ETH) += hdlc_raw_eth.o
obj-$(CONFIG_HDLC_CISCO) += hdlc_cisco.o
obj-$(CONFIG_HDLC_FR) += hdlc_fr.o
-obj-$(CONFIG_HDLC_PPP) += hdlc_ppp.o syncppp.o
+obj-$(CONFIG_HDLC_PPP) += hdlc_ppp.o
obj-$(CONFIG_HDLC_X25) += hdlc_x25.o
pc300-y := pc300_drv.o
@@ -41,6 +41,7 @@ obj-$(CONFIG_C101) += c101.o
obj-$(CONFIG_WANXL) += wanxl.o
obj-$(CONFIG_PCI200SYN) += pci200syn.o
obj-$(CONFIG_PC300TOO) += pc300too.o
+obj-$(CONFIG_IXP4XX_HSS) += ixp4xx_hss.o
clean-files := wanxlfw.inc
$(obj)/wanxl.o: $(obj)/wanxlfw.inc
diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c
index c8e563106a4a..b46897996f7e 100644
--- a/drivers/net/wan/c101.c
+++ b/drivers/net/wan/c101.c
@@ -88,7 +88,7 @@ static card_t **new_card = &first_card;
/* EDA address register must be set in EDAL, EDAH order - 8 bit ISA bus */
#define sca_outw(value, reg, card) do { \
writeb(value & 0xFF, (card)->win0base + C101_SCA + (reg)); \
- writeb((value >> 8 ) & 0xFF, (card)->win0base + C101_SCA + (reg+1));\
+ writeb((value >> 8 ) & 0xFF, (card)->win0base + C101_SCA + (reg + 1));\
} while(0)
#define port_to_card(port) (port)
@@ -113,7 +113,7 @@ static inline void openwin(card_t *card, u8 page)
}
-#include "hd6457x.c"
+#include "hd64570.c"
static inline void set_carrier(port_t *port)
@@ -381,7 +381,7 @@ static int __init c101_run(unsigned long irq, unsigned long winbase)
return result;
}
- sca_init_sync_port(card); /* Set up C101 memory */
+ sca_init_port(card); /* Set up C101 memory */
set_carrier(card);
printk(KERN_INFO "%s: Moxa C101 on IRQ%u,"
diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
index 7f97f8d08c39..d80b72e22dea 100644
--- a/drivers/net/wan/cosa.c
+++ b/drivers/net/wan/cosa.c
@@ -754,7 +754,6 @@ static int cosa_net_rx_done(struct channel_data *chan)
chan->netdev->stats.rx_bytes += chan->cosa->rxsize;
netif_rx(chan->rx_skb);
chan->rx_skb = NULL;
- chan->netdev->last_rx = jiffies;
return 0;
}
diff --git a/drivers/net/wan/cycx_x25.c b/drivers/net/wan/cycx_x25.c
index 5a7303dc0965..5fa52923efa8 100644
--- a/drivers/net/wan/cycx_x25.c
+++ b/drivers/net/wan/cycx_x25.c
@@ -199,6 +199,8 @@ static struct net_device *cycx_x25_get_dev_by_lcn(struct wan_device *wandev,
static struct net_device *
cycx_x25_get_dev_by_dte_addr(struct wan_device *wandev, char *dte);
+static void cycx_x25_chan_setup(struct net_device *dev);
+
#ifdef CYCLOMX_X25_DEBUG
static void hex_dump(char *msg, unsigned char *p, int len);
static void cycx_x25_dump_config(struct cycx_x25_config *conf);
@@ -353,6 +355,12 @@ static int cycx_wan_update(struct wan_device *wandev)
return 0;
}
+/* callback to initialize device */
+static void cycx_x25_chan_setup(struct net_device *dev)
+{
+ dev->init = cycx_netdevice_init;
+}
+
/* Create new logical channel.
* This routine is called by the router when ROUTER_IFNEW IOCTL is being
* handled.
@@ -376,11 +384,12 @@ static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
return -EINVAL;
}
- /* allocate and initialize private data */
- chan = kzalloc(sizeof(struct cycx_x25_channel), GFP_KERNEL);
- if (!chan)
+ dev = alloc_netdev(sizeof(struct cycx_x25_channel), conf->name,
+ cycx_x25_chan_setup);
+ if (!dev)
return -ENOMEM;
+ chan = netdev_priv(dev);
strcpy(chan->name, conf->name);
chan->card = card;
chan->link = conf->port;
@@ -396,14 +405,14 @@ static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
if (len > WAN_ADDRESS_SZ) {
printk(KERN_ERR "%s: %s local addr too long!\n",
wandev->name, chan->name);
- kfree(chan);
- return -EINVAL;
+ err = -EINVAL;
+ goto error;
} else {
chan->local_addr = kmalloc(len + 1, GFP_KERNEL);
if (!chan->local_addr) {
- kfree(chan);
- return -ENOMEM;
+ err = -ENOMEM;
+ goto error;
}
}
@@ -429,41 +438,31 @@ static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
"%s: PVC %u is out of range on interface %s!\n",
wandev->name, lcn, chan->name);
err = -EINVAL;
+ goto error;
}
} else {
printk(KERN_ERR "%s: invalid media address on interface %s!\n",
wandev->name, chan->name);
err = -EINVAL;
+ goto error;
}
- if (err) {
- kfree(chan->local_addr);
- kfree(chan);
- return err;
- }
-
- /* prepare network device data space for registration */
- strcpy(dev->name, chan->name);
- dev->init = cycx_netdevice_init;
- dev->priv = chan;
-
return 0;
+
+error:
+ free_netdev(dev);
+ return err;
}
/* Delete logical channel. */
static int cycx_wan_del_if(struct wan_device *wandev, struct net_device *dev)
{
- if (dev->priv) {
- struct cycx_x25_channel *chan = dev->priv;
+ struct cycx_x25_channel *chan = netdev_priv(dev);
- if (chan->svc) {
- kfree(chan->local_addr);
- if (chan->state == WAN_CONNECTED)
- del_timer(&chan->timer);
- }
-
- kfree(chan);
- dev->priv = NULL;
+ if (chan->svc) {
+ kfree(chan->local_addr);
+ if (chan->state == WAN_CONNECTED)
+ del_timer(&chan->timer);
}
return 0;
@@ -484,7 +483,7 @@ static const struct header_ops cycx_header_ops = {
* registration. */
static int cycx_netdevice_init(struct net_device *dev)
{
- struct cycx_x25_channel *chan = dev->priv;
+ struct cycx_x25_channel *chan = netdev_priv(dev);
struct cycx_device *card = chan->card;
struct wan_device *wandev = &card->wandev;
@@ -542,7 +541,7 @@ static int cycx_netdevice_open(struct net_device *dev)
* o if there's no more open channels then disconnect physical link. */
static int cycx_netdevice_stop(struct net_device *dev)
{
- struct cycx_x25_channel *chan = dev->priv;
+ struct cycx_x25_channel *chan = netdev_priv(dev);
netif_stop_queue(dev);
@@ -596,7 +595,7 @@ static int cycx_netdevice_rebuild_header(struct sk_buff *skb)
static int cycx_netdevice_hard_start_xmit(struct sk_buff *skb,
struct net_device *dev)
{
- struct cycx_x25_channel *chan = dev->priv;
+ struct cycx_x25_channel *chan = netdev_priv(dev);
struct cycx_device *card = chan->card;
if (!chan->svc)
@@ -670,7 +669,7 @@ free_packet:
* Return a pointer to struct net_device_stats */
static struct net_device_stats *cycx_netdevice_get_stats(struct net_device *dev)
{
- struct cycx_x25_channel *chan = dev->priv;
+ struct cycx_x25_channel *chan = netdev_priv(dev);
return chan ? &chan->ifstats : NULL;
}
@@ -783,7 +782,7 @@ static void cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
return;
}
- chan = dev->priv;
+ chan = netdev_priv(dev);
reset_timer(dev);
if (chan->drop_sequence) {
@@ -843,7 +842,6 @@ static void cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
skb_reset_mac_header(skb);
netif_rx(skb);
- dev->last_rx = jiffies; /* timestamp */
}
/* Connect interrupt handler. */
@@ -884,7 +882,7 @@ static void cycx_x25_irq_connect(struct cycx_device *card,
return;
}
- chan = dev->priv;
+ chan = netdev_priv(dev);
chan->lcn = lcn;
cycx_x25_connect_response(card, chan);
cycx_x25_set_chan_state(dev, WAN_CONNECTED);
@@ -914,7 +912,7 @@ static void cycx_x25_irq_connect_confirm(struct cycx_device *card,
}
clear_bit(--key, (void*)&card->u.x.connection_keys);
- chan = dev->priv;
+ chan = netdev_priv(dev);
chan->lcn = lcn;
cycx_x25_set_chan_state(dev, WAN_CONNECTED);
}
@@ -954,7 +952,7 @@ static void cycx_x25_irq_disconnect(struct cycx_device *card,
dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
if (dev) {
- struct cycx_x25_channel *chan = dev->priv;
+ struct cycx_x25_channel *chan = netdev_priv(dev);
cycx_x25_disconnect_response(card, chan->link, lcn);
cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
@@ -1302,7 +1300,7 @@ static struct net_device *cycx_x25_get_dev_by_lcn(struct wan_device *wandev,
struct cycx_x25_channel *chan;
while (dev) {
- chan = (struct cycx_x25_channel*)dev->priv;
+ chan = netdev_priv(dev);
if (chan->lcn == lcn)
break;
@@ -1319,7 +1317,7 @@ static struct net_device *
struct cycx_x25_channel *chan;
while (dev) {
- chan = (struct cycx_x25_channel*)dev->priv;
+ chan = netdev_priv(dev);
if (!strcmp(chan->addr, dte))
break;
@@ -1337,7 +1335,7 @@ static struct net_device *
* <0 failure */
static int cycx_x25_chan_connect(struct net_device *dev)
{
- struct cycx_x25_channel *chan = dev->priv;
+ struct cycx_x25_channel *chan = netdev_priv(dev);
struct cycx_device *card = chan->card;
if (chan->svc) {
@@ -1362,7 +1360,7 @@ static int cycx_x25_chan_connect(struct net_device *dev)
* o if SVC then clear X.25 call */
static void cycx_x25_chan_disconnect(struct net_device *dev)
{
- struct cycx_x25_channel *chan = dev->priv;
+ struct cycx_x25_channel *chan = netdev_priv(dev);
if (chan->svc) {
x25_clear_call(chan->card, chan->link, chan->lcn, 0, 0);
@@ -1375,7 +1373,7 @@ static void cycx_x25_chan_disconnect(struct net_device *dev)
static void cycx_x25_chan_timer(unsigned long d)
{
struct net_device *dev = (struct net_device *)d;
- struct cycx_x25_channel *chan = dev->priv;
+ struct cycx_x25_channel *chan = netdev_priv(dev);
if (chan->state == WAN_CONNECTED)
cycx_x25_chan_disconnect(dev);
@@ -1387,7 +1385,7 @@ static void cycx_x25_chan_timer(unsigned long d)
/* Set logical channel state. */
static void cycx_x25_set_chan_state(struct net_device *dev, u8 state)
{
- struct cycx_x25_channel *chan = dev->priv;
+ struct cycx_x25_channel *chan = netdev_priv(dev);
struct cycx_device *card = chan->card;
unsigned long flags;
char *string_state = NULL;
@@ -1453,7 +1451,7 @@ static void cycx_x25_set_chan_state(struct net_device *dev, u8 state)
* to the router. */
static int cycx_x25_chan_send(struct net_device *dev, struct sk_buff *skb)
{
- struct cycx_x25_channel *chan = dev->priv;
+ struct cycx_x25_channel *chan = netdev_priv(dev);
struct cycx_device *card = chan->card;
int bitm = 0; /* final packet */
unsigned len = skb->len;
@@ -1494,7 +1492,6 @@ static void cycx_x25_chan_send_event(struct net_device *dev, u8 event)
skb->protocol = x25_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies; /* timestamp */
}
/* Convert line speed in bps to a number used by cyclom 2x code. */
@@ -1547,7 +1544,7 @@ static unsigned dec_to_uint(u8 *str, int len)
static void reset_timer(struct net_device *dev)
{
- struct cycx_x25_channel *chan = dev->priv;
+ struct cycx_x25_channel *chan = netdev_priv(dev);
if (chan->svc)
mod_timer(&chan->timer, jiffies+chan->idle_tmout*HZ);
@@ -1600,7 +1597,7 @@ static void cycx_x25_dump_devs(struct wan_device *wandev)
printk(KERN_INFO "---------------------------------------\n");
while(dev) {
- struct cycx_x25_channel *chan = dev->priv;
+ struct cycx_x25_channel *chan = netdev_priv(dev);
printk(KERN_INFO "%-5.5s %-15.15s %d ETH_P_%s\n",
chan->name, chan->addr, netif_queue_stopped(dev),
diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c
index b14242768fad..a297e3efa05d 100644
--- a/drivers/net/wan/dlci.c
+++ b/drivers/net/wan/dlci.c
@@ -74,7 +74,7 @@ static int dlci_header(struct sk_buff *skb, struct net_device *dev,
unsigned int hlen;
char *dest;
- dlp = dev->priv;
+ dlp = netdev_priv(dev);
hdr.control = FRAD_I_UI;
switch(type)
@@ -110,7 +110,7 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
struct frhdr *hdr;
int process, header;
- dlp = dev->priv;
+ dlp = netdev_priv(dev);
if (!pskb_may_pull(skb, sizeof(*hdr))) {
printk(KERN_NOTICE "%s: invalid data no header\n",
dev->name);
@@ -181,7 +181,6 @@ static void dlci_receive(struct sk_buff *skb, struct net_device *dev)
dlp->stats.rx_bytes += skb->len;
netif_rx(skb);
dlp->stats.rx_packets++;
- dev->last_rx = jiffies;
}
else
dev_kfree_skb(skb);
@@ -197,7 +196,7 @@ static int dlci_transmit(struct sk_buff *skb, struct net_device *dev)
if (!skb || !dev)
return(0);
- dlp = dev->priv;
+ dlp = netdev_priv(dev);
netif_stop_queue(dev);
@@ -235,9 +234,9 @@ static int dlci_config(struct net_device *dev, struct dlci_conf __user *conf, in
struct frad_local *flp;
int err;
- dlp = dev->priv;
+ dlp = netdev_priv(dev);
- flp = dlp->slave->priv;
+ flp = netdev_priv(dlp->slave);
if (!get)
{
@@ -269,7 +268,7 @@ static int dlci_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if (!capable(CAP_NET_ADMIN))
return(-EPERM);
- dlp = dev->priv;
+ dlp = netdev_priv(dev);
switch(cmd)
{
@@ -298,7 +297,7 @@ static int dlci_change_mtu(struct net_device *dev, int new_mtu)
{
struct dlci_local *dlp;
- dlp = dev->priv;
+ dlp = netdev_priv(dev);
return((*dlp->slave->change_mtu)(dlp->slave, new_mtu));
}
@@ -309,7 +308,7 @@ static int dlci_open(struct net_device *dev)
struct frad_local *flp;
int err;
- dlp = dev->priv;
+ dlp = netdev_priv(dev);
if (!*(short *)(dev->dev_addr))
return(-EINVAL);
@@ -317,7 +316,7 @@ static int dlci_open(struct net_device *dev)
if (!netif_running(dlp->slave))
return(-ENOTCONN);
- flp = dlp->slave->priv;
+ flp = netdev_priv(dlp->slave);
err = (*flp->activate)(dlp->slave, dev);
if (err)
return(err);
@@ -335,9 +334,9 @@ static int dlci_close(struct net_device *dev)
netif_stop_queue(dev);
- dlp = dev->priv;
+ dlp = netdev_priv(dev);
- flp = dlp->slave->priv;
+ flp = netdev_priv(dlp->slave);
err = (*flp->deactivate)(dlp->slave, dev);
return 0;
@@ -347,7 +346,7 @@ static struct net_device_stats *dlci_get_stats(struct net_device *dev)
{
struct dlci_local *dlp;
- dlp = dev->priv;
+ dlp = netdev_priv(dev);
return(&dlp->stats);
}
@@ -365,7 +364,7 @@ static int dlci_add(struct dlci_add *dlci)
if (!slave)
return -ENODEV;
- if (slave->type != ARPHRD_FRAD || slave->priv == NULL)
+ if (slave->type != ARPHRD_FRAD || netdev_priv(slave) == NULL)
goto err1;
/* create device name */
@@ -391,11 +390,11 @@ static int dlci_add(struct dlci_add *dlci)
*(short *)(master->dev_addr) = dlci->dlci;
- dlp = (struct dlci_local *) master->priv;
+ dlp = netdev_priv(master);
dlp->slave = slave;
dlp->master = master;
- flp = slave->priv;
+ flp = netdev_priv(slave);
err = (*flp->assoc)(slave, master);
if (err < 0)
goto err2;
@@ -435,9 +434,9 @@ static int dlci_del(struct dlci_add *dlci)
return(-EBUSY);
}
- dlp = master->priv;
+ dlp = netdev_priv(master);
slave = dlp->slave;
- flp = slave->priv;
+ flp = netdev_priv(slave);
rtnl_lock();
err = (*flp->deassoc)(slave, master);
@@ -491,7 +490,7 @@ static const struct header_ops dlci_header_ops = {
static void dlci_setup(struct net_device *dev)
{
- struct dlci_local *dlp = dev->priv;
+ struct dlci_local *dlp = netdev_priv(dev);
dev->flags = 0;
dev->open = dlci_open;
diff --git a/drivers/net/wan/dscc4.c b/drivers/net/wan/dscc4.c
index 5f1ccb2b08b1..888025db2f02 100644
--- a/drivers/net/wan/dscc4.c
+++ b/drivers/net/wan/dscc4.c
@@ -659,7 +659,6 @@ static inline void dscc4_rx_skb(struct dscc4_dev_priv *dpriv,
skb_put(skb, pkt_len);
if (netif_running(dev))
skb->protocol = hdlc_type_trans(skb, dev);
- skb->dev->last_rx = jiffies;
netif_rx(skb);
} else {
if (skb->data[pkt_len] & FrameRdo)
@@ -730,8 +729,7 @@ static int __devinit dscc4_init_one(struct pci_dev *pdev,
goto err_free_mmio_region_1;
}
- ioaddr = ioremap(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
+ ioaddr = pci_ioremap_bar(pdev, 0);
if (!ioaddr) {
printk(KERN_ERR "%s: cannot remap MMIO region %llx @ %llx\n",
DRV_NAME, (unsigned long long)pci_resource_len(pdev, 0),
diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c
index 9557ad078ab8..48a2c9d28950 100644
--- a/drivers/net/wan/farsync.c
+++ b/drivers/net/wan/farsync.c
@@ -896,7 +896,6 @@ fst_rx_dma_complete(struct fst_card_info *card, struct fst_port_info *port,
fst_process_rx_status(rx_status, port_to_dev(port)->name);
if (rx_status == NET_RX_DROP)
dev->stats.rx_dropped++;
- dev->last_rx = jiffies;
}
/*
@@ -1322,7 +1321,6 @@ fst_intr_rx(struct fst_card_info *card, struct fst_port_info *port)
fst_process_rx_status(rx_status, port_to_dev(port)->name);
if (rx_status == NET_RX_DROP)
dev->stats.rx_dropped++;
- dev->last_rx = jiffies;
} else {
card->dma_skb_rx = skb;
card->dma_port_rx = port;
diff --git a/drivers/net/wan/hd6457x.c b/drivers/net/wan/hd64570.c
index 591fb45a7c68..223238de475c 100644
--- a/drivers/net/wan/hd6457x.c
+++ b/drivers/net/wan/hd64570.c
@@ -1,5 +1,5 @@
/*
- * Hitachi SCA HD64570 and HD64572 common driver for Linux
+ * Hitachi SCA HD64570 driver for Linux
*
* Copyright (C) 1998-2003 Krzysztof Halasa <khc@pm.waw.pl>
*
@@ -7,9 +7,7 @@
* under the terms of version 2 of the GNU General Public License
* as published by the Free Software Foundation.
*
- * Sources of information:
- * Hitachi HD64570 SCA User's Manual
- * Hitachi HD64572 SCA-II User's Manual
+ * Source of information: Hitachi HD64570 SCA User's Manual
*
* We use the following SCA memory map:
*
@@ -26,33 +24,26 @@
* tx_ring_buffers * HDLC_MAX_MRU = logical channel #0 TX buffers (if used)
*/
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-#include <linux/types.h>
+#include <linux/bitops.h>
+#include <linux/errno.h>
#include <linux/fcntl.h>
-#include <linux/interrupt.h>
+#include <linux/hdlc.h>
#include <linux/in.h>
-#include <linux/string.h>
-#include <linux/errno.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/ioport.h>
-#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
-
-#include <linux/hdlc.h>
-
-#if (!defined (__HD64570_H) && !defined (__HD64572_H)) || \
- (defined (__HD64570_H) && defined (__HD64572_H))
-#error Either hd64570.h or hd64572.h must be included
-#endif
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include "hd64570.h"
#define get_msci(port) (phy_node(port) ? MSCI1_OFFSET : MSCI0_OFFSET)
#define get_dmac_rx(port) (phy_node(port) ? DMAC1RX_OFFSET : DMAC0RX_OFFSET)
@@ -62,16 +53,6 @@
#define SCA_INTR_DMAC_RX(node) (node ? 0x20 : 0x02)
#define SCA_INTR_DMAC_TX(node) (node ? 0x40 : 0x04)
-#ifdef __HD64570_H /* HD64570 */
-#define sca_outa(value, reg, card) sca_outw(value, reg, card)
-#define sca_ina(reg, card) sca_inw(reg, card)
-#define writea(value, ptr) writew(value, ptr)
-
-#else /* HD64572 */
-#define sca_outa(value, reg, card) sca_outl(value, reg, card)
-#define sca_ina(reg, card) sca_inl(reg, card)
-#define writea(value, ptr) writel(value, ptr)
-#endif
static inline struct net_device *port_to_dev(port_t *port)
{
@@ -81,8 +62,6 @@ static inline struct net_device *port_to_dev(port_t *port)
static inline int sca_intr_status(card_t *card)
{
u8 result = 0;
-
-#ifdef __HD64570_H /* HD64570 */
u8 isr0 = sca_in(ISR0, card);
u8 isr1 = sca_in(ISR1, card);
@@ -93,18 +72,6 @@ static inline int sca_intr_status(card_t *card)
if (isr0 & 0x0F) result |= SCA_INTR_MSCI(0);
if (isr0 & 0xF0) result |= SCA_INTR_MSCI(1);
-#else /* HD64572 */
- u32 isr0 = sca_inl(ISR0, card);
-
- if (isr0 & 0x0000000F) result |= SCA_INTR_DMAC_RX(0);
- if (isr0 & 0x000000F0) result |= SCA_INTR_DMAC_TX(0);
- if (isr0 & 0x00000F00) result |= SCA_INTR_DMAC_RX(1);
- if (isr0 & 0x0000F000) result |= SCA_INTR_DMAC_TX(1);
- if (isr0 & 0x003E0000) result |= SCA_INTR_MSCI(0);
- if (isr0 & 0x3E000000) result |= SCA_INTR_MSCI(1);
-
-#endif /* HD64570 vs HD64572 */
-
if (!(result & SCA_INTR_DMAC_TX(0)))
if (sca_in(DSR_TX(0), card) & DSR_EOM)
result |= SCA_INTR_DMAC_TX(0);
@@ -127,7 +94,6 @@ static inline u16 next_desc(port_t *port, u16 desc, int transmit)
}
-
static inline u16 desc_abs_number(port_t *port, u16 desc, int transmit)
{
u16 rx_buffs = port_to_card(port)->rx_ring_buffers;
@@ -139,28 +105,26 @@ static inline u16 desc_abs_number(port_t *port, u16 desc, int transmit)
}
-
static inline u16 desc_offset(port_t *port, u16 desc, int transmit)
{
- /* Descriptor offset always fits in 16 bytes */
+ /* Descriptor offset always fits in 16 bits */
return desc_abs_number(port, desc, transmit) * sizeof(pkt_desc);
}
-
-static inline pkt_desc __iomem *desc_address(port_t *port, u16 desc, int transmit)
+static inline pkt_desc __iomem *desc_address(port_t *port, u16 desc,
+ int transmit)
{
#ifdef PAGE0_ALWAYS_MAPPED
return (pkt_desc __iomem *)(win0base(port_to_card(port))
- + desc_offset(port, desc, transmit));
+ + desc_offset(port, desc, transmit));
#else
return (pkt_desc __iomem *)(winbase(port_to_card(port))
- + desc_offset(port, desc, transmit));
+ + desc_offset(port, desc, transmit));
#endif
}
-
static inline u32 buffer_offset(port_t *port, u16 desc, int transmit)
{
return port_to_card(port)->buff_offset +
@@ -186,7 +150,7 @@ static inline void sca_set_carrier(port_t *port)
}
-static void sca_init_sync_port(port_t *port)
+static void sca_init_port(port_t *port)
{
card_t *card = port_to_card(port);
int transmit, i;
@@ -195,7 +159,7 @@ static void sca_init_sync_port(port_t *port)
port->txin = 0;
port->txlast = 0;
-#if !defined(PAGE0_ALWAYS_MAPPED) && !defined(ALL_PAGES_ALWAYS_MAPPED)
+#ifndef PAGE0_ALWAYS_MAPPED
openwin(card, 0);
#endif
@@ -209,7 +173,7 @@ static void sca_init_sync_port(port_t *port)
u16 chain_off = desc_offset(port, i + 1, transmit);
u32 buff_off = buffer_offset(port, i, transmit);
- writea(chain_off, &desc->cp);
+ writew(chain_off, &desc->cp);
writel(buff_off, &desc->bp);
writew(0, &desc->len);
writeb(0, &desc->stat);
@@ -222,16 +186,14 @@ static void sca_init_sync_port(port_t *port)
sca_out(DCR_ABORT, transmit ? DCR_TX(phy_node(port)) :
DCR_RX(phy_node(port)), card);
-#ifdef __HD64570_H
- sca_out(0, dmac + CPB, card); /* pointer base */
-#endif
/* current desc addr */
- sca_outa(desc_offset(port, 0, transmit), dmac + CDAL, card);
+ sca_out(0, dmac + CPB, card); /* pointer base */
+ sca_outw(desc_offset(port, 0, transmit), dmac + CDAL, card);
if (!transmit)
- sca_outa(desc_offset(port, buffs - 1, transmit),
+ sca_outw(desc_offset(port, buffs - 1, transmit),
dmac + EDAL, card);
else
- sca_outa(desc_offset(port, 0, transmit), dmac + EDAL,
+ sca_outw(desc_offset(port, 0, transmit), dmac + EDAL,
card);
/* clear frame end interrupt counter */
@@ -258,7 +220,6 @@ static void sca_init_sync_port(port_t *port)
}
-
#ifdef NEED_SCA_MSCI_INTR
/* MSCI interrupt service */
static inline void sca_msci_intr(port_t *port)
@@ -282,17 +243,15 @@ static inline void sca_msci_intr(port_t *port)
#endif
-
-static inline void sca_rx(card_t *card, port_t *port, pkt_desc __iomem *desc, u16 rxin)
+static inline void sca_rx(card_t *card, port_t *port, pkt_desc __iomem *desc,
+ u16 rxin)
{
struct net_device *dev = port_to_dev(port);
struct sk_buff *skb;
u16 len;
u32 buff;
-#ifndef ALL_PAGES_ALWAYS_MAPPED
u32 maxlen;
u8 page;
-#endif
len = readw(&desc->len);
skb = dev_alloc_skb(len);
@@ -302,7 +261,6 @@ static inline void sca_rx(card_t *card, port_t *port, pkt_desc __iomem *desc, u1
}
buff = buffer_offset(port, rxin, 0);
-#ifndef ALL_PAGES_ALWAYS_MAPPED
page = buff / winsize(card);
buff = buff % winsize(card);
maxlen = winsize(card) - buff;
@@ -314,12 +272,10 @@ static inline void sca_rx(card_t *card, port_t *port, pkt_desc __iomem *desc, u1
openwin(card, page + 1);
memcpy_fromio(skb->data + maxlen, winbase(card), len - maxlen);
} else
-#endif
- memcpy_fromio(skb->data, winbase(card) + buff, len);
+ memcpy_fromio(skb->data, winbase(card) + buff, len);
-#if !defined(PAGE0_ALWAYS_MAPPED) && !defined(ALL_PAGES_ALWAYS_MAPPED)
- /* select pkt_desc table page back */
- openwin(card, 0);
+#ifndef PAGE0_ALWAYS_MAPPED
+ openwin(card, 0); /* select pkt_desc table page back */
#endif
skb_put(skb, len);
#ifdef DEBUG_PKT
@@ -328,13 +284,11 @@ static inline void sca_rx(card_t *card, port_t *port, pkt_desc __iomem *desc, u1
#endif
dev->stats.rx_packets++;
dev->stats.rx_bytes += skb->len;
- dev->last_rx = jiffies;
skb->protocol = hdlc_type_trans(skb, dev);
netif_rx(skb);
}
-
/* Receive DMA interrupt service */
static inline void sca_rx_intr(port_t *port)
{
@@ -354,7 +308,7 @@ static inline void sca_rx_intr(port_t *port)
while (1) {
u32 desc_off = desc_offset(port, port->rxin, 0);
pkt_desc __iomem *desc;
- u32 cda = sca_ina(dmac + CDAL, card);
+ u32 cda = sca_inw(dmac + CDAL, card);
if ((cda >= desc_off) && (cda < desc_off + sizeof(pkt_desc)))
break; /* No frame received */
@@ -378,7 +332,7 @@ static inline void sca_rx_intr(port_t *port)
sca_rx(card, port, desc, port->rxin);
/* Set new error descriptor address */
- sca_outa(desc_off, dmac + EDAL, card);
+ sca_outw(desc_off, dmac + EDAL, card);
port->rxin = next_desc(port, port->rxin, 0);
}
@@ -387,7 +341,6 @@ static inline void sca_rx_intr(port_t *port)
}
-
/* Transmit DMA interrupt service */
static inline void sca_tx_intr(port_t *port)
{
@@ -408,7 +361,7 @@ static inline void sca_tx_intr(port_t *port)
pkt_desc __iomem *desc;
u32 desc_off = desc_offset(port, port->txlast, 1);
- u32 cda = sca_ina(dmac + CDAL, card);
+ u32 cda = sca_inw(dmac + CDAL, card);
if ((cda >= desc_off) && (cda < desc_off + sizeof(pkt_desc)))
break; /* Transmitter is/will_be sending this frame */
@@ -424,17 +377,13 @@ static inline void sca_tx_intr(port_t *port)
}
-
static irqreturn_t sca_intr(int irq, void* dev_id)
{
card_t *card = dev_id;
int i;
u8 stat;
int handled = 0;
-
-#ifndef ALL_PAGES_ALWAYS_MAPPED
u8 page = sca_get_page(card);
-#endif
while((stat = sca_intr_status(card)) != 0) {
handled = 1;
@@ -453,14 +402,11 @@ static irqreturn_t sca_intr(int irq, void* dev_id)
}
}
-#ifndef ALL_PAGES_ALWAYS_MAPPED
openwin(card, page); /* Restore original page */
-#endif
return IRQ_RETVAL(handled);
}
-
static void sca_set_port(port_t *port)
{
card_t* card = port_to_card(port);
@@ -498,12 +444,7 @@ static void sca_set_port(port_t *port)
port->tmc = tmc;
/* baud divisor - time constant*/
-#ifdef __HD64570_H
sca_out(port->tmc, msci + TMC, card);
-#else
- sca_out(port->tmc, msci + TMCR, card);
- sca_out(port->tmc, msci + TMCT, card);
-#endif
/* Set BRG bits */
sca_out(port->rxs, msci + RXS, card);
@@ -519,7 +460,6 @@ static void sca_set_port(port_t *port)
}
-
static void sca_open(struct net_device *dev)
{
port_t *port = dev_to_port(dev);
@@ -541,11 +481,7 @@ static void sca_open(struct net_device *dev)
switch(port->parity) {
case PARITY_CRC16_PR0: md0 = MD0_HDLC | MD0_CRC_16_0; break;
case PARITY_CRC16_PR1: md0 = MD0_HDLC | MD0_CRC_16; break;
-#ifdef __HD64570_H
case PARITY_CRC16_PR0_CCITT: md0 = MD0_HDLC | MD0_CRC_ITU_0; break;
-#else
- case PARITY_CRC32_PR1_CCITT: md0 = MD0_HDLC | MD0_CRC_ITU32; break;
-#endif
case PARITY_CRC16_PR1_CCITT: md0 = MD0_HDLC | MD0_CRC_ITU; break;
default: md0 = MD0_HDLC | MD0_CRC_NONE;
}
@@ -555,35 +491,20 @@ static void sca_open(struct net_device *dev)
sca_out(0x00, msci + MD1, card); /* no address field check */
sca_out(md2, msci + MD2, card);
sca_out(0x7E, msci + IDL, card); /* flag character 0x7E */
-#ifdef __HD64570_H
sca_out(CTL_IDLE, msci + CTL, card);
-#else
- /* Skip the rest of underrun frame */
- sca_out(CTL_IDLE | CTL_URCT | CTL_URSKP, msci + CTL, card);
-#endif
-#ifdef __HD64570_H
/* Allow at least 8 bytes before requesting RX DMA operation */
/* TX with higher priority and possibly with shorter transfers */
sca_out(0x07, msci + RRC, card); /* +1=RXRDY/DMA activation condition*/
sca_out(0x10, msci + TRC0, card); /* = TXRDY/DMA activation condition*/
sca_out(0x14, msci + TRC1, card); /* +1=TXRDY/DMA deactiv condition */
-#else
- sca_out(0x0F, msci + RNR, card); /* +1=RX DMA activation condition */
- sca_out(0x3C, msci + TFS, card); /* +1 = TX start */
- sca_out(0x38, msci + TCR, card); /* =Critical TX DMA activ condition */
- sca_out(0x38, msci + TNR0, card); /* =TX DMA activation condition */
- sca_out(0x3F, msci + TNR1, card); /* +1=TX DMA deactivation condition*/
-#endif
/* We're using the following interrupts:
- TXINT (DMAC completed all transmisions, underrun or DCD change)
- all DMA interrupts
*/
-
sca_set_carrier(port);
-#ifdef __HD64570_H
/* MSCI TX INT and RX INT A IRQ enable */
sca_out(IE0_TXINT | IE0_RXINTA, msci + IE0, card);
sca_out(IE1_UDRN | IE1_CDCD, msci + IE1, card);
@@ -592,21 +513,8 @@ static void sca_open(struct net_device *dev)
/* enable DMA IRQ */
sca_out(sca_in(IER1, card) | (phy_node(port) ? 0xF0 : 0x0F),
IER1, card);
-#else
- /* MSCI TXINT and RXINTA interrupt enable */
- sca_outl(IE0_TXINT | IE0_RXINTA | IE0_UDRN | IE0_CDCD, msci + IE0,
- card);
- /* DMA & MSCI IRQ enable */
- sca_outl(sca_inl(IER0, card) |
- (phy_node(port) ? 0x0A006600 : 0x000A0066), IER0, card);
-#endif
-#ifdef __HD64570_H
sca_out(port->tmc, msci + TMC, card); /* Restore registers */
-#else
- sca_out(port->tmc, msci + TMCR, card);
- sca_out(port->tmc, msci + TMCT, card);
-#endif
sca_out(port->rxs, msci + RXS, card);
sca_out(port->txs, msci + TXS, card);
sca_out(CMD_TX_ENABLE, msci + CMD, card);
@@ -616,7 +524,6 @@ static void sca_open(struct net_device *dev)
}
-
static void sca_close(struct net_device *dev)
{
port_t *port = dev_to_port(dev);
@@ -624,23 +531,17 @@ static void sca_close(struct net_device *dev)
/* reset channel */
sca_out(CMD_RESET, get_msci(port) + CMD, port_to_card(port));
-#ifdef __HD64570_H
/* disable MSCI interrupts */
sca_out(sca_in(IER0, card) & (phy_node(port) ? 0x0F : 0xF0),
IER0, card);
/* disable DMA interrupts */
sca_out(sca_in(IER1, card) & (phy_node(port) ? 0x0F : 0xF0),
IER1, card);
-#else
- /* disable DMA & MSCI IRQ */
- sca_outl(sca_inl(IER0, card) &
- (phy_node(port) ? 0x00FF00FF : 0xFF00FF00), IER0, card);
-#endif
+
netif_stop_queue(dev);
}
-
static int sca_attach(struct net_device *dev, unsigned short encoding,
unsigned short parity)
{
@@ -654,11 +555,7 @@ static int sca_attach(struct net_device *dev, unsigned short encoding,
if (parity != PARITY_NONE &&
parity != PARITY_CRC16_PR0 &&
parity != PARITY_CRC16_PR1 &&
-#ifdef __HD64570_H
parity != PARITY_CRC16_PR0_CCITT &&
-#else
- parity != PARITY_CRC32_PR1_CCITT &&
-#endif
parity != PARITY_CRC16_PR1_CCITT)
return -EINVAL;
@@ -668,34 +565,30 @@ static int sca_attach(struct net_device *dev, unsigned short encoding,
}
-
#ifdef DEBUG_RINGS
static void sca_dump_rings(struct net_device *dev)
{
port_t *port = dev_to_port(dev);
card_t *card = port_to_card(port);
u16 cnt;
-#if !defined(PAGE0_ALWAYS_MAPPED) && !defined(ALL_PAGES_ALWAYS_MAPPED)
- u8 page;
-#endif
+#ifndef PAGE0_ALWAYS_MAPPED
+ u8 page = sca_get_page(card);
-#if !defined(PAGE0_ALWAYS_MAPPED) && !defined(ALL_PAGES_ALWAYS_MAPPED)
- page = sca_get_page(card);
openwin(card, 0);
#endif
printk(KERN_DEBUG "RX ring: CDA=%u EDA=%u DSR=%02X in=%u %sactive",
- sca_ina(get_dmac_rx(port) + CDAL, card),
- sca_ina(get_dmac_rx(port) + EDAL, card),
+ sca_inw(get_dmac_rx(port) + CDAL, card),
+ sca_inw(get_dmac_rx(port) + EDAL, card),
sca_in(DSR_RX(phy_node(port)), card), port->rxin,
- sca_in(DSR_RX(phy_node(port)), card) & DSR_DE?"":"in");
+ sca_in(DSR_RX(phy_node(port)), card) & DSR_DE ? "" : "in");
for (cnt = 0; cnt < port_to_card(port)->rx_ring_buffers; cnt++)
printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
printk("\n" KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u "
"last=%u %sactive",
- sca_ina(get_dmac_tx(port) + CDAL, card),
- sca_ina(get_dmac_tx(port) + EDAL, card),
+ sca_inw(get_dmac_tx(port) + CDAL, card),
+ sca_inw(get_dmac_tx(port) + EDAL, card),
sca_in(DSR_TX(phy_node(port)), card), port->txin, port->txlast,
sca_in(DSR_TX(phy_node(port)), card) & DSR_DE ? "" : "in");
@@ -703,12 +596,8 @@ static void sca_dump_rings(struct net_device *dev)
printk(" %02X", readb(&(desc_address(port, cnt, 1)->stat)));
printk("\n");
- printk(KERN_DEBUG "MSCI: MD: %02x %02x %02x, "
- "ST: %02x %02x %02x %02x"
-#ifdef __HD64572_H
- " %02x"
-#endif
- ", FST: %02x CST: %02x %02x\n",
+ printk(KERN_DEBUG "MSCI: MD: %02x %02x %02x, ST: %02x %02x %02x %02x,"
+ " FST: %02x CST: %02x %02x\n",
sca_in(get_msci(port) + MD0, card),
sca_in(get_msci(port) + MD1, card),
sca_in(get_msci(port) + MD2, card),
@@ -716,52 +605,33 @@ static void sca_dump_rings(struct net_device *dev)
sca_in(get_msci(port) + ST1, card),
sca_in(get_msci(port) + ST2, card),
sca_in(get_msci(port) + ST3, card),
-#ifdef __HD64572_H
- sca_in(get_msci(port) + ST4, card),
-#endif
sca_in(get_msci(port) + FST, card),
sca_in(get_msci(port) + CST0, card),
sca_in(get_msci(port) + CST1, card));
-#ifdef __HD64572_H
- printk(KERN_DEBUG "ILAR: %02x ISR: %08x %08x\n", sca_in(ILAR, card),
- sca_inl(ISR0, card), sca_inl(ISR1, card));
-#else
printk(KERN_DEBUG "ISR: %02x %02x %02x\n", sca_in(ISR0, card),
sca_in(ISR1, card), sca_in(ISR2, card));
-#endif
-#if !defined(PAGE0_ALWAYS_MAPPED) && !defined(ALL_PAGES_ALWAYS_MAPPED)
+#ifndef PAGE0_ALWAYS_MAPPED
openwin(card, page); /* Restore original page */
#endif
}
#endif /* DEBUG_RINGS */
-
static int sca_xmit(struct sk_buff *skb, struct net_device *dev)
{
port_t *port = dev_to_port(dev);
card_t *card = port_to_card(port);
pkt_desc __iomem *desc;
u32 buff, len;
-#ifndef ALL_PAGES_ALWAYS_MAPPED
u8 page;
u32 maxlen;
-#endif
spin_lock_irq(&port->lock);
desc = desc_address(port, port->txin + 1, 1);
- if (readb(&desc->stat)) { /* allow 1 packet gap */
- /* should never happen - previous xmit should stop queue */
-#ifdef DEBUG_PKT
- printk(KERN_DEBUG "%s: transmitter buffer full\n", dev->name);
-#endif
- netif_stop_queue(dev);
- spin_unlock_irq(&port->lock);
- return 1; /* request packet to be queued */
- }
+ BUG_ON(readb(&desc->stat)); /* previous xmit should stop queue */
#ifdef DEBUG_PKT
printk(KERN_DEBUG "%s TX(%i):", dev->name, skb->len);
@@ -771,7 +641,6 @@ static int sca_xmit(struct sk_buff *skb, struct net_device *dev)
desc = desc_address(port, port->txin, 1);
buff = buffer_offset(port, port->txin, 1);
len = skb->len;
-#ifndef ALL_PAGES_ALWAYS_MAPPED
page = buff / winsize(card);
buff = buff % winsize(card);
maxlen = winsize(card) - buff;
@@ -781,12 +650,10 @@ static int sca_xmit(struct sk_buff *skb, struct net_device *dev)
memcpy_toio(winbase(card) + buff, skb->data, maxlen);
openwin(card, page + 1);
memcpy_toio(winbase(card), skb->data + maxlen, len - maxlen);
- }
- else
-#endif
+ } else
memcpy_toio(winbase(card) + buff, skb->data, len);
-#if !defined(PAGE0_ALWAYS_MAPPED) && !defined(ALL_PAGES_ALWAYS_MAPPED)
+#ifndef PAGE0_ALWAYS_MAPPED
openwin(card, 0); /* select pkt_desc table page back */
#endif
writew(len, &desc->len);
@@ -794,7 +661,7 @@ static int sca_xmit(struct sk_buff *skb, struct net_device *dev)
dev->trans_start = jiffies;
port->txin = next_desc(port, port->txin, 1);
- sca_outa(desc_offset(port, port->txin, 1),
+ sca_outw(desc_offset(port, port->txin, 1),
get_dmac_tx(port) + EDAL, card);
sca_out(DSR_DE, DSR_TX(phy_node(port)), card); /* Enable TX DMA */
@@ -810,40 +677,29 @@ static int sca_xmit(struct sk_buff *skb, struct net_device *dev)
}
-
#ifdef NEED_DETECT_RAM
-static u32 __devinit sca_detect_ram(card_t *card, u8 __iomem *rambase, u32 ramsize)
+static u32 __devinit sca_detect_ram(card_t *card, u8 __iomem *rambase,
+ u32 ramsize)
{
/* Round RAM size to 32 bits, fill from end to start */
u32 i = ramsize &= ~3;
-
-#ifndef ALL_PAGES_ALWAYS_MAPPED
u32 size = winsize(card);
openwin(card, (i - 4) / size); /* select last window */
-#endif
+
do {
i -= 4;
-#ifndef ALL_PAGES_ALWAYS_MAPPED
if ((i + 4) % size == 0)
openwin(card, i / size);
writel(i ^ 0x12345678, rambase + i % size);
-#else
- writel(i ^ 0x12345678, rambase + i);
-#endif
- }while (i > 0);
+ } while (i > 0);
for (i = 0; i < ramsize ; i += 4) {
-#ifndef ALL_PAGES_ALWAYS_MAPPED
if (i % size == 0)
openwin(card, i / size);
if (readl(rambase + i % size) != (i ^ 0x12345678))
break;
-#else
- if (readl(rambase + i) != (i ^ 0x12345678))
- break;
-#endif
}
return i;
@@ -851,7 +707,6 @@ static u32 __devinit sca_detect_ram(card_t *card, u8 __iomem *rambase, u32 ramsi
#endif /* NEED_DETECT_RAM */
-
static void __devinit sca_init(card_t *card, int wait_states)
{
sca_out(wait_states, WCRL, card); /* Wait Control */
diff --git a/drivers/net/wan/hd64572.c b/drivers/net/wan/hd64572.c
new file mode 100644
index 000000000000..08b3536944fe
--- /dev/null
+++ b/drivers/net/wan/hd64572.c
@@ -0,0 +1,640 @@
+/*
+ * Hitachi (now Renesas) SCA-II HD64572 driver for Linux
+ *
+ * Copyright (C) 1998-2008 Krzysztof Halasa <khc@pm.waw.pl>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ *
+ * Source of information: HD64572 SCA-II User's Manual
+ *
+ * We use the following SCA memory map:
+ *
+ * Packet buffer descriptor rings - starting from card->rambase:
+ * rx_ring_buffers * sizeof(pkt_desc) = logical channel #0 RX ring
+ * tx_ring_buffers * sizeof(pkt_desc) = logical channel #0 TX ring
+ * rx_ring_buffers * sizeof(pkt_desc) = logical channel #1 RX ring (if used)
+ * tx_ring_buffers * sizeof(pkt_desc) = logical channel #1 TX ring (if used)
+ *
+ * Packet data buffers - starting from card->rambase + buff_offset:
+ * rx_ring_buffers * HDLC_MAX_MRU = logical channel #0 RX buffers
+ * tx_ring_buffers * HDLC_MAX_MRU = logical channel #0 TX buffers
+ * rx_ring_buffers * HDLC_MAX_MRU = logical channel #0 RX buffers (if used)
+ * tx_ring_buffers * HDLC_MAX_MRU = logical channel #0 TX buffers (if used)
+ */
+
+#include <linux/bitops.h>
+#include <linux/errno.h>
+#include <linux/fcntl.h>
+#include <linux/hdlc.h>
+#include <linux/in.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include "hd64572.h"
+
+#define NAPI_WEIGHT 16
+
+#define get_msci(port) (port->chan ? MSCI1_OFFSET : MSCI0_OFFSET)
+#define get_dmac_rx(port) (port->chan ? DMAC1RX_OFFSET : DMAC0RX_OFFSET)
+#define get_dmac_tx(port) (port->chan ? DMAC1TX_OFFSET : DMAC0TX_OFFSET)
+
+#define sca_in(reg, card) readb(card->scabase + (reg))
+#define sca_out(value, reg, card) writeb(value, card->scabase + (reg))
+#define sca_inw(reg, card) readw(card->scabase + (reg))
+#define sca_outw(value, reg, card) writew(value, card->scabase + (reg))
+#define sca_inl(reg, card) readl(card->scabase + (reg))
+#define sca_outl(value, reg, card) writel(value, card->scabase + (reg))
+
+static int sca_poll(struct napi_struct *napi, int budget);
+
+static inline port_t* dev_to_port(struct net_device *dev)
+{
+ return dev_to_hdlc(dev)->priv;
+}
+
+static inline void enable_intr(port_t *port)
+{
+ /* enable DMIB and MSCI RXINTA interrupts */
+ sca_outl(sca_inl(IER0, port->card) |
+ (port->chan ? 0x08002200 : 0x00080022), IER0, port->card);
+}
+
+static inline void disable_intr(port_t *port)
+{
+ sca_outl(sca_inl(IER0, port->card) &
+ (port->chan ? 0x00FF00FF : 0xFF00FF00), IER0, port->card);
+}
+
+static inline u16 desc_abs_number(port_t *port, u16 desc, int transmit)
+{
+ u16 rx_buffs = port->card->rx_ring_buffers;
+ u16 tx_buffs = port->card->tx_ring_buffers;
+
+ desc %= (transmit ? tx_buffs : rx_buffs); // called with "X + 1" etc.
+ return port->chan * (rx_buffs + tx_buffs) + transmit * rx_buffs + desc;
+}
+
+
+static inline u16 desc_offset(port_t *port, u16 desc, int transmit)
+{
+ /* Descriptor offset always fits in 16 bits */
+ return desc_abs_number(port, desc, transmit) * sizeof(pkt_desc);
+}
+
+
+static inline pkt_desc __iomem *desc_address(port_t *port, u16 desc,
+ int transmit)
+{
+ return (pkt_desc __iomem *)(port->card->rambase +
+ desc_offset(port, desc, transmit));
+}
+
+
+static inline u32 buffer_offset(port_t *port, u16 desc, int transmit)
+{
+ return port->card->buff_offset +
+ desc_abs_number(port, desc, transmit) * (u32)HDLC_MAX_MRU;
+}
+
+
+static inline void sca_set_carrier(port_t *port)
+{
+ if (!(sca_in(get_msci(port) + ST3, port->card) & ST3_DCD)) {
+#ifdef DEBUG_LINK
+ printk(KERN_DEBUG "%s: sca_set_carrier on\n",
+ port->netdev.name);
+#endif
+ netif_carrier_on(port->netdev);
+ } else {
+#ifdef DEBUG_LINK
+ printk(KERN_DEBUG "%s: sca_set_carrier off\n",
+ port->netdev.name);
+#endif
+ netif_carrier_off(port->netdev);
+ }
+}
+
+
+static void sca_init_port(port_t *port)
+{
+ card_t *card = port->card;
+ u16 dmac_rx = get_dmac_rx(port), dmac_tx = get_dmac_tx(port);
+ int transmit, i;
+
+ port->rxin = 0;
+ port->txin = 0;
+ port->txlast = 0;
+
+ for (transmit = 0; transmit < 2; transmit++) {
+ u16 buffs = transmit ? card->tx_ring_buffers
+ : card->rx_ring_buffers;
+
+ for (i = 0; i < buffs; i++) {
+ pkt_desc __iomem *desc = desc_address(port, i, transmit);
+ u16 chain_off = desc_offset(port, i + 1, transmit);
+ u32 buff_off = buffer_offset(port, i, transmit);
+
+ writel(chain_off, &desc->cp);
+ writel(buff_off, &desc->bp);
+ writew(0, &desc->len);
+ writeb(0, &desc->stat);
+ }
+ }
+
+ /* DMA disable - to halt state */
+ sca_out(0, DSR_RX(port->chan), card);
+ sca_out(0, DSR_TX(port->chan), card);
+
+ /* software ABORT - to initial state */
+ sca_out(DCR_ABORT, DCR_RX(port->chan), card);
+ sca_out(DCR_ABORT, DCR_TX(port->chan), card);
+
+ /* current desc addr */
+ sca_outl(desc_offset(port, 0, 0), dmac_rx + CDAL, card);
+ sca_outl(desc_offset(port, card->tx_ring_buffers - 1, 0),
+ dmac_rx + EDAL, card);
+ sca_outl(desc_offset(port, 0, 1), dmac_tx + CDAL, card);
+ sca_outl(desc_offset(port, 0, 1), dmac_tx + EDAL, card);
+
+ /* clear frame end interrupt counter */
+ sca_out(DCR_CLEAR_EOF, DCR_RX(port->chan), card);
+ sca_out(DCR_CLEAR_EOF, DCR_TX(port->chan), card);
+
+ /* Receive */
+ sca_outw(HDLC_MAX_MRU, dmac_rx + BFLL, card); /* set buffer length */
+ sca_out(0x14, DMR_RX(port->chan), card); /* Chain mode, Multi-frame */
+ sca_out(DIR_EOME, DIR_RX(port->chan), card); /* enable interrupts */
+ sca_out(DSR_DE, DSR_RX(port->chan), card); /* DMA enable */
+
+ /* Transmit */
+ sca_out(0x14, DMR_TX(port->chan), card); /* Chain mode, Multi-frame */
+ sca_out(DIR_EOME, DIR_TX(port->chan), card); /* enable interrupts */
+
+ sca_set_carrier(port);
+ netif_napi_add(port->netdev, &port->napi, sca_poll, NAPI_WEIGHT);
+}
+
+
+/* MSCI interrupt service */
+static inline void sca_msci_intr(port_t *port)
+{
+ u16 msci = get_msci(port);
+ card_t* card = port->card;
+
+ if (sca_in(msci + ST1, card) & ST1_CDCD) {
+ /* Reset MSCI CDCD status bit */
+ sca_out(ST1_CDCD, msci + ST1, card);
+ sca_set_carrier(port);
+ }
+}
+
+
+static inline void sca_rx(card_t *card, port_t *port, pkt_desc __iomem *desc,
+ u16 rxin)
+{
+ struct net_device *dev = port->netdev;
+ struct sk_buff *skb;
+ u16 len;
+ u32 buff;
+
+ len = readw(&desc->len);
+ skb = dev_alloc_skb(len);
+ if (!skb) {
+ dev->stats.rx_dropped++;
+ return;
+ }
+
+ buff = buffer_offset(port, rxin, 0);
+ memcpy_fromio(skb->data, card->rambase + buff, len);
+
+ skb_put(skb, len);
+#ifdef DEBUG_PKT
+ printk(KERN_DEBUG "%s RX(%i):", dev->name, skb->len);
+ debug_frame(skb);
+#endif
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += skb->len;
+ skb->protocol = hdlc_type_trans(skb, dev);
+ netif_receive_skb(skb);
+}
+
+
+/* Receive DMA service */
+static inline int sca_rx_done(port_t *port, int budget)
+{
+ struct net_device *dev = port->netdev;
+ u16 dmac = get_dmac_rx(port);
+ card_t *card = port->card;
+ u8 stat = sca_in(DSR_RX(port->chan), card); /* read DMA Status */
+ int received = 0;
+
+ /* Reset DSR status bits */
+ sca_out((stat & (DSR_EOT | DSR_EOM | DSR_BOF | DSR_COF)) | DSR_DWE,
+ DSR_RX(port->chan), card);
+
+ if (stat & DSR_BOF)
+ /* Dropped one or more frames */
+ dev->stats.rx_over_errors++;
+
+ while (received < budget) {
+ u32 desc_off = desc_offset(port, port->rxin, 0);
+ pkt_desc __iomem *desc;
+ u32 cda = sca_inl(dmac + CDAL, card);
+
+ if ((cda >= desc_off) && (cda < desc_off + sizeof(pkt_desc)))
+ break; /* No frame received */
+
+ desc = desc_address(port, port->rxin, 0);
+ stat = readb(&desc->stat);
+ if (!(stat & ST_RX_EOM))
+ port->rxpart = 1; /* partial frame received */
+ else if ((stat & ST_ERROR_MASK) || port->rxpart) {
+ dev->stats.rx_errors++;
+ if (stat & ST_RX_OVERRUN)
+ dev->stats.rx_fifo_errors++;
+ else if ((stat & (ST_RX_SHORT | ST_RX_ABORT |
+ ST_RX_RESBIT)) || port->rxpart)
+ dev->stats.rx_frame_errors++;
+ else if (stat & ST_RX_CRC)
+ dev->stats.rx_crc_errors++;
+ if (stat & ST_RX_EOM)
+ port->rxpart = 0; /* received last fragment */
+ } else {
+ sca_rx(card, port, desc, port->rxin);
+ received++;
+ }
+
+ /* Set new error descriptor address */
+ sca_outl(desc_off, dmac + EDAL, card);
+ port->rxin = (port->rxin + 1) % card->rx_ring_buffers;
+ }
+
+ /* make sure RX DMA is enabled */
+ sca_out(DSR_DE, DSR_RX(port->chan), card);
+ return received;
+}
+
+
+/* Transmit DMA service */
+static inline void sca_tx_done(port_t *port)
+{
+ struct net_device *dev = port->netdev;
+ card_t* card = port->card;
+ u8 stat;
+
+ spin_lock(&port->lock);
+
+ stat = sca_in(DSR_TX(port->chan), card); /* read DMA Status */
+
+ /* Reset DSR status bits */
+ sca_out((stat & (DSR_EOT | DSR_EOM | DSR_BOF | DSR_COF)) | DSR_DWE,
+ DSR_TX(port->chan), card);
+
+ while (1) {
+ pkt_desc __iomem *desc = desc_address(port, port->txlast, 1);
+ u8 stat = readb(&desc->stat);
+
+ if (!(stat & ST_TX_OWNRSHP))
+ break; /* not yet transmitted */
+ if (stat & ST_TX_UNDRRUN) {
+ dev->stats.tx_errors++;
+ dev->stats.tx_fifo_errors++;
+ } else {
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += readw(&desc->len);
+ }
+ writeb(0, &desc->stat); /* Free descriptor */
+ port->txlast = (port->txlast + 1) % card->tx_ring_buffers;
+ }
+
+ netif_wake_queue(dev);
+ spin_unlock(&port->lock);
+}
+
+
+static int sca_poll(struct napi_struct *napi, int budget)
+{
+ port_t *port = container_of(napi, port_t, napi);
+ u32 isr0 = sca_inl(ISR0, port->card);
+ int received = 0;
+
+ if (isr0 & (port->chan ? 0x08000000 : 0x00080000))
+ sca_msci_intr(port);
+
+ if (isr0 & (port->chan ? 0x00002000 : 0x00000020))
+ sca_tx_done(port);
+
+ if (isr0 & (port->chan ? 0x00000200 : 0x00000002))
+ received = sca_rx_done(port, budget);
+
+ if (received < budget) {
+ netif_rx_complete(napi);
+ enable_intr(port);
+ }
+
+ return received;
+}
+
+static irqreturn_t sca_intr(int irq, void *dev_id)
+{
+ card_t *card = dev_id;
+ u32 isr0 = sca_inl(ISR0, card);
+ int i, handled = 0;
+
+ for (i = 0; i < 2; i++) {
+ port_t *port = get_port(card, i);
+ if (port && (isr0 & (i ? 0x08002200 : 0x00080022))) {
+ handled = 1;
+ disable_intr(port);
+ netif_rx_schedule(&port->napi);
+ }
+ }
+
+ return IRQ_RETVAL(handled);
+}
+
+
+static void sca_set_port(port_t *port)
+{
+ card_t* card = port->card;
+ u16 msci = get_msci(port);
+ u8 md2 = sca_in(msci + MD2, card);
+ unsigned int tmc, br = 10, brv = 1024;
+
+
+ if (port->settings.clock_rate > 0) {
+ /* Try lower br for better accuracy*/
+ do {
+ br--;
+ brv >>= 1; /* brv = 2^9 = 512 max in specs */
+
+ /* Baud Rate = CLOCK_BASE / TMC / 2^BR */
+ tmc = CLOCK_BASE / brv / port->settings.clock_rate;
+ }while (br > 1 && tmc <= 128);
+
+ if (tmc < 1) {
+ tmc = 1;
+ br = 0; /* For baud=CLOCK_BASE we use tmc=1 br=0 */
+ brv = 1;
+ } else if (tmc > 255)
+ tmc = 256; /* tmc=0 means 256 - low baud rates */
+
+ port->settings.clock_rate = CLOCK_BASE / brv / tmc;
+ } else {
+ br = 9; /* Minimum clock rate */
+ tmc = 256; /* 8bit = 0 */
+ port->settings.clock_rate = CLOCK_BASE / (256 * 512);
+ }
+
+ port->rxs = (port->rxs & ~CLK_BRG_MASK) | br;
+ port->txs = (port->txs & ~CLK_BRG_MASK) | br;
+ port->tmc = tmc;
+
+ /* baud divisor - time constant*/
+ sca_out(port->tmc, msci + TMCR, card);
+ sca_out(port->tmc, msci + TMCT, card);
+
+ /* Set BRG bits */
+ sca_out(port->rxs, msci + RXS, card);
+ sca_out(port->txs, msci + TXS, card);
+
+ if (port->settings.loopback)
+ md2 |= MD2_LOOPBACK;
+ else
+ md2 &= ~MD2_LOOPBACK;
+
+ sca_out(md2, msci + MD2, card);
+
+}
+
+
+static void sca_open(struct net_device *dev)
+{
+ port_t *port = dev_to_port(dev);
+ card_t* card = port->card;
+ u16 msci = get_msci(port);
+ u8 md0, md2;
+
+ switch(port->encoding) {
+ case ENCODING_NRZ: md2 = MD2_NRZ; break;
+ case ENCODING_NRZI: md2 = MD2_NRZI; break;
+ case ENCODING_FM_MARK: md2 = MD2_FM_MARK; break;
+ case ENCODING_FM_SPACE: md2 = MD2_FM_SPACE; break;
+ default: md2 = MD2_MANCHESTER;
+ }
+
+ if (port->settings.loopback)
+ md2 |= MD2_LOOPBACK;
+
+ switch(port->parity) {
+ case PARITY_CRC16_PR0: md0 = MD0_HDLC | MD0_CRC_16_0; break;
+ case PARITY_CRC16_PR1: md0 = MD0_HDLC | MD0_CRC_16; break;
+ case PARITY_CRC32_PR1_CCITT: md0 = MD0_HDLC | MD0_CRC_ITU32; break;
+ case PARITY_CRC16_PR1_CCITT: md0 = MD0_HDLC | MD0_CRC_ITU; break;
+ default: md0 = MD0_HDLC | MD0_CRC_NONE;
+ }
+
+ sca_out(CMD_RESET, msci + CMD, card);
+ sca_out(md0, msci + MD0, card);
+ sca_out(0x00, msci + MD1, card); /* no address field check */
+ sca_out(md2, msci + MD2, card);
+ sca_out(0x7E, msci + IDL, card); /* flag character 0x7E */
+ /* Skip the rest of underrun frame */
+ sca_out(CTL_IDLE | CTL_URCT | CTL_URSKP, msci + CTL, card);
+ sca_out(0x0F, msci + RNR, card); /* +1=RX DMA activation condition */
+ sca_out(0x3C, msci + TFS, card); /* +1 = TX start */
+ sca_out(0x38, msci + TCR, card); /* =Critical TX DMA activ condition */
+ sca_out(0x38, msci + TNR0, card); /* =TX DMA activation condition */
+ sca_out(0x3F, msci + TNR1, card); /* +1=TX DMA deactivation condition*/
+
+/* We're using the following interrupts:
+ - RXINTA (DCD changes only)
+ - DMIB (EOM - single frame transfer complete)
+*/
+ sca_outl(IE0_RXINTA | IE0_CDCD, msci + IE0, card);
+
+ sca_out(port->tmc, msci + TMCR, card);
+ sca_out(port->tmc, msci + TMCT, card);
+ sca_out(port->rxs, msci + RXS, card);
+ sca_out(port->txs, msci + TXS, card);
+ sca_out(CMD_TX_ENABLE, msci + CMD, card);
+ sca_out(CMD_RX_ENABLE, msci + CMD, card);
+
+ sca_set_carrier(port);
+ enable_intr(port);
+ napi_enable(&port->napi);
+ netif_start_queue(dev);
+}
+
+
+static void sca_close(struct net_device *dev)
+{
+ port_t *port = dev_to_port(dev);
+
+ /* reset channel */
+ sca_out(CMD_RESET, get_msci(port) + CMD, port->card);
+ disable_intr(port);
+ napi_disable(&port->napi);
+ netif_stop_queue(dev);
+}
+
+
+static int sca_attach(struct net_device *dev, unsigned short encoding,
+ unsigned short parity)
+{
+ if (encoding != ENCODING_NRZ &&
+ encoding != ENCODING_NRZI &&
+ encoding != ENCODING_FM_MARK &&
+ encoding != ENCODING_FM_SPACE &&
+ encoding != ENCODING_MANCHESTER)
+ return -EINVAL;
+
+ if (parity != PARITY_NONE &&
+ parity != PARITY_CRC16_PR0 &&
+ parity != PARITY_CRC16_PR1 &&
+ parity != PARITY_CRC32_PR1_CCITT &&
+ parity != PARITY_CRC16_PR1_CCITT)
+ return -EINVAL;
+
+ dev_to_port(dev)->encoding = encoding;
+ dev_to_port(dev)->parity = parity;
+ return 0;
+}
+
+
+#ifdef DEBUG_RINGS
+static void sca_dump_rings(struct net_device *dev)
+{
+ port_t *port = dev_to_port(dev);
+ card_t *card = port->card;
+ u16 cnt;
+
+ printk(KERN_DEBUG "RX ring: CDA=%u EDA=%u DSR=%02X in=%u %sactive",
+ sca_inl(get_dmac_rx(port) + CDAL, card),
+ sca_inl(get_dmac_rx(port) + EDAL, card),
+ sca_in(DSR_RX(port->chan), card), port->rxin,
+ sca_in(DSR_RX(port->chan), card) & DSR_DE ? "" : "in");
+ for (cnt = 0; cnt < port->card->rx_ring_buffers; cnt++)
+ printk(" %02X", readb(&(desc_address(port, cnt, 0)->stat)));
+
+ printk("\n" KERN_DEBUG "TX ring: CDA=%u EDA=%u DSR=%02X in=%u "
+ "last=%u %sactive",
+ sca_inl(get_dmac_tx(port) + CDAL, card),
+ sca_inl(get_dmac_tx(port) + EDAL, card),
+ sca_in(DSR_TX(port->chan), card), port->txin, port->txlast,
+ sca_in(DSR_TX(port->chan), card) & DSR_DE ? "" : "in");
+
+ for (cnt = 0; cnt < port->card->tx_ring_buffers; cnt++)
+ printk(" %02X", readb(&(desc_address(port, cnt, 1)->stat)));
+ printk("\n");
+
+ printk(KERN_DEBUG "MSCI: MD: %02x %02x %02x,"
+ " ST: %02x %02x %02x %02x %02x, FST: %02x CST: %02x %02x\n",
+ sca_in(get_msci(port) + MD0, card),
+ sca_in(get_msci(port) + MD1, card),
+ sca_in(get_msci(port) + MD2, card),
+ sca_in(get_msci(port) + ST0, card),
+ sca_in(get_msci(port) + ST1, card),
+ sca_in(get_msci(port) + ST2, card),
+ sca_in(get_msci(port) + ST3, card),
+ sca_in(get_msci(port) + ST4, card),
+ sca_in(get_msci(port) + FST, card),
+ sca_in(get_msci(port) + CST0, card),
+ sca_in(get_msci(port) + CST1, card));
+
+ printk(KERN_DEBUG "ILAR: %02x ISR: %08x %08x\n", sca_in(ILAR, card),
+ sca_inl(ISR0, card), sca_inl(ISR1, card));
+}
+#endif /* DEBUG_RINGS */
+
+
+static int sca_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ port_t *port = dev_to_port(dev);
+ card_t *card = port->card;
+ pkt_desc __iomem *desc;
+ u32 buff, len;
+
+ spin_lock_irq(&port->lock);
+
+ desc = desc_address(port, port->txin + 1, 1);
+ BUG_ON(readb(&desc->stat)); /* previous xmit should stop queue */
+
+#ifdef DEBUG_PKT
+ printk(KERN_DEBUG "%s TX(%i):", dev->name, skb->len);
+ debug_frame(skb);
+#endif
+
+ desc = desc_address(port, port->txin, 1);
+ buff = buffer_offset(port, port->txin, 1);
+ len = skb->len;
+ memcpy_toio(card->rambase + buff, skb->data, len);
+
+ writew(len, &desc->len);
+ writeb(ST_TX_EOM, &desc->stat);
+ dev->trans_start = jiffies;
+
+ port->txin = (port->txin + 1) % card->tx_ring_buffers;
+ sca_outl(desc_offset(port, port->txin, 1),
+ get_dmac_tx(port) + EDAL, card);
+
+ sca_out(DSR_DE, DSR_TX(port->chan), card); /* Enable TX DMA */
+
+ desc = desc_address(port, port->txin + 1, 1);
+ if (readb(&desc->stat)) /* allow 1 packet gap */
+ netif_stop_queue(dev);
+
+ spin_unlock_irq(&port->lock);
+
+ dev_kfree_skb(skb);
+ return 0;
+}
+
+
+static u32 __devinit sca_detect_ram(card_t *card, u8 __iomem *rambase,
+ u32 ramsize)
+{
+ /* Round RAM size to 32 bits, fill from end to start */
+ u32 i = ramsize &= ~3;
+
+ do {
+ i -= 4;
+ writel(i ^ 0x12345678, rambase + i);
+ } while (i > 0);
+
+ for (i = 0; i < ramsize ; i += 4) {
+ if (readl(rambase + i) != (i ^ 0x12345678))
+ break;
+ }
+
+ return i;
+}
+
+
+static void __devinit sca_init(card_t *card, int wait_states)
+{
+ sca_out(wait_states, WCRL, card); /* Wait Control */
+ sca_out(wait_states, WCRM, card);
+ sca_out(wait_states, WCRH, card);
+
+ sca_out(0, DMER, card); /* DMA Master disable */
+ sca_out(0x03, PCR, card); /* DMA priority */
+ sca_out(0, DSR_RX(0), card); /* DMA disable - to halt state */
+ sca_out(0, DSR_TX(0), card);
+ sca_out(0, DSR_RX(1), card);
+ sca_out(0, DSR_TX(1), card);
+ sca_out(DMER_DME, DMER, card); /* DMA Master enable */
+}
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c
index d3d5055741ad..f1ddd7c3459c 100644
--- a/drivers/net/wan/hdlc_fr.c
+++ b/drivers/net/wan/hdlc_fr.c
@@ -342,7 +342,7 @@ static int fr_hard_header(struct sk_buff **skb_p, u16 dlci)
static int pvc_open(struct net_device *dev)
{
- pvc_device *pvc = dev->priv;
+ pvc_device *pvc = dev->ml_priv;
if ((pvc->frad->flags & IFF_UP) == 0)
return -EIO; /* Frad must be UP in order to activate PVC */
@@ -362,7 +362,7 @@ static int pvc_open(struct net_device *dev)
static int pvc_close(struct net_device *dev)
{
- pvc_device *pvc = dev->priv;
+ pvc_device *pvc = dev->ml_priv;
if (--pvc->open_count == 0) {
hdlc_device *hdlc = dev_to_hdlc(pvc->frad);
@@ -381,7 +381,7 @@ static int pvc_close(struct net_device *dev)
static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
- pvc_device *pvc = dev->priv;
+ pvc_device *pvc = dev->ml_priv;
fr_proto_pvc_info info;
if (ifr->ifr_settings.type == IF_GET_PROTO) {
@@ -409,7 +409,7 @@ static int pvc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
static int pvc_xmit(struct sk_buff *skb, struct net_device *dev)
{
- pvc_device *pvc = dev->priv;
+ pvc_device *pvc = dev->ml_priv;
if (pvc->state.active) {
if (dev->type == ARPHRD_ETHER) {
@@ -1111,7 +1111,7 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type)
dev->change_mtu = pvc_change_mtu;
dev->mtu = HDLC_MAX_MTU;
dev->tx_queue_len = 0;
- dev->priv = pvc;
+ dev->ml_priv = pvc;
result = dev_alloc_name(dev, dev->name);
if (result < 0) {
diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c
index 4efe9e6d32d5..57fe714c1c7f 100644
--- a/drivers/net/wan/hdlc_ppp.c
+++ b/drivers/net/wan/hdlc_ppp.c
@@ -2,7 +2,7 @@
* Generic HDLC support routines for Linux
* Point-to-point protocol support
*
- * Copyright (C) 1999 - 2006 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 1999 - 2008 Krzysztof Halasa <khc@pm.waw.pl>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
@@ -18,87 +18,633 @@
#include <linux/module.h>
#include <linux/pkt_sched.h>
#include <linux/poll.h>
-#include <linux/rtnetlink.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
-#include <net/syncppp.h>
+#include <linux/spinlock.h>
+
+#define DEBUG_CP 0 /* also bytes# to dump */
+#define DEBUG_STATE 0
+#define DEBUG_HARD_HEADER 0
+
+#define HDLC_ADDR_ALLSTATIONS 0xFF
+#define HDLC_CTRL_UI 0x03
+
+#define PID_LCP 0xC021
+#define PID_IP 0x0021
+#define PID_IPCP 0x8021
+#define PID_IPV6 0x0057
+#define PID_IPV6CP 0x8057
+
+enum {IDX_LCP = 0, IDX_IPCP, IDX_IPV6CP, IDX_COUNT};
+enum {CP_CONF_REQ = 1, CP_CONF_ACK, CP_CONF_NAK, CP_CONF_REJ, CP_TERM_REQ,
+ CP_TERM_ACK, CP_CODE_REJ, LCP_PROTO_REJ, LCP_ECHO_REQ, LCP_ECHO_REPLY,
+ LCP_DISC_REQ, CP_CODES};
+#if DEBUG_CP
+static const char *const code_names[CP_CODES] = {
+ "0", "ConfReq", "ConfAck", "ConfNak", "ConfRej", "TermReq",
+ "TermAck", "CodeRej", "ProtoRej", "EchoReq", "EchoReply", "Discard"
+};
+static char debug_buffer[64 + 3 * DEBUG_CP];
+#endif
+
+enum {LCP_OPTION_MRU = 1, LCP_OPTION_ACCM, LCP_OPTION_MAGIC = 5};
+
+struct hdlc_header {
+ u8 address;
+ u8 control;
+ __be16 protocol;
+};
+
+struct cp_header {
+ u8 code;
+ u8 id;
+ __be16 len;
+};
+
-struct ppp_state {
- struct ppp_device pppdev;
- struct ppp_device *syncppp_ptr;
- int (*old_change_mtu)(struct net_device *dev, int new_mtu);
+struct proto {
+ struct net_device *dev;
+ struct timer_list timer;
+ unsigned long timeout;
+ u16 pid; /* protocol ID */
+ u8 state;
+ u8 cr_id; /* ID of last Configuration-Request */
+ u8 restart_counter;
};
+struct ppp {
+ struct proto protos[IDX_COUNT];
+ spinlock_t lock;
+ unsigned long last_pong;
+ unsigned int req_timeout, cr_retries, term_retries;
+ unsigned int keepalive_interval, keepalive_timeout;
+ u8 seq; /* local sequence number for requests */
+ u8 echo_id; /* ID of last Echo-Request (LCP) */
+};
+
+enum {CLOSED = 0, STOPPED, STOPPING, REQ_SENT, ACK_RECV, ACK_SENT, OPENED,
+ STATES, STATE_MASK = 0xF};
+enum {START = 0, STOP, TO_GOOD, TO_BAD, RCR_GOOD, RCR_BAD, RCA, RCN, RTR, RTA,
+ RUC, RXJ_GOOD, RXJ_BAD, EVENTS};
+enum {INV = 0x10, IRC = 0x20, ZRC = 0x40, SCR = 0x80, SCA = 0x100,
+ SCN = 0x200, STR = 0x400, STA = 0x800, SCJ = 0x1000};
+
+#if DEBUG_STATE
+static const char *const state_names[STATES] = {
+ "Closed", "Stopped", "Stopping", "ReqSent", "AckRecv", "AckSent",
+ "Opened"
+};
+static const char *const event_names[EVENTS] = {
+ "Start", "Stop", "TO+", "TO-", "RCR+", "RCR-", "RCA", "RCN",
+ "RTR", "RTA", "RUC", "RXJ+", "RXJ-"
+};
+#endif
+
+static struct sk_buff_head tx_queue; /* used when holding the spin lock */
+
static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr);
+static inline struct ppp* get_ppp(struct net_device *dev)
+{
+ return (struct ppp *)dev_to_hdlc(dev)->state;
+}
-static inline struct ppp_state* state(hdlc_device *hdlc)
+static inline struct proto* get_proto(struct net_device *dev, u16 pid)
{
- return(struct ppp_state *)(hdlc->state);
+ struct ppp *ppp = get_ppp(dev);
+
+ switch (pid) {
+ case PID_LCP:
+ return &ppp->protos[IDX_LCP];
+ case PID_IPCP:
+ return &ppp->protos[IDX_IPCP];
+ case PID_IPV6CP:
+ return &ppp->protos[IDX_IPV6CP];
+ default:
+ return NULL;
+ }
}
+static inline const char* proto_name(u16 pid)
+{
+ switch (pid) {
+ case PID_LCP:
+ return "LCP";
+ case PID_IPCP:
+ return "IPCP";
+ case PID_IPV6CP:
+ return "IPV6CP";
+ default:
+ return NULL;
+ }
+}
-static int ppp_open(struct net_device *dev)
+static __be16 ppp_type_trans(struct sk_buff *skb, struct net_device *dev)
{
- hdlc_device *hdlc = dev_to_hdlc(dev);
- int (*old_ioctl)(struct net_device *, struct ifreq *, int);
- int result;
+ struct hdlc_header *data = (struct hdlc_header*)skb->data;
+
+ if (skb->len < sizeof(struct hdlc_header))
+ return htons(ETH_P_HDLC);
+ if (data->address != HDLC_ADDR_ALLSTATIONS ||
+ data->control != HDLC_CTRL_UI)
+ return htons(ETH_P_HDLC);
+
+ switch (data->protocol) {
+ case __constant_htons(PID_IP):
+ skb_pull(skb, sizeof(struct hdlc_header));
+ return htons(ETH_P_IP);
- dev->ml_priv = &state(hdlc)->syncppp_ptr;
- state(hdlc)->syncppp_ptr = &state(hdlc)->pppdev;
- state(hdlc)->pppdev.dev = dev;
+ case __constant_htons(PID_IPV6):
+ skb_pull(skb, sizeof(struct hdlc_header));
+ return htons(ETH_P_IPV6);
- old_ioctl = dev->do_ioctl;
- state(hdlc)->old_change_mtu = dev->change_mtu;
- sppp_attach(&state(hdlc)->pppdev);
- /* sppp_attach nukes them. We don't need syncppp's ioctl */
- dev->do_ioctl = old_ioctl;
- state(hdlc)->pppdev.sppp.pp_flags &= ~PP_CISCO;
- dev->type = ARPHRD_PPP;
- result = sppp_open(dev);
- if (result) {
- sppp_detach(dev);
- return result;
+ default:
+ return htons(ETH_P_HDLC);
}
+}
- return 0;
+
+static int ppp_hard_header(struct sk_buff *skb, struct net_device *dev,
+ u16 type, const void *daddr, const void *saddr,
+ unsigned int len)
+{
+ struct hdlc_header *data;
+#if DEBUG_HARD_HEADER
+ printk(KERN_DEBUG "%s: ppp_hard_header() called\n", dev->name);
+#endif
+
+ skb_push(skb, sizeof(struct hdlc_header));
+ data = (struct hdlc_header*)skb->data;
+
+ data->address = HDLC_ADDR_ALLSTATIONS;
+ data->control = HDLC_CTRL_UI;
+ switch (type) {
+ case ETH_P_IP:
+ data->protocol = htons(PID_IP);
+ break;
+ case ETH_P_IPV6:
+ data->protocol = htons(PID_IPV6);
+ break;
+ case PID_LCP:
+ case PID_IPCP:
+ case PID_IPV6CP:
+ data->protocol = htons(type);
+ break;
+ default: /* unknown protocol */
+ data->protocol = 0;
+ }
+ return sizeof(struct hdlc_header);
}
+static void ppp_tx_flush(void)
+{
+ struct sk_buff *skb;
+ while ((skb = skb_dequeue(&tx_queue)) != NULL)
+ dev_queue_xmit(skb);
+}
-static void ppp_close(struct net_device *dev)
+static void ppp_tx_cp(struct net_device *dev, u16 pid, u8 code,
+ u8 id, unsigned int len, const void *data)
{
- hdlc_device *hdlc = dev_to_hdlc(dev);
+ struct sk_buff *skb;
+ struct cp_header *cp;
+ unsigned int magic_len = 0;
+ static u32 magic;
+
+#if DEBUG_CP
+ int i;
+ char *ptr;
+#endif
+
+ if (pid == PID_LCP && (code == LCP_ECHO_REQ || code == LCP_ECHO_REPLY))
+ magic_len = sizeof(magic);
+
+ skb = dev_alloc_skb(sizeof(struct hdlc_header) +
+ sizeof(struct cp_header) + magic_len + len);
+ if (!skb) {
+ printk(KERN_WARNING "%s: out of memory in ppp_tx_cp()\n",
+ dev->name);
+ return;
+ }
+ skb_reserve(skb, sizeof(struct hdlc_header));
+
+ cp = (struct cp_header *)skb_put(skb, sizeof(struct cp_header));
+ cp->code = code;
+ cp->id = id;
+ cp->len = htons(sizeof(struct cp_header) + magic_len + len);
+
+ if (magic_len)
+ memcpy(skb_put(skb, magic_len), &magic, magic_len);
+ if (len)
+ memcpy(skb_put(skb, len), data, len);
+
+#if DEBUG_CP
+ BUG_ON(code >= CP_CODES);
+ ptr = debug_buffer;
+ *ptr = '\x0';
+ for (i = 0; i < min_t(unsigned int, magic_len + len, DEBUG_CP); i++) {
+ sprintf(ptr, " %02X", skb->data[sizeof(struct cp_header) + i]);
+ ptr += strlen(ptr);
+ }
+ printk(KERN_DEBUG "%s: TX %s [%s id 0x%X]%s\n", dev->name,
+ proto_name(pid), code_names[code], id, debug_buffer);
+#endif
- sppp_close(dev);
- sppp_detach(dev);
+ ppp_hard_header(skb, dev, pid, NULL, NULL, 0);
- dev->change_mtu = state(hdlc)->old_change_mtu;
- dev->mtu = HDLC_MAX_MTU;
- dev->hard_header_len = 16;
+ skb->priority = TC_PRIO_CONTROL;
+ skb->dev = dev;
+ skb_reset_network_header(skb);
+ skb_queue_tail(&tx_queue, skb);
}
+/* State transition table (compare STD-51)
+ Events Actions
+ TO+ = Timeout with counter > 0 irc = Initialize-Restart-Count
+ TO- = Timeout with counter expired zrc = Zero-Restart-Count
+
+ RCR+ = Receive-Configure-Request (Good) scr = Send-Configure-Request
+ RCR- = Receive-Configure-Request (Bad)
+ RCA = Receive-Configure-Ack sca = Send-Configure-Ack
+ RCN = Receive-Configure-Nak/Rej scn = Send-Configure-Nak/Rej
+
+ RTR = Receive-Terminate-Request str = Send-Terminate-Request
+ RTA = Receive-Terminate-Ack sta = Send-Terminate-Ack
+
+ RUC = Receive-Unknown-Code scj = Send-Code-Reject
+ RXJ+ = Receive-Code-Reject (permitted)
+ or Receive-Protocol-Reject
+ RXJ- = Receive-Code-Reject (catastrophic)
+ or Receive-Protocol-Reject
+*/
+static int cp_table[EVENTS][STATES] = {
+ /* CLOSED STOPPED STOPPING REQ_SENT ACK_RECV ACK_SENT OPENED
+ 0 1 2 3 4 5 6 */
+ {IRC|SCR|3, INV , INV , INV , INV , INV , INV }, /* START */
+ { INV , 0 , 0 , 0 , 0 , 0 , 0 }, /* STOP */
+ { INV , INV ,STR|2, SCR|3 ,SCR|3, SCR|5 , INV }, /* TO+ */
+ { INV , INV , 1 , 1 , 1 , 1 , INV }, /* TO- */
+ { STA|0 ,IRC|SCR|SCA|5, 2 , SCA|5 ,SCA|6, SCA|5 ,SCR|SCA|5}, /* RCR+ */
+ { STA|0 ,IRC|SCR|SCN|3, 2 , SCN|3 ,SCN|4, SCN|3 ,SCR|SCN|3}, /* RCR- */
+ { STA|0 , STA|1 , 2 , IRC|4 ,SCR|3, 6 , SCR|3 }, /* RCA */
+ { STA|0 , STA|1 , 2 ,IRC|SCR|3,SCR|3,IRC|SCR|5, SCR|3 }, /* RCN */
+ { STA|0 , STA|1 ,STA|2, STA|3 ,STA|3, STA|3 ,ZRC|STA|2}, /* RTR */
+ { 0 , 1 , 1 , 3 , 3 , 5 , SCR|3 }, /* RTA */
+ { SCJ|0 , SCJ|1 ,SCJ|2, SCJ|3 ,SCJ|4, SCJ|5 , SCJ|6 }, /* RUC */
+ { 0 , 1 , 2 , 3 , 3 , 5 , 6 }, /* RXJ+ */
+ { 0 , 1 , 1 , 1 , 1 , 1 ,IRC|STR|2}, /* RXJ- */
+};
+
-static __be16 ppp_type_trans(struct sk_buff *skb, struct net_device *dev)
+/* SCA: RCR+ must supply id, len and data
+ SCN: RCR- must supply code, id, len and data
+ STA: RTR must supply id
+ SCJ: RUC must supply CP packet len and data */
+static void ppp_cp_event(struct net_device *dev, u16 pid, u16 event, u8 code,
+ u8 id, unsigned int len, const void *data)
{
- return __constant_htons(ETH_P_WAN_PPP);
+ int old_state, action;
+ struct ppp *ppp = get_ppp(dev);
+ struct proto *proto = get_proto(dev, pid);
+
+ old_state = proto->state;
+ BUG_ON(old_state >= STATES);
+ BUG_ON(event >= EVENTS);
+
+#if DEBUG_STATE
+ printk(KERN_DEBUG "%s: %s ppp_cp_event(%s) %s ...\n", dev->name,
+ proto_name(pid), event_names[event], state_names[proto->state]);
+#endif
+
+ action = cp_table[event][old_state];
+
+ proto->state = action & STATE_MASK;
+ if (action & (SCR | STR)) /* set Configure-Req/Terminate-Req timer */
+ mod_timer(&proto->timer, proto->timeout =
+ jiffies + ppp->req_timeout * HZ);
+ if (action & ZRC)
+ proto->restart_counter = 0;
+ if (action & IRC)
+ proto->restart_counter = (proto->state == STOPPING) ?
+ ppp->term_retries : ppp->cr_retries;
+
+ if (action & SCR) /* send Configure-Request */
+ ppp_tx_cp(dev, pid, CP_CONF_REQ, proto->cr_id = ++ppp->seq,
+ 0, NULL);
+ if (action & SCA) /* send Configure-Ack */
+ ppp_tx_cp(dev, pid, CP_CONF_ACK, id, len, data);
+ if (action & SCN) /* send Configure-Nak/Reject */
+ ppp_tx_cp(dev, pid, code, id, len, data);
+ if (action & STR) /* send Terminate-Request */
+ ppp_tx_cp(dev, pid, CP_TERM_REQ, ++ppp->seq, 0, NULL);
+ if (action & STA) /* send Terminate-Ack */
+ ppp_tx_cp(dev, pid, CP_TERM_ACK, id, 0, NULL);
+ if (action & SCJ) /* send Code-Reject */
+ ppp_tx_cp(dev, pid, CP_CODE_REJ, ++ppp->seq, len, data);
+
+ if (old_state != OPENED && proto->state == OPENED) {
+ printk(KERN_INFO "%s: %s up\n", dev->name, proto_name(pid));
+ if (pid == PID_LCP) {
+ netif_dormant_off(dev);
+ ppp_cp_event(dev, PID_IPCP, START, 0, 0, 0, NULL);
+ ppp_cp_event(dev, PID_IPV6CP, START, 0, 0, 0, NULL);
+ ppp->last_pong = jiffies;
+ mod_timer(&proto->timer, proto->timeout =
+ jiffies + ppp->keepalive_interval * HZ);
+ }
+ }
+ if (old_state == OPENED && proto->state != OPENED) {
+ printk(KERN_INFO "%s: %s down\n", dev->name, proto_name(pid));
+ if (pid == PID_LCP) {
+ netif_dormant_on(dev);
+ ppp_cp_event(dev, PID_IPCP, STOP, 0, 0, 0, NULL);
+ ppp_cp_event(dev, PID_IPV6CP, STOP, 0, 0, 0, NULL);
+ }
+ }
+ if (old_state != CLOSED && proto->state == CLOSED)
+ del_timer(&proto->timer);
+
+#if DEBUG_STATE
+ printk(KERN_DEBUG "%s: %s ppp_cp_event(%s) ... %s\n", dev->name,
+ proto_name(pid), event_names[event], state_names[proto->state]);
+#endif
+}
+
+
+static void ppp_cp_parse_cr(struct net_device *dev, u16 pid, u8 id,
+ unsigned int req_len, const u8 *data)
+{
+ static u8 const valid_accm[6] = { LCP_OPTION_ACCM, 6, 0, 0, 0, 0 };
+ const u8 *opt;
+ u8 *out;
+ unsigned int len = req_len, nak_len = 0, rej_len = 0;
+
+ if (!(out = kmalloc(len, GFP_ATOMIC))) {
+ dev->stats.rx_dropped++;
+ return; /* out of memory, ignore CR packet */
+ }
+
+ for (opt = data; len; len -= opt[1], opt += opt[1]) {
+ if (len < 2 || len < opt[1]) {
+ dev->stats.rx_errors++;
+ return; /* bad packet, drop silently */
+ }
+
+ if (pid == PID_LCP)
+ switch (opt[0]) {
+ case LCP_OPTION_MRU:
+ continue; /* MRU always OK and > 1500 bytes? */
+
+ case LCP_OPTION_ACCM: /* async control character map */
+ if (!memcmp(opt, valid_accm,
+ sizeof(valid_accm)))
+ continue;
+ if (!rej_len) { /* NAK it */
+ memcpy(out + nak_len, valid_accm,
+ sizeof(valid_accm));
+ nak_len += sizeof(valid_accm);
+ continue;
+ }
+ break;
+ case LCP_OPTION_MAGIC:
+ if (opt[1] != 6 || (!opt[2] && !opt[3] &&
+ !opt[4] && !opt[5]))
+ break; /* reject invalid magic number */
+ continue;
+ }
+ /* reject this option */
+ memcpy(out + rej_len, opt, opt[1]);
+ rej_len += opt[1];
+ }
+
+ if (rej_len)
+ ppp_cp_event(dev, pid, RCR_BAD, CP_CONF_REJ, id, rej_len, out);
+ else if (nak_len)
+ ppp_cp_event(dev, pid, RCR_BAD, CP_CONF_NAK, id, nak_len, out);
+ else
+ ppp_cp_event(dev, pid, RCR_GOOD, CP_CONF_ACK, id, req_len, data);
+
+ kfree(out);
+}
+
+static int ppp_rx(struct sk_buff *skb)
+{
+ struct hdlc_header *hdr = (struct hdlc_header*)skb->data;
+ struct net_device *dev = skb->dev;
+ struct ppp *ppp = get_ppp(dev);
+ struct proto *proto;
+ struct cp_header *cp;
+ unsigned long flags;
+ unsigned int len;
+ u16 pid;
+#if DEBUG_CP
+ int i;
+ char *ptr;
+#endif
+
+ spin_lock_irqsave(&ppp->lock, flags);
+ /* Check HDLC header */
+ if (skb->len < sizeof(struct hdlc_header))
+ goto rx_error;
+ cp = (struct cp_header*)skb_pull(skb, sizeof(struct hdlc_header));
+ if (hdr->address != HDLC_ADDR_ALLSTATIONS ||
+ hdr->control != HDLC_CTRL_UI)
+ goto rx_error;
+
+ pid = ntohs(hdr->protocol);
+ proto = get_proto(dev, pid);
+ if (!proto) {
+ if (ppp->protos[IDX_LCP].state == OPENED)
+ ppp_tx_cp(dev, PID_LCP, LCP_PROTO_REJ,
+ ++ppp->seq, skb->len + 2, &hdr->protocol);
+ goto rx_error;
+ }
+
+ len = ntohs(cp->len);
+ if (len < sizeof(struct cp_header) /* no complete CP header? */ ||
+ skb->len < len /* truncated packet? */)
+ goto rx_error;
+ skb_pull(skb, sizeof(struct cp_header));
+ len -= sizeof(struct cp_header);
+
+ /* HDLC and CP headers stripped from skb */
+#if DEBUG_CP
+ if (cp->code < CP_CODES)
+ sprintf(debug_buffer, "[%s id 0x%X]", code_names[cp->code],
+ cp->id);
+ else
+ sprintf(debug_buffer, "[code %u id 0x%X]", cp->code, cp->id);
+ ptr = debug_buffer + strlen(debug_buffer);
+ for (i = 0; i < min_t(unsigned int, len, DEBUG_CP); i++) {
+ sprintf(ptr, " %02X", skb->data[i]);
+ ptr += strlen(ptr);
+ }
+ printk(KERN_DEBUG "%s: RX %s %s\n", dev->name, proto_name(pid),
+ debug_buffer);
+#endif
+
+ /* LCP only */
+ if (pid == PID_LCP)
+ switch (cp->code) {
+ case LCP_PROTO_REJ:
+ pid = ntohs(*(__be16*)skb->data);
+ if (pid == PID_LCP || pid == PID_IPCP ||
+ pid == PID_IPV6CP)
+ ppp_cp_event(dev, pid, RXJ_BAD, 0, 0,
+ 0, NULL);
+ goto out;
+
+ case LCP_ECHO_REQ: /* send Echo-Reply */
+ if (len >= 4 && proto->state == OPENED)
+ ppp_tx_cp(dev, PID_LCP, LCP_ECHO_REPLY,
+ cp->id, len - 4, skb->data + 4);
+ goto out;
+
+ case LCP_ECHO_REPLY:
+ if (cp->id == ppp->echo_id)
+ ppp->last_pong = jiffies;
+ goto out;
+
+ case LCP_DISC_REQ: /* discard */
+ goto out;
+ }
+
+ /* LCP, IPCP and IPV6CP */
+ switch (cp->code) {
+ case CP_CONF_REQ:
+ ppp_cp_parse_cr(dev, pid, cp->id, len, skb->data);
+ goto out;
+
+ case CP_CONF_ACK:
+ if (cp->id == proto->cr_id)
+ ppp_cp_event(dev, pid, RCA, 0, 0, 0, NULL);
+ goto out;
+
+ case CP_CONF_REJ:
+ case CP_CONF_NAK:
+ if (cp->id == proto->cr_id)
+ ppp_cp_event(dev, pid, RCN, 0, 0, 0, NULL);
+ goto out;
+
+ case CP_TERM_REQ:
+ ppp_cp_event(dev, pid, RTR, 0, cp->id, 0, NULL);
+ goto out;
+
+ case CP_TERM_ACK:
+ ppp_cp_event(dev, pid, RTA, 0, 0, 0, NULL);
+ goto out;
+
+ case CP_CODE_REJ:
+ ppp_cp_event(dev, pid, RXJ_BAD, 0, 0, 0, NULL);
+ goto out;
+
+ default:
+ len += sizeof(struct cp_header);
+ if (len > dev->mtu)
+ len = dev->mtu;
+ ppp_cp_event(dev, pid, RUC, 0, 0, len, cp);
+ goto out;
+ }
+ goto out;
+
+rx_error:
+ dev->stats.rx_errors++;
+out:
+ spin_unlock_irqrestore(&ppp->lock, flags);
+ dev_kfree_skb_any(skb);
+ ppp_tx_flush();
+ return NET_RX_DROP;
}
+static void ppp_timer(unsigned long arg)
+{
+ struct proto *proto = (struct proto *)arg;
+ struct ppp *ppp = get_ppp(proto->dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&ppp->lock, flags);
+ switch (proto->state) {
+ case STOPPING:
+ case REQ_SENT:
+ case ACK_RECV:
+ case ACK_SENT:
+ if (proto->restart_counter) {
+ ppp_cp_event(proto->dev, proto->pid, TO_GOOD, 0, 0,
+ 0, NULL);
+ proto->restart_counter--;
+ } else
+ ppp_cp_event(proto->dev, proto->pid, TO_BAD, 0, 0,
+ 0, NULL);
+ break;
+
+ case OPENED:
+ if (proto->pid != PID_LCP)
+ break;
+ if (time_after(jiffies, ppp->last_pong +
+ ppp->keepalive_timeout * HZ)) {
+ printk(KERN_INFO "%s: Link down\n", proto->dev->name);
+ ppp_cp_event(proto->dev, PID_LCP, STOP, 0, 0, 0, NULL);
+ ppp_cp_event(proto->dev, PID_LCP, START, 0, 0, 0, NULL);
+ } else { /* send keep-alive packet */
+ ppp->echo_id = ++ppp->seq;
+ ppp_tx_cp(proto->dev, PID_LCP, LCP_ECHO_REQ,
+ ppp->echo_id, 0, NULL);
+ proto->timer.expires = jiffies +
+ ppp->keepalive_interval * HZ;
+ add_timer(&proto->timer);
+ }
+ break;
+ }
+ spin_unlock_irqrestore(&ppp->lock, flags);
+ ppp_tx_flush();
+}
+
+
+static void ppp_start(struct net_device *dev)
+{
+ struct ppp *ppp = get_ppp(dev);
+ int i;
+
+ for (i = 0; i < IDX_COUNT; i++) {
+ struct proto *proto = &ppp->protos[i];
+ proto->dev = dev;
+ init_timer(&proto->timer);
+ proto->timer.function = ppp_timer;
+ proto->timer.data = (unsigned long)proto;
+ proto->state = CLOSED;
+ }
+ ppp->protos[IDX_LCP].pid = PID_LCP;
+ ppp->protos[IDX_IPCP].pid = PID_IPCP;
+ ppp->protos[IDX_IPV6CP].pid = PID_IPV6CP;
+
+ ppp_cp_event(dev, PID_LCP, START, 0, 0, 0, NULL);
+}
+
+static void ppp_stop(struct net_device *dev)
+{
+ ppp_cp_event(dev, PID_LCP, STOP, 0, 0, 0, NULL);
+}
static struct hdlc_proto proto = {
- .open = ppp_open,
- .close = ppp_close,
+ .start = ppp_start,
+ .stop = ppp_stop,
.type_trans = ppp_type_trans,
.ioctl = ppp_ioctl,
+ .netif_rx = ppp_rx,
.module = THIS_MODULE,
};
+static const struct header_ops ppp_header_ops = {
+ .create = ppp_hard_header,
+};
static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
+ struct ppp *ppp;
int result;
switch (ifr->ifr_settings.type) {
@@ -109,25 +655,35 @@ static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
return 0; /* return protocol only, no settable parameters */
case IF_PROTO_PPP:
- if(!capable(CAP_NET_ADMIN))
+ if (!capable(CAP_NET_ADMIN))
return -EPERM;
- if(dev->flags & IFF_UP)
+ if (dev->flags & IFF_UP)
return -EBUSY;
/* no settable parameters */
- result=hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
+ result = hdlc->attach(dev, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
if (result)
return result;
- result = attach_hdlc_protocol(dev, &proto,
- sizeof(struct ppp_state));
+ result = attach_hdlc_protocol(dev, &proto, sizeof(struct ppp));
if (result)
return result;
+
+ ppp = get_ppp(dev);
+ spin_lock_init(&ppp->lock);
+ ppp->req_timeout = 2;
+ ppp->cr_retries = 10;
+ ppp->term_retries = 2;
+ ppp->keepalive_interval = 10;
+ ppp->keepalive_timeout = 60;
+
dev->hard_start_xmit = hdlc->xmit;
+ dev->hard_header_len = sizeof(struct hdlc_header);
+ dev->header_ops = &ppp_header_ops;
dev->type = ARPHRD_PPP;
- netif_dormant_off(dev);
+ netif_dormant_on(dev);
return 0;
}
@@ -137,12 +693,11 @@ static int ppp_ioctl(struct net_device *dev, struct ifreq *ifr)
static int __init mod_init(void)
{
+ skb_queue_head_init(&tx_queue);
register_hdlc_protocol(&proto);
return 0;
}
-
-
static void __exit mod_exit(void)
{
unregister_hdlc_protocol(&proto);
diff --git a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c
index e299313f828a..af54f0cf1b35 100644
--- a/drivers/net/wan/hostess_sv11.c
+++ b/drivers/net/wan/hostess_sv11.c
@@ -66,7 +66,6 @@ static void hostess_input(struct z8530_channel *c, struct sk_buff *skb)
* it right now.
*/
netif_rx(skb);
- c->netdevice->last_rx = jiffies;
}
/*
diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c
new file mode 100644
index 000000000000..0c6802507a79
--- /dev/null
+++ b/drivers/net/wan/ixp4xx_hss.c
@@ -0,0 +1,1325 @@
+/*
+ * Intel IXP4xx HSS (synchronous serial port) driver for Linux
+ *
+ * Copyright (C) 2007-2008 Krzysztof Hałasa <khc@pm.waw.pl>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License
+ * as published by the Free Software Foundation.
+ */
+
+#include <linux/bitops.h>
+#include <linux/cdev.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/fs.h>
+#include <linux/hdlc.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/poll.h>
+#include <mach/npe.h>
+#include <mach/qmgr.h>
+
+#define DEBUG_DESC 0
+#define DEBUG_RX 0
+#define DEBUG_TX 0
+#define DEBUG_PKT_BYTES 0
+#define DEBUG_CLOSE 0
+
+#define DRV_NAME "ixp4xx_hss"
+
+#define PKT_EXTRA_FLAGS 0 /* orig 1 */
+#define PKT_NUM_PIPES 1 /* 1, 2 or 4 */
+#define PKT_PIPE_FIFO_SIZEW 4 /* total 4 dwords per HSS */
+
+#define RX_DESCS 16 /* also length of all RX queues */
+#define TX_DESCS 16 /* also length of all TX queues */
+
+#define POOL_ALLOC_SIZE (sizeof(struct desc) * (RX_DESCS + TX_DESCS))
+#define RX_SIZE (HDLC_MAX_MRU + 4) /* NPE needs more space */
+#define MAX_CLOSE_WAIT 1000 /* microseconds */
+#define HSS_COUNT 2
+#define FRAME_SIZE 256 /* doesn't matter at this point */
+#define FRAME_OFFSET 0
+#define MAX_CHANNELS (FRAME_SIZE / 8)
+
+#define NAPI_WEIGHT 16
+
+/* Queue IDs */
+#define HSS0_CHL_RXTRIG_QUEUE 12 /* orig size = 32 dwords */
+#define HSS0_PKT_RX_QUEUE 13 /* orig size = 32 dwords */
+#define HSS0_PKT_TX0_QUEUE 14 /* orig size = 16 dwords */
+#define HSS0_PKT_TX1_QUEUE 15
+#define HSS0_PKT_TX2_QUEUE 16
+#define HSS0_PKT_TX3_QUEUE 17
+#define HSS0_PKT_RXFREE0_QUEUE 18 /* orig size = 16 dwords */
+#define HSS0_PKT_RXFREE1_QUEUE 19
+#define HSS0_PKT_RXFREE2_QUEUE 20
+#define HSS0_PKT_RXFREE3_QUEUE 21
+#define HSS0_PKT_TXDONE_QUEUE 22 /* orig size = 64 dwords */
+
+#define HSS1_CHL_RXTRIG_QUEUE 10
+#define HSS1_PKT_RX_QUEUE 0
+#define HSS1_PKT_TX0_QUEUE 5
+#define HSS1_PKT_TX1_QUEUE 6
+#define HSS1_PKT_TX2_QUEUE 7
+#define HSS1_PKT_TX3_QUEUE 8
+#define HSS1_PKT_RXFREE0_QUEUE 1
+#define HSS1_PKT_RXFREE1_QUEUE 2
+#define HSS1_PKT_RXFREE2_QUEUE 3
+#define HSS1_PKT_RXFREE3_QUEUE 4
+#define HSS1_PKT_TXDONE_QUEUE 9
+
+#define NPE_PKT_MODE_HDLC 0
+#define NPE_PKT_MODE_RAW 1
+#define NPE_PKT_MODE_56KMODE 2
+#define NPE_PKT_MODE_56KENDIAN_MSB 4
+
+/* PKT_PIPE_HDLC_CFG_WRITE flags */
+#define PKT_HDLC_IDLE_ONES 0x1 /* default = flags */
+#define PKT_HDLC_CRC_32 0x2 /* default = CRC-16 */
+#define PKT_HDLC_MSB_ENDIAN 0x4 /* default = LE */
+
+
+/* hss_config, PCRs */
+/* Frame sync sampling, default = active low */
+#define PCR_FRM_SYNC_ACTIVE_HIGH 0x40000000
+#define PCR_FRM_SYNC_FALLINGEDGE 0x80000000
+#define PCR_FRM_SYNC_RISINGEDGE 0xC0000000
+
+/* Frame sync pin: input (default) or output generated off a given clk edge */
+#define PCR_FRM_SYNC_OUTPUT_FALLING 0x20000000
+#define PCR_FRM_SYNC_OUTPUT_RISING 0x30000000
+
+/* Frame and data clock sampling on edge, default = falling */
+#define PCR_FCLK_EDGE_RISING 0x08000000
+#define PCR_DCLK_EDGE_RISING 0x04000000
+
+/* Clock direction, default = input */
+#define PCR_SYNC_CLK_DIR_OUTPUT 0x02000000
+
+/* Generate/Receive frame pulses, default = enabled */
+#define PCR_FRM_PULSE_DISABLED 0x01000000
+
+ /* Data rate is full (default) or half the configured clk speed */
+#define PCR_HALF_CLK_RATE 0x00200000
+
+/* Invert data between NPE and HSS FIFOs? (default = no) */
+#define PCR_DATA_POLARITY_INVERT 0x00100000
+
+/* TX/RX endianness, default = LSB */
+#define PCR_MSB_ENDIAN 0x00080000
+
+/* Normal (default) / open drain mode (TX only) */
+#define PCR_TX_PINS_OPEN_DRAIN 0x00040000
+
+/* No framing bit transmitted and expected on RX? (default = framing bit) */
+#define PCR_SOF_NO_FBIT 0x00020000
+
+/* Drive data pins? */
+#define PCR_TX_DATA_ENABLE 0x00010000
+
+/* Voice 56k type: drive the data pins low (default), high, high Z */
+#define PCR_TX_V56K_HIGH 0x00002000
+#define PCR_TX_V56K_HIGH_IMP 0x00004000
+
+/* Unassigned type: drive the data pins low (default), high, high Z */
+#define PCR_TX_UNASS_HIGH 0x00000800
+#define PCR_TX_UNASS_HIGH_IMP 0x00001000
+
+/* T1 @ 1.544MHz only: Fbit dictated in FIFO (default) or high Z */
+#define PCR_TX_FB_HIGH_IMP 0x00000400
+
+/* 56k data endiannes - which bit unused: high (default) or low */
+#define PCR_TX_56KE_BIT_0_UNUSED 0x00000200
+
+/* 56k data transmission type: 32/8 bit data (default) or 56K data */
+#define PCR_TX_56KS_56K_DATA 0x00000100
+
+/* hss_config, cCR */
+/* Number of packetized clients, default = 1 */
+#define CCR_NPE_HFIFO_2_HDLC 0x04000000
+#define CCR_NPE_HFIFO_3_OR_4HDLC 0x08000000
+
+/* default = no loopback */
+#define CCR_LOOPBACK 0x02000000
+
+/* HSS number, default = 0 (first) */
+#define CCR_SECOND_HSS 0x01000000
+
+
+/* hss_config, clkCR: main:10, num:10, denom:12 */
+#define CLK42X_SPEED_EXP ((0x3FF << 22) | ( 2 << 12) | 15) /*65 KHz*/
+
+#define CLK42X_SPEED_512KHZ (( 130 << 22) | ( 2 << 12) | 15)
+#define CLK42X_SPEED_1536KHZ (( 43 << 22) | ( 18 << 12) | 47)
+#define CLK42X_SPEED_1544KHZ (( 43 << 22) | ( 33 << 12) | 192)
+#define CLK42X_SPEED_2048KHZ (( 32 << 22) | ( 34 << 12) | 63)
+#define CLK42X_SPEED_4096KHZ (( 16 << 22) | ( 34 << 12) | 127)
+#define CLK42X_SPEED_8192KHZ (( 8 << 22) | ( 34 << 12) | 255)
+
+#define CLK46X_SPEED_512KHZ (( 130 << 22) | ( 24 << 12) | 127)
+#define CLK46X_SPEED_1536KHZ (( 43 << 22) | (152 << 12) | 383)
+#define CLK46X_SPEED_1544KHZ (( 43 << 22) | ( 66 << 12) | 385)
+#define CLK46X_SPEED_2048KHZ (( 32 << 22) | (280 << 12) | 511)
+#define CLK46X_SPEED_4096KHZ (( 16 << 22) | (280 << 12) | 1023)
+#define CLK46X_SPEED_8192KHZ (( 8 << 22) | (280 << 12) | 2047)
+
+
+/* hss_config, LUT entries */
+#define TDMMAP_UNASSIGNED 0
+#define TDMMAP_HDLC 1 /* HDLC - packetized */
+#define TDMMAP_VOICE56K 2 /* Voice56K - 7-bit channelized */
+#define TDMMAP_VOICE64K 3 /* Voice64K - 8-bit channelized */
+
+/* offsets into HSS config */
+#define HSS_CONFIG_TX_PCR 0x00 /* port configuration registers */
+#define HSS_CONFIG_RX_PCR 0x04
+#define HSS_CONFIG_CORE_CR 0x08 /* loopback control, HSS# */
+#define HSS_CONFIG_CLOCK_CR 0x0C /* clock generator control */
+#define HSS_CONFIG_TX_FCR 0x10 /* frame configuration registers */
+#define HSS_CONFIG_RX_FCR 0x14
+#define HSS_CONFIG_TX_LUT 0x18 /* channel look-up tables */
+#define HSS_CONFIG_RX_LUT 0x38
+
+
+/* NPE command codes */
+/* writes the ConfigWord value to the location specified by offset */
+#define PORT_CONFIG_WRITE 0x40
+
+/* triggers the NPE to load the contents of the configuration table */
+#define PORT_CONFIG_LOAD 0x41
+
+/* triggers the NPE to return an HssErrorReadResponse message */
+#define PORT_ERROR_READ 0x42
+
+/* triggers the NPE to reset internal status and enable the HssPacketized
+ operation for the flow specified by pPipe */
+#define PKT_PIPE_FLOW_ENABLE 0x50
+#define PKT_PIPE_FLOW_DISABLE 0x51
+#define PKT_NUM_PIPES_WRITE 0x52
+#define PKT_PIPE_FIFO_SIZEW_WRITE 0x53
+#define PKT_PIPE_HDLC_CFG_WRITE 0x54
+#define PKT_PIPE_IDLE_PATTERN_WRITE 0x55
+#define PKT_PIPE_RX_SIZE_WRITE 0x56
+#define PKT_PIPE_MODE_WRITE 0x57
+
+/* HDLC packet status values - desc->status */
+#define ERR_SHUTDOWN 1 /* stop or shutdown occurrance */
+#define ERR_HDLC_ALIGN 2 /* HDLC alignment error */
+#define ERR_HDLC_FCS 3 /* HDLC Frame Check Sum error */
+#define ERR_RXFREE_Q_EMPTY 4 /* RX-free queue became empty while receiving
+ this packet (if buf_len < pkt_len) */
+#define ERR_HDLC_TOO_LONG 5 /* HDLC frame size too long */
+#define ERR_HDLC_ABORT 6 /* abort sequence received */
+#define ERR_DISCONNECTING 7 /* disconnect is in progress */
+
+
+#ifdef __ARMEB__
+typedef struct sk_buff buffer_t;
+#define free_buffer dev_kfree_skb
+#define free_buffer_irq dev_kfree_skb_irq
+#else
+typedef void buffer_t;
+#define free_buffer kfree
+#define free_buffer_irq kfree
+#endif
+
+struct port {
+ struct device *dev;
+ struct npe *npe;
+ struct net_device *netdev;
+ struct napi_struct napi;
+ struct hss_plat_info *plat;
+ buffer_t *rx_buff_tab[RX_DESCS], *tx_buff_tab[TX_DESCS];
+ struct desc *desc_tab; /* coherent */
+ u32 desc_tab_phys;
+ unsigned int id;
+ unsigned int clock_type, clock_rate, loopback;
+ unsigned int initialized, carrier;
+ u8 hdlc_cfg;
+};
+
+/* NPE message structure */
+struct msg {
+#ifdef __ARMEB__
+ u8 cmd, unused, hss_port, index;
+ union {
+ struct { u8 data8a, data8b, data8c, data8d; };
+ struct { u16 data16a, data16b; };
+ struct { u32 data32; };
+ };
+#else
+ u8 index, hss_port, unused, cmd;
+ union {
+ struct { u8 data8d, data8c, data8b, data8a; };
+ struct { u16 data16b, data16a; };
+ struct { u32 data32; };
+ };
+#endif
+};
+
+/* HDLC packet descriptor */
+struct desc {
+ u32 next; /* pointer to next buffer, unused */
+
+#ifdef __ARMEB__
+ u16 buf_len; /* buffer length */
+ u16 pkt_len; /* packet length */
+ u32 data; /* pointer to data buffer in RAM */
+ u8 status;
+ u8 error_count;
+ u16 __reserved;
+#else
+ u16 pkt_len; /* packet length */
+ u16 buf_len; /* buffer length */
+ u32 data; /* pointer to data buffer in RAM */
+ u16 __reserved;
+ u8 error_count;
+ u8 status;
+#endif
+ u32 __reserved1[4];
+};
+
+
+#define rx_desc_phys(port, n) ((port)->desc_tab_phys + \
+ (n) * sizeof(struct desc))
+#define rx_desc_ptr(port, n) (&(port)->desc_tab[n])
+
+#define tx_desc_phys(port, n) ((port)->desc_tab_phys + \
+ ((n) + RX_DESCS) * sizeof(struct desc))
+#define tx_desc_ptr(port, n) (&(port)->desc_tab[(n) + RX_DESCS])
+
+/*****************************************************************************
+ * global variables
+ ****************************************************************************/
+
+static int ports_open;
+static struct dma_pool *dma_pool;
+static spinlock_t npe_lock;
+
+static const struct {
+ int tx, txdone, rx, rxfree;
+}queue_ids[2] = {{HSS0_PKT_TX0_QUEUE, HSS0_PKT_TXDONE_QUEUE, HSS0_PKT_RX_QUEUE,
+ HSS0_PKT_RXFREE0_QUEUE},
+ {HSS1_PKT_TX0_QUEUE, HSS1_PKT_TXDONE_QUEUE, HSS1_PKT_RX_QUEUE,
+ HSS1_PKT_RXFREE0_QUEUE},
+};
+
+/*****************************************************************************
+ * utility functions
+ ****************************************************************************/
+
+static inline struct port* dev_to_port(struct net_device *dev)
+{
+ return dev_to_hdlc(dev)->priv;
+}
+
+#ifndef __ARMEB__
+static inline void memcpy_swab32(u32 *dest, u32 *src, int cnt)
+{
+ int i;
+ for (i = 0; i < cnt; i++)
+ dest[i] = swab32(src[i]);
+}
+#endif
+
+/*****************************************************************************
+ * HSS access
+ ****************************************************************************/
+
+static void hss_npe_send(struct port *port, struct msg *msg, const char* what)
+{
+ u32 *val = (u32*)msg;
+ if (npe_send_message(port->npe, msg, what)) {
+ printk(KERN_CRIT "HSS-%i: unable to send command [%08X:%08X]"
+ " to %s\n", port->id, val[0], val[1],
+ npe_name(port->npe));
+ BUG();
+ }
+}
+
+static void hss_config_set_lut(struct port *port)
+{
+ struct msg msg;
+ int ch;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.cmd = PORT_CONFIG_WRITE;
+ msg.hss_port = port->id;
+
+ for (ch = 0; ch < MAX_CHANNELS; ch++) {
+ msg.data32 >>= 2;
+ msg.data32 |= TDMMAP_HDLC << 30;
+
+ if (ch % 16 == 15) {
+ msg.index = HSS_CONFIG_TX_LUT + ((ch / 4) & ~3);
+ hss_npe_send(port, &msg, "HSS_SET_TX_LUT");
+
+ msg.index += HSS_CONFIG_RX_LUT - HSS_CONFIG_TX_LUT;
+ hss_npe_send(port, &msg, "HSS_SET_RX_LUT");
+ }
+ }
+}
+
+static void hss_config(struct port *port)
+{
+ struct msg msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.cmd = PORT_CONFIG_WRITE;
+ msg.hss_port = port->id;
+ msg.index = HSS_CONFIG_TX_PCR;
+ msg.data32 = PCR_FRM_SYNC_OUTPUT_RISING | PCR_MSB_ENDIAN |
+ PCR_TX_DATA_ENABLE | PCR_SOF_NO_FBIT;
+ if (port->clock_type == CLOCK_INT)
+ msg.data32 |= PCR_SYNC_CLK_DIR_OUTPUT;
+ hss_npe_send(port, &msg, "HSS_SET_TX_PCR");
+
+ msg.index = HSS_CONFIG_RX_PCR;
+ msg.data32 ^= PCR_TX_DATA_ENABLE | PCR_DCLK_EDGE_RISING;
+ hss_npe_send(port, &msg, "HSS_SET_RX_PCR");
+
+ memset(&msg, 0, sizeof(msg));
+ msg.cmd = PORT_CONFIG_WRITE;
+ msg.hss_port = port->id;
+ msg.index = HSS_CONFIG_CORE_CR;
+ msg.data32 = (port->loopback ? CCR_LOOPBACK : 0) |
+ (port->id ? CCR_SECOND_HSS : 0);
+ hss_npe_send(port, &msg, "HSS_SET_CORE_CR");
+
+ memset(&msg, 0, sizeof(msg));
+ msg.cmd = PORT_CONFIG_WRITE;
+ msg.hss_port = port->id;
+ msg.index = HSS_CONFIG_CLOCK_CR;
+ msg.data32 = CLK42X_SPEED_2048KHZ /* FIXME */;
+ hss_npe_send(port, &msg, "HSS_SET_CLOCK_CR");
+
+ memset(&msg, 0, sizeof(msg));
+ msg.cmd = PORT_CONFIG_WRITE;
+ msg.hss_port = port->id;
+ msg.index = HSS_CONFIG_TX_FCR;
+ msg.data16a = FRAME_OFFSET;
+ msg.data16b = FRAME_SIZE - 1;
+ hss_npe_send(port, &msg, "HSS_SET_TX_FCR");
+
+ memset(&msg, 0, sizeof(msg));
+ msg.cmd = PORT_CONFIG_WRITE;
+ msg.hss_port = port->id;
+ msg.index = HSS_CONFIG_RX_FCR;
+ msg.data16a = FRAME_OFFSET;
+ msg.data16b = FRAME_SIZE - 1;
+ hss_npe_send(port, &msg, "HSS_SET_RX_FCR");
+
+ hss_config_set_lut(port);
+
+ memset(&msg, 0, sizeof(msg));
+ msg.cmd = PORT_CONFIG_LOAD;
+ msg.hss_port = port->id;
+ hss_npe_send(port, &msg, "HSS_LOAD_CONFIG");
+
+ if (npe_recv_message(port->npe, &msg, "HSS_LOAD_CONFIG") ||
+ /* HSS_LOAD_CONFIG for port #1 returns port_id = #4 */
+ msg.cmd != PORT_CONFIG_LOAD || msg.data32) {
+ printk(KERN_CRIT "HSS-%i: HSS_LOAD_CONFIG failed\n",
+ port->id);
+ BUG();
+ }
+
+ /* HDLC may stop working without this - check FIXME */
+ npe_recv_message(port->npe, &msg, "FLUSH_IT");
+}
+
+static void hss_set_hdlc_cfg(struct port *port)
+{
+ struct msg msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.cmd = PKT_PIPE_HDLC_CFG_WRITE;
+ msg.hss_port = port->id;
+ msg.data8a = port->hdlc_cfg; /* rx_cfg */
+ msg.data8b = port->hdlc_cfg | (PKT_EXTRA_FLAGS << 3); /* tx_cfg */
+ hss_npe_send(port, &msg, "HSS_SET_HDLC_CFG");
+}
+
+static u32 hss_get_status(struct port *port)
+{
+ struct msg msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.cmd = PORT_ERROR_READ;
+ msg.hss_port = port->id;
+ hss_npe_send(port, &msg, "PORT_ERROR_READ");
+ if (npe_recv_message(port->npe, &msg, "PORT_ERROR_READ")) {
+ printk(KERN_CRIT "HSS-%i: unable to read HSS status\n",
+ port->id);
+ BUG();
+ }
+
+ return msg.data32;
+}
+
+static void hss_start_hdlc(struct port *port)
+{
+ struct msg msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.cmd = PKT_PIPE_FLOW_ENABLE;
+ msg.hss_port = port->id;
+ msg.data32 = 0;
+ hss_npe_send(port, &msg, "HSS_ENABLE_PKT_PIPE");
+}
+
+static void hss_stop_hdlc(struct port *port)
+{
+ struct msg msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.cmd = PKT_PIPE_FLOW_DISABLE;
+ msg.hss_port = port->id;
+ hss_npe_send(port, &msg, "HSS_DISABLE_PKT_PIPE");
+ hss_get_status(port); /* make sure it's halted */
+}
+
+static int hss_load_firmware(struct port *port)
+{
+ struct msg msg;
+ int err;
+
+ if (port->initialized)
+ return 0;
+
+ if (!npe_running(port->npe) &&
+ (err = npe_load_firmware(port->npe, npe_name(port->npe),
+ port->dev)))
+ return err;
+
+ /* HDLC mode configuration */
+ memset(&msg, 0, sizeof(msg));
+ msg.cmd = PKT_NUM_PIPES_WRITE;
+ msg.hss_port = port->id;
+ msg.data8a = PKT_NUM_PIPES;
+ hss_npe_send(port, &msg, "HSS_SET_PKT_PIPES");
+
+ msg.cmd = PKT_PIPE_FIFO_SIZEW_WRITE;
+ msg.data8a = PKT_PIPE_FIFO_SIZEW;
+ hss_npe_send(port, &msg, "HSS_SET_PKT_FIFO");
+
+ msg.cmd = PKT_PIPE_MODE_WRITE;
+ msg.data8a = NPE_PKT_MODE_HDLC;
+ /* msg.data8b = inv_mask */
+ /* msg.data8c = or_mask */
+ hss_npe_send(port, &msg, "HSS_SET_PKT_MODE");
+
+ msg.cmd = PKT_PIPE_RX_SIZE_WRITE;
+ msg.data16a = HDLC_MAX_MRU; /* including CRC */
+ hss_npe_send(port, &msg, "HSS_SET_PKT_RX_SIZE");
+
+ msg.cmd = PKT_PIPE_IDLE_PATTERN_WRITE;
+ msg.data32 = 0x7F7F7F7F; /* ??? FIXME */
+ hss_npe_send(port, &msg, "HSS_SET_PKT_IDLE");
+
+ port->initialized = 1;
+ return 0;
+}
+
+/*****************************************************************************
+ * packetized (HDLC) operation
+ ****************************************************************************/
+
+static inline void debug_pkt(struct net_device *dev, const char *func,
+ u8 *data, int len)
+{
+#if DEBUG_PKT_BYTES
+ int i;
+
+ printk(KERN_DEBUG "%s: %s(%i)", dev->name, func, len);
+ for (i = 0; i < len; i++) {
+ if (i >= DEBUG_PKT_BYTES)
+ break;
+ printk("%s%02X", !(i % 4) ? " " : "", data[i]);
+ }
+ printk("\n");
+#endif
+}
+
+
+static inline void debug_desc(u32 phys, struct desc *desc)
+{
+#if DEBUG_DESC
+ printk(KERN_DEBUG "%X: %X %3X %3X %08X %X %X\n",
+ phys, desc->next, desc->buf_len, desc->pkt_len,
+ desc->data, desc->status, desc->error_count);
+#endif
+}
+
+static inline int queue_get_desc(unsigned int queue, struct port *port,
+ int is_tx)
+{
+ u32 phys, tab_phys, n_desc;
+ struct desc *tab;
+
+ if (!(phys = qmgr_get_entry(queue)))
+ return -1;
+
+ BUG_ON(phys & 0x1F);
+ tab_phys = is_tx ? tx_desc_phys(port, 0) : rx_desc_phys(port, 0);
+ tab = is_tx ? tx_desc_ptr(port, 0) : rx_desc_ptr(port, 0);
+ n_desc = (phys - tab_phys) / sizeof(struct desc);
+ BUG_ON(n_desc >= (is_tx ? TX_DESCS : RX_DESCS));
+ debug_desc(phys, &tab[n_desc]);
+ BUG_ON(tab[n_desc].next);
+ return n_desc;
+}
+
+static inline void queue_put_desc(unsigned int queue, u32 phys,
+ struct desc *desc)
+{
+ debug_desc(phys, desc);
+ BUG_ON(phys & 0x1F);
+ qmgr_put_entry(queue, phys);
+ BUG_ON(qmgr_stat_overflow(queue));
+}
+
+
+static inline void dma_unmap_tx(struct port *port, struct desc *desc)
+{
+#ifdef __ARMEB__
+ dma_unmap_single(&port->netdev->dev, desc->data,
+ desc->buf_len, DMA_TO_DEVICE);
+#else
+ dma_unmap_single(&port->netdev->dev, desc->data & ~3,
+ ALIGN((desc->data & 3) + desc->buf_len, 4),
+ DMA_TO_DEVICE);
+#endif
+}
+
+
+static void hss_hdlc_set_carrier(void *pdev, int carrier)
+{
+ struct net_device *netdev = pdev;
+ struct port *port = dev_to_port(netdev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&npe_lock, flags);
+ port->carrier = carrier;
+ if (!port->loopback) {
+ if (carrier)
+ netif_carrier_on(netdev);
+ else
+ netif_carrier_off(netdev);
+ }
+ spin_unlock_irqrestore(&npe_lock, flags);
+}
+
+static void hss_hdlc_rx_irq(void *pdev)
+{
+ struct net_device *dev = pdev;
+ struct port *port = dev_to_port(dev);
+
+#if DEBUG_RX
+ printk(KERN_DEBUG "%s: hss_hdlc_rx_irq\n", dev->name);
+#endif
+ qmgr_disable_irq(queue_ids[port->id].rx);
+ netif_rx_schedule(dev, &port->napi);
+}
+
+static int hss_hdlc_poll(struct napi_struct *napi, int budget)
+{
+ struct port *port = container_of(napi, struct port, napi);
+ struct net_device *dev = port->netdev;
+ unsigned int rxq = queue_ids[port->id].rx;
+ unsigned int rxfreeq = queue_ids[port->id].rxfree;
+ int received = 0;
+
+#if DEBUG_RX
+ printk(KERN_DEBUG "%s: hss_hdlc_poll\n", dev->name);
+#endif
+
+ while (received < budget) {
+ struct sk_buff *skb;
+ struct desc *desc;
+ int n;
+#ifdef __ARMEB__
+ struct sk_buff *temp;
+ u32 phys;
+#endif
+
+ if ((n = queue_get_desc(rxq, port, 0)) < 0) {
+#if DEBUG_RX
+ printk(KERN_DEBUG "%s: hss_hdlc_poll"
+ " netif_rx_complete\n", dev->name);
+#endif
+ netif_rx_complete(dev, napi);
+ qmgr_enable_irq(rxq);
+ if (!qmgr_stat_empty(rxq) &&
+ netif_rx_reschedule(dev, napi)) {
+#if DEBUG_RX
+ printk(KERN_DEBUG "%s: hss_hdlc_poll"
+ " netif_rx_reschedule succeeded\n",
+ dev->name);
+#endif
+ qmgr_disable_irq(rxq);
+ continue;
+ }
+#if DEBUG_RX
+ printk(KERN_DEBUG "%s: hss_hdlc_poll all done\n",
+ dev->name);
+#endif
+ return received; /* all work done */
+ }
+
+ desc = rx_desc_ptr(port, n);
+#if 0 /* FIXME - error_count counts modulo 256, perhaps we should use it */
+ if (desc->error_count)
+ printk(KERN_DEBUG "%s: hss_hdlc_poll status 0x%02X"
+ " errors %u\n", dev->name, desc->status,
+ desc->error_count);
+#endif
+ skb = NULL;
+ switch (desc->status) {
+ case 0:
+#ifdef __ARMEB__
+ if ((skb = netdev_alloc_skb(dev, RX_SIZE)) != NULL) {
+ phys = dma_map_single(&dev->dev, skb->data,
+ RX_SIZE,
+ DMA_FROM_DEVICE);
+ if (dma_mapping_error(&dev->dev, phys)) {
+ dev_kfree_skb(skb);
+ skb = NULL;
+ }
+ }
+#else
+ skb = netdev_alloc_skb(dev, desc->pkt_len);
+#endif
+ if (!skb)
+ dev->stats.rx_dropped++;
+ break;
+ case ERR_HDLC_ALIGN:
+ case ERR_HDLC_ABORT:
+ dev->stats.rx_frame_errors++;
+ dev->stats.rx_errors++;
+ break;
+ case ERR_HDLC_FCS:
+ dev->stats.rx_crc_errors++;
+ dev->stats.rx_errors++;
+ break;
+ case ERR_HDLC_TOO_LONG:
+ dev->stats.rx_length_errors++;
+ dev->stats.rx_errors++;
+ break;
+ default: /* FIXME - remove printk */
+ printk(KERN_ERR "%s: hss_hdlc_poll: status 0x%02X"
+ " errors %u\n", dev->name, desc->status,
+ desc->error_count);
+ dev->stats.rx_errors++;
+ }
+
+ if (!skb) {
+ /* put the desc back on RX-ready queue */
+ desc->buf_len = RX_SIZE;
+ desc->pkt_len = desc->status = 0;
+ queue_put_desc(rxfreeq, rx_desc_phys(port, n), desc);
+ continue;
+ }
+
+ /* process received frame */
+#ifdef __ARMEB__
+ temp = skb;
+ skb = port->rx_buff_tab[n];
+ dma_unmap_single(&dev->dev, desc->data,
+ RX_SIZE, DMA_FROM_DEVICE);
+#else
+ dma_sync_single(&dev->dev, desc->data,
+ RX_SIZE, DMA_FROM_DEVICE);
+ memcpy_swab32((u32 *)skb->data, (u32 *)port->rx_buff_tab[n],
+ ALIGN(desc->pkt_len, 4) / 4);
+#endif
+ skb_put(skb, desc->pkt_len);
+
+ debug_pkt(dev, "hss_hdlc_poll", skb->data, skb->len);
+
+ skb->protocol = hdlc_type_trans(skb, dev);
+ dev->stats.rx_packets++;
+ dev->stats.rx_bytes += skb->len;
+ netif_receive_skb(skb);
+
+ /* put the new buffer on RX-free queue */
+#ifdef __ARMEB__
+ port->rx_buff_tab[n] = temp;
+ desc->data = phys;
+#endif
+ desc->buf_len = RX_SIZE;
+ desc->pkt_len = 0;
+ queue_put_desc(rxfreeq, rx_desc_phys(port, n), desc);
+ received++;
+ }
+#if DEBUG_RX
+ printk(KERN_DEBUG "hss_hdlc_poll: end, not all work done\n");
+#endif
+ return received; /* not all work done */
+}
+
+
+static void hss_hdlc_txdone_irq(void *pdev)
+{
+ struct net_device *dev = pdev;
+ struct port *port = dev_to_port(dev);
+ int n_desc;
+
+#if DEBUG_TX
+ printk(KERN_DEBUG DRV_NAME ": hss_hdlc_txdone_irq\n");
+#endif
+ while ((n_desc = queue_get_desc(queue_ids[port->id].txdone,
+ port, 1)) >= 0) {
+ struct desc *desc;
+ int start;
+
+ desc = tx_desc_ptr(port, n_desc);
+
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += desc->pkt_len;
+
+ dma_unmap_tx(port, desc);
+#if DEBUG_TX
+ printk(KERN_DEBUG "%s: hss_hdlc_txdone_irq free %p\n",
+ dev->name, port->tx_buff_tab[n_desc]);
+#endif
+ free_buffer_irq(port->tx_buff_tab[n_desc]);
+ port->tx_buff_tab[n_desc] = NULL;
+
+ start = qmgr_stat_empty(port->plat->txreadyq);
+ queue_put_desc(port->plat->txreadyq,
+ tx_desc_phys(port, n_desc), desc);
+ if (start) {
+#if DEBUG_TX
+ printk(KERN_DEBUG "%s: hss_hdlc_txdone_irq xmit"
+ " ready\n", dev->name);
+#endif
+ netif_wake_queue(dev);
+ }
+ }
+}
+
+static int hss_hdlc_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct port *port = dev_to_port(dev);
+ unsigned int txreadyq = port->plat->txreadyq;
+ int len, offset, bytes, n;
+ void *mem;
+ u32 phys;
+ struct desc *desc;
+
+#if DEBUG_TX
+ printk(KERN_DEBUG "%s: hss_hdlc_xmit\n", dev->name);
+#endif
+
+ if (unlikely(skb->len > HDLC_MAX_MRU)) {
+ dev_kfree_skb(skb);
+ dev->stats.tx_errors++;
+ return NETDEV_TX_OK;
+ }
+
+ debug_pkt(dev, "hss_hdlc_xmit", skb->data, skb->len);
+
+ len = skb->len;
+#ifdef __ARMEB__
+ offset = 0; /* no need to keep alignment */
+ bytes = len;
+ mem = skb->data;
+#else
+ offset = (int)skb->data & 3; /* keep 32-bit alignment */
+ bytes = ALIGN(offset + len, 4);
+ if (!(mem = kmalloc(bytes, GFP_ATOMIC))) {
+ dev_kfree_skb(skb);
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
+ }
+ memcpy_swab32(mem, (u32 *)((int)skb->data & ~3), bytes / 4);
+ dev_kfree_skb(skb);
+#endif
+
+ phys = dma_map_single(&dev->dev, mem, bytes, DMA_TO_DEVICE);
+ if (dma_mapping_error(&dev->dev, phys)) {
+#ifdef __ARMEB__
+ dev_kfree_skb(skb);
+#else
+ kfree(mem);
+#endif
+ dev->stats.tx_dropped++;
+ return NETDEV_TX_OK;
+ }
+
+ n = queue_get_desc(txreadyq, port, 1);
+ BUG_ON(n < 0);
+ desc = tx_desc_ptr(port, n);
+
+#ifdef __ARMEB__
+ port->tx_buff_tab[n] = skb;
+#else
+ port->tx_buff_tab[n] = mem;
+#endif
+ desc->data = phys + offset;
+ desc->buf_len = desc->pkt_len = len;
+
+ wmb();
+ queue_put_desc(queue_ids[port->id].tx, tx_desc_phys(port, n), desc);
+ dev->trans_start = jiffies;
+
+ if (qmgr_stat_empty(txreadyq)) {
+#if DEBUG_TX
+ printk(KERN_DEBUG "%s: hss_hdlc_xmit queue full\n", dev->name);
+#endif
+ netif_stop_queue(dev);
+ /* we could miss TX ready interrupt */
+ if (!qmgr_stat_empty(txreadyq)) {
+#if DEBUG_TX
+ printk(KERN_DEBUG "%s: hss_hdlc_xmit ready again\n",
+ dev->name);
+#endif
+ netif_wake_queue(dev);
+ }
+ }
+
+#if DEBUG_TX
+ printk(KERN_DEBUG "%s: hss_hdlc_xmit end\n", dev->name);
+#endif
+ return NETDEV_TX_OK;
+}
+
+
+static int request_hdlc_queues(struct port *port)
+{
+ int err;
+
+ err = qmgr_request_queue(queue_ids[port->id].rxfree, RX_DESCS, 0, 0,
+ "%s:RX-free", port->netdev->name);
+ if (err)
+ return err;
+
+ err = qmgr_request_queue(queue_ids[port->id].rx, RX_DESCS, 0, 0,
+ "%s:RX", port->netdev->name);
+ if (err)
+ goto rel_rxfree;
+
+ err = qmgr_request_queue(queue_ids[port->id].tx, TX_DESCS, 0, 0,
+ "%s:TX", port->netdev->name);
+ if (err)
+ goto rel_rx;
+
+ err = qmgr_request_queue(port->plat->txreadyq, TX_DESCS, 0, 0,
+ "%s:TX-ready", port->netdev->name);
+ if (err)
+ goto rel_tx;
+
+ err = qmgr_request_queue(queue_ids[port->id].txdone, TX_DESCS, 0, 0,
+ "%s:TX-done", port->netdev->name);
+ if (err)
+ goto rel_txready;
+ return 0;
+
+rel_txready:
+ qmgr_release_queue(port->plat->txreadyq);
+rel_tx:
+ qmgr_release_queue(queue_ids[port->id].tx);
+rel_rx:
+ qmgr_release_queue(queue_ids[port->id].rx);
+rel_rxfree:
+ qmgr_release_queue(queue_ids[port->id].rxfree);
+ printk(KERN_DEBUG "%s: unable to request hardware queues\n",
+ port->netdev->name);
+ return err;
+}
+
+static void release_hdlc_queues(struct port *port)
+{
+ qmgr_release_queue(queue_ids[port->id].rxfree);
+ qmgr_release_queue(queue_ids[port->id].rx);
+ qmgr_release_queue(queue_ids[port->id].txdone);
+ qmgr_release_queue(queue_ids[port->id].tx);
+ qmgr_release_queue(port->plat->txreadyq);
+}
+
+static int init_hdlc_queues(struct port *port)
+{
+ int i;
+
+ if (!ports_open)
+ if (!(dma_pool = dma_pool_create(DRV_NAME, NULL,
+ POOL_ALLOC_SIZE, 32, 0)))
+ return -ENOMEM;
+
+ if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL,
+ &port->desc_tab_phys)))
+ return -ENOMEM;
+ memset(port->desc_tab, 0, POOL_ALLOC_SIZE);
+ memset(port->rx_buff_tab, 0, sizeof(port->rx_buff_tab)); /* tables */
+ memset(port->tx_buff_tab, 0, sizeof(port->tx_buff_tab));
+
+ /* Setup RX buffers */
+ for (i = 0; i < RX_DESCS; i++) {
+ struct desc *desc = rx_desc_ptr(port, i);
+ buffer_t *buff;
+ void *data;
+#ifdef __ARMEB__
+ if (!(buff = netdev_alloc_skb(port->netdev, RX_SIZE)))
+ return -ENOMEM;
+ data = buff->data;
+#else
+ if (!(buff = kmalloc(RX_SIZE, GFP_KERNEL)))
+ return -ENOMEM;
+ data = buff;
+#endif
+ desc->buf_len = RX_SIZE;
+ desc->data = dma_map_single(&port->netdev->dev, data,
+ RX_SIZE, DMA_FROM_DEVICE);
+ if (dma_mapping_error(&port->netdev->dev, desc->data)) {
+ free_buffer(buff);
+ return -EIO;
+ }
+ port->rx_buff_tab[i] = buff;
+ }
+
+ return 0;
+}
+
+static void destroy_hdlc_queues(struct port *port)
+{
+ int i;
+
+ if (port->desc_tab) {
+ for (i = 0; i < RX_DESCS; i++) {
+ struct desc *desc = rx_desc_ptr(port, i);
+ buffer_t *buff = port->rx_buff_tab[i];
+ if (buff) {
+ dma_unmap_single(&port->netdev->dev,
+ desc->data, RX_SIZE,
+ DMA_FROM_DEVICE);
+ free_buffer(buff);
+ }
+ }
+ for (i = 0; i < TX_DESCS; i++) {
+ struct desc *desc = tx_desc_ptr(port, i);
+ buffer_t *buff = port->tx_buff_tab[i];
+ if (buff) {
+ dma_unmap_tx(port, desc);
+ free_buffer(buff);
+ }
+ }
+ dma_pool_free(dma_pool, port->desc_tab, port->desc_tab_phys);
+ port->desc_tab = NULL;
+ }
+
+ if (!ports_open && dma_pool) {
+ dma_pool_destroy(dma_pool);
+ dma_pool = NULL;
+ }
+}
+
+static int hss_hdlc_open(struct net_device *dev)
+{
+ struct port *port = dev_to_port(dev);
+ unsigned long flags;
+ int i, err = 0;
+
+ if ((err = hdlc_open(dev)))
+ return err;
+
+ if ((err = hss_load_firmware(port)))
+ goto err_hdlc_close;
+
+ if ((err = request_hdlc_queues(port)))
+ goto err_hdlc_close;
+
+ if ((err = init_hdlc_queues(port)))
+ goto err_destroy_queues;
+
+ spin_lock_irqsave(&npe_lock, flags);
+ if (port->plat->open)
+ if ((err = port->plat->open(port->id, dev,
+ hss_hdlc_set_carrier)))
+ goto err_unlock;
+ spin_unlock_irqrestore(&npe_lock, flags);
+
+ /* Populate queues with buffers, no failure after this point */
+ for (i = 0; i < TX_DESCS; i++)
+ queue_put_desc(port->plat->txreadyq,
+ tx_desc_phys(port, i), tx_desc_ptr(port, i));
+
+ for (i = 0; i < RX_DESCS; i++)
+ queue_put_desc(queue_ids[port->id].rxfree,
+ rx_desc_phys(port, i), rx_desc_ptr(port, i));
+
+ napi_enable(&port->napi);
+ netif_start_queue(dev);
+
+ qmgr_set_irq(queue_ids[port->id].rx, QUEUE_IRQ_SRC_NOT_EMPTY,
+ hss_hdlc_rx_irq, dev);
+
+ qmgr_set_irq(queue_ids[port->id].txdone, QUEUE_IRQ_SRC_NOT_EMPTY,
+ hss_hdlc_txdone_irq, dev);
+ qmgr_enable_irq(queue_ids[port->id].txdone);
+
+ ports_open++;
+
+ hss_set_hdlc_cfg(port);
+ hss_config(port);
+
+ hss_start_hdlc(port);
+
+ /* we may already have RX data, enables IRQ */
+ netif_rx_schedule(dev, &port->napi);
+ return 0;
+
+err_unlock:
+ spin_unlock_irqrestore(&npe_lock, flags);
+err_destroy_queues:
+ destroy_hdlc_queues(port);
+ release_hdlc_queues(port);
+err_hdlc_close:
+ hdlc_close(dev);
+ return err;
+}
+
+static int hss_hdlc_close(struct net_device *dev)
+{
+ struct port *port = dev_to_port(dev);
+ unsigned long flags;
+ int i, buffs = RX_DESCS; /* allocated RX buffers */
+
+ spin_lock_irqsave(&npe_lock, flags);
+ ports_open--;
+ qmgr_disable_irq(queue_ids[port->id].rx);
+ netif_stop_queue(dev);
+ napi_disable(&port->napi);
+
+ hss_stop_hdlc(port);
+
+ while (queue_get_desc(queue_ids[port->id].rxfree, port, 0) >= 0)
+ buffs--;
+ while (queue_get_desc(queue_ids[port->id].rx, port, 0) >= 0)
+ buffs--;
+
+ if (buffs)
+ printk(KERN_CRIT "%s: unable to drain RX queue, %i buffer(s)"
+ " left in NPE\n", dev->name, buffs);
+
+ buffs = TX_DESCS;
+ while (queue_get_desc(queue_ids[port->id].tx, port, 1) >= 0)
+ buffs--; /* cancel TX */
+
+ i = 0;
+ do {
+ while (queue_get_desc(port->plat->txreadyq, port, 1) >= 0)
+ buffs--;
+ if (!buffs)
+ break;
+ } while (++i < MAX_CLOSE_WAIT);
+
+ if (buffs)
+ printk(KERN_CRIT "%s: unable to drain TX queue, %i buffer(s) "
+ "left in NPE\n", dev->name, buffs);
+#if DEBUG_CLOSE
+ if (!buffs)
+ printk(KERN_DEBUG "Draining TX queues took %i cycles\n", i);
+#endif
+ qmgr_disable_irq(queue_ids[port->id].txdone);
+
+ if (port->plat->close)
+ port->plat->close(port->id, dev);
+ spin_unlock_irqrestore(&npe_lock, flags);
+
+ destroy_hdlc_queues(port);
+ release_hdlc_queues(port);
+ hdlc_close(dev);
+ return 0;
+}
+
+
+static int hss_hdlc_attach(struct net_device *dev, unsigned short encoding,
+ unsigned short parity)
+{
+ struct port *port = dev_to_port(dev);
+
+ if (encoding != ENCODING_NRZ)
+ return -EINVAL;
+
+ switch(parity) {
+ case PARITY_CRC16_PR1_CCITT:
+ port->hdlc_cfg = 0;
+ return 0;
+
+ case PARITY_CRC32_PR1_CCITT:
+ port->hdlc_cfg = PKT_HDLC_CRC_32;
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+
+static int hss_hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ const size_t size = sizeof(sync_serial_settings);
+ sync_serial_settings new_line;
+ sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
+ struct port *port = dev_to_port(dev);
+ unsigned long flags;
+ int clk;
+
+ if (cmd != SIOCWANDEV)
+ return hdlc_ioctl(dev, ifr, cmd);
+
+ switch(ifr->ifr_settings.type) {
+ case IF_GET_IFACE:
+ ifr->ifr_settings.type = IF_IFACE_V35;
+ if (ifr->ifr_settings.size < size) {
+ ifr->ifr_settings.size = size; /* data size wanted */
+ return -ENOBUFS;
+ }
+ memset(&new_line, 0, sizeof(new_line));
+ new_line.clock_type = port->clock_type;
+ new_line.clock_rate = 2048000; /* FIXME */
+ new_line.loopback = port->loopback;
+ if (copy_to_user(line, &new_line, size))
+ return -EFAULT;
+ return 0;
+
+ case IF_IFACE_SYNC_SERIAL:
+ case IF_IFACE_V35:
+ if(!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (copy_from_user(&new_line, line, size))
+ return -EFAULT;
+
+ clk = new_line.clock_type;
+ if (port->plat->set_clock)
+ clk = port->plat->set_clock(port->id, clk);
+
+ if (clk != CLOCK_EXT && clk != CLOCK_INT)
+ return -EINVAL; /* No such clock setting */
+
+ if (new_line.loopback != 0 && new_line.loopback != 1)
+ return -EINVAL;
+
+ port->clock_type = clk; /* Update settings */
+ /* FIXME port->clock_rate = new_line.clock_rate */;
+ port->loopback = new_line.loopback;
+
+ spin_lock_irqsave(&npe_lock, flags);
+
+ if (dev->flags & IFF_UP)
+ hss_config(port);
+
+ if (port->loopback || port->carrier)
+ netif_carrier_on(port->netdev);
+ else
+ netif_carrier_off(port->netdev);
+ spin_unlock_irqrestore(&npe_lock, flags);
+
+ return 0;
+
+ default:
+ return hdlc_ioctl(dev, ifr, cmd);
+ }
+}
+
+/*****************************************************************************
+ * initialization
+ ****************************************************************************/
+
+static int __devinit hss_init_one(struct platform_device *pdev)
+{
+ struct port *port;
+ struct net_device *dev;
+ hdlc_device *hdlc;
+ int err;
+
+ if ((port = kzalloc(sizeof(*port), GFP_KERNEL)) == NULL)
+ return -ENOMEM;
+
+ if ((port->npe = npe_request(0)) == NULL) {
+ err = -ENOSYS;
+ goto err_free;
+ }
+
+ if ((port->netdev = dev = alloc_hdlcdev(port)) == NULL) {
+ err = -ENOMEM;
+ goto err_plat;
+ }
+
+ SET_NETDEV_DEV(dev, &pdev->dev);
+ hdlc = dev_to_hdlc(dev);
+ hdlc->attach = hss_hdlc_attach;
+ hdlc->xmit = hss_hdlc_xmit;
+ dev->open = hss_hdlc_open;
+ dev->stop = hss_hdlc_close;
+ dev->do_ioctl = hss_hdlc_ioctl;
+ dev->tx_queue_len = 100;
+ port->clock_type = CLOCK_EXT;
+ port->clock_rate = 2048000;
+ port->id = pdev->id;
+ port->dev = &pdev->dev;
+ port->plat = pdev->dev.platform_data;
+ netif_napi_add(dev, &port->napi, hss_hdlc_poll, NAPI_WEIGHT);
+
+ if ((err = register_hdlc_device(dev)))
+ goto err_free_netdev;
+
+ platform_set_drvdata(pdev, port);
+
+ printk(KERN_INFO "%s: HSS-%i\n", dev->name, port->id);
+ return 0;
+
+err_free_netdev:
+ free_netdev(dev);
+err_plat:
+ npe_release(port->npe);
+err_free:
+ kfree(port);
+ return err;
+}
+
+static int __devexit hss_remove_one(struct platform_device *pdev)
+{
+ struct port *port = platform_get_drvdata(pdev);
+
+ unregister_hdlc_device(port->netdev);
+ free_netdev(port->netdev);
+ npe_release(port->npe);
+ platform_set_drvdata(pdev, NULL);
+ kfree(port);
+ return 0;
+}
+
+static struct platform_driver ixp4xx_hss_driver = {
+ .driver.name = DRV_NAME,
+ .probe = hss_init_one,
+ .remove = hss_remove_one,
+};
+
+static int __init hss_init_module(void)
+{
+ if ((ixp4xx_read_feature_bits() &
+ (IXP4XX_FEATURE_HDLC | IXP4XX_FEATURE_HSS)) !=
+ (IXP4XX_FEATURE_HDLC | IXP4XX_FEATURE_HSS))
+ return -ENOSYS;
+
+ spin_lock_init(&npe_lock);
+
+ return platform_driver_register(&ixp4xx_hss_driver);
+}
+
+static void __exit hss_cleanup_module(void)
+{
+ platform_driver_unregister(&ixp4xx_hss_driver);
+}
+
+MODULE_AUTHOR("Krzysztof Halasa");
+MODULE_DESCRIPTION("Intel IXP4xx HSS driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:ixp4xx_hss");
+module_init(hss_init_module);
+module_exit(hss_cleanup_module);
diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c
index 24fd613466b7..5b61b3eef45f 100644
--- a/drivers/net/wan/lapbether.c
+++ b/drivers/net/wan/lapbether.c
@@ -143,7 +143,6 @@ static int lapbeth_data_indication(struct net_device *dev, struct sk_buff *skb)
*ptr = 0x00;
skb->protocol = x25_type_trans(skb, dev);
- skb->dev->last_rx = jiffies;
return netif_rx(skb);
}
@@ -235,7 +234,6 @@ static void lapbeth_connected(struct net_device *dev, int reason)
*ptr = 0x01;
skb->protocol = x25_type_trans(skb, dev);
- skb->dev->last_rx = jiffies;
netif_rx(skb);
}
@@ -253,7 +251,6 @@ static void lapbeth_disconnected(struct net_device *dev, int reason)
*ptr = 0x02;
skb->protocol = x25_type_trans(skb, dev);
- skb->dev->last_rx = jiffies;
netif_rx(skb);
}
diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c
index d7bb63e616b5..feac3b99f8fe 100644
--- a/drivers/net/wan/lmc/lmc_main.c
+++ b/drivers/net/wan/lmc/lmc_main.c
@@ -1594,7 +1594,6 @@ static int lmc_rx(struct net_device *dev)
goto skip_packet;
}
- dev->last_rx = jiffies;
sc->lmc_device->stats.rx_packets++;
sc->lmc_device->stats.rx_bytes += len;
diff --git a/drivers/net/wan/lmc/lmc_proto.c b/drivers/net/wan/lmc/lmc_proto.c
index be9877ff551e..94b4c208b013 100644
--- a/drivers/net/wan/lmc/lmc_proto.c
+++ b/drivers/net/wan/lmc/lmc_proto.c
@@ -142,7 +142,6 @@ void lmc_proto_netif(lmc_softc_t *sc, struct sk_buff *skb) /*FOLD00*/
case LMC_PPP:
case LMC_NET:
default:
- skb->dev->last_rx = jiffies;
netif_rx(skb);
break;
case LMC_RAW:
diff --git a/drivers/net/wan/n2.c b/drivers/net/wan/n2.c
index 0a566b0daacb..697715ae80f4 100644
--- a/drivers/net/wan/n2.c
+++ b/drivers/net/wan/n2.c
@@ -53,7 +53,7 @@ static const char* devname = "RISCom/N2";
#define NEED_SCA_MSCI_INTR
#define MAX_TX_BUFFERS 10
-static char *hw = NULL; /* pointer to hw=xxx command line string */
+static char *hw; /* pointer to hw=xxx command line string */
/* RISCom/N2 Board Registers */
@@ -145,7 +145,6 @@ static card_t **new_card = &first_card;
&(card)->ports[port] : NULL)
-
static __inline__ u8 sca_get_page(card_t *card)
{
return inb(card->io + N2_PSR) & PSR_PAGEBITS;
@@ -159,9 +158,7 @@ static __inline__ void openwin(card_t *card, u8 page)
}
-
-#include "hd6457x.c"
-
+#include "hd64570.c"
static void n2_set_iface(port_t *port)
@@ -478,7 +475,7 @@ static int __init n2_run(unsigned long io, unsigned long irq,
n2_destroy_card(card);
return -ENOBUFS;
}
- sca_init_sync_port(port); /* Set up SCA memory */
+ sca_init_port(port); /* Set up SCA memory */
printk(KERN_INFO "%s: RISCom/N2 node %d\n",
dev->name, port->phy_node);
diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c
index d0a8d1e352ac..c23fde0c0344 100644
--- a/drivers/net/wan/pc300_drv.c
+++ b/drivers/net/wan/pc300_drv.c
@@ -1769,7 +1769,7 @@ cpc_trace(struct net_device *dev, struct sk_buff *skb_main, char rx_tx)
static void cpc_tx_timeout(struct net_device *dev)
{
- pc300dev_t *d = (pc300dev_t *) dev->priv;
+ pc300dev_t *d = (pc300dev_t *) dev_to_hdlc(dev)->priv;
pc300ch_t *chan = (pc300ch_t *) d->chan;
pc300_t *card = (pc300_t *) chan->card;
int ch = chan->channel;
@@ -1796,7 +1796,7 @@ static void cpc_tx_timeout(struct net_device *dev)
static int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
{
- pc300dev_t *d = (pc300dev_t *) dev->priv;
+ pc300dev_t *d = (pc300dev_t *) dev_to_hdlc(dev)->priv;
pc300ch_t *chan = (pc300ch_t *) d->chan;
pc300_t *card = (pc300_t *) chan->card;
int ch = chan->channel;
@@ -1874,7 +1874,7 @@ static int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
static void cpc_net_rx(struct net_device *dev)
{
- pc300dev_t *d = (pc300dev_t *) dev->priv;
+ pc300dev_t *d = (pc300dev_t *) dev_to_hdlc(dev)->priv;
pc300ch_t *chan = (pc300ch_t *) d->chan;
pc300_t *card = (pc300_t *) chan->card;
int ch = chan->channel;
@@ -2522,7 +2522,7 @@ static int cpc_change_mtu(struct net_device *dev, int new_mtu)
static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
- pc300dev_t *d = (pc300dev_t *) dev->priv;
+ pc300dev_t *d = (pc300dev_t *) dev_to_hdlc(dev)->priv;
pc300ch_t *chan = (pc300ch_t *) d->chan;
pc300_t *card = (pc300_t *) chan->card;
pc300conf_t conf_aux;
@@ -2718,9 +2718,8 @@ static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
}
pc300patrntst.num_errors =
falc_pattern_test_error(card, ch);
- if (!arg
- || copy_to_user(arg, &pc300patrntst,
- sizeof (pc300patterntst_t)))
+ if (copy_to_user(arg, &pc300patrntst,
+ sizeof(pc300patterntst_t)))
return -EINVAL;
} else {
falc_pattern_test(card, ch, pc300patrntst.patrntst_on);
@@ -3058,7 +3057,7 @@ static int tx_config(pc300dev_t * d)
static int cpc_attach(struct net_device *dev, unsigned short encoding,
unsigned short parity)
{
- pc300dev_t *d = (pc300dev_t *)dev->priv;
+ pc300dev_t *d = (pc300dev_t *)dev_to_hdlc(dev)->priv;
pc300ch_t *chan = (pc300ch_t *)d->chan;
pc300_t *card = (pc300_t *)chan->card;
pc300chconf_t *conf = (pc300chconf_t *)&chan->conf;
@@ -3138,7 +3137,7 @@ static void cpc_closech(pc300dev_t * d)
int cpc_open(struct net_device *dev)
{
- pc300dev_t *d = (pc300dev_t *) dev->priv;
+ pc300dev_t *d = (pc300dev_t *) dev_to_hdlc(dev)->priv;
struct ifreq ifr;
int result;
@@ -3166,7 +3165,7 @@ err_out:
static int cpc_close(struct net_device *dev)
{
- pc300dev_t *d = (pc300dev_t *) dev->priv;
+ pc300dev_t *d = (pc300dev_t *) dev_to_hdlc(dev)->priv;
pc300ch_t *chan = (pc300ch_t *) d->chan;
pc300_t *card = (pc300_t *) chan->card;
unsigned long flags;
@@ -3347,7 +3346,7 @@ static void cpc_init_card(pc300_t * card)
d->line_on = 0;
d->line_off = 0;
- dev = alloc_hdlcdev(NULL);
+ dev = alloc_hdlcdev(d);
if (dev == NULL)
continue;
@@ -3372,7 +3371,6 @@ static void cpc_init_card(pc300_t * card)
dev->do_ioctl = cpc_ioctl;
if (register_hdlc_device(dev) == 0) {
- dev->priv = d; /* We need 'priv', hdlc doesn't */
printk("%s: Cyclades-PC300/", dev->name);
switch (card->hw.type) {
case PC300_TE:
diff --git a/drivers/net/wan/pc300too.c b/drivers/net/wan/pc300too.c
index bf1b01590429..f247e5d9002a 100644
--- a/drivers/net/wan/pc300too.c
+++ b/drivers/net/wan/pc300too.c
@@ -1,7 +1,7 @@
/*
* Cyclades PC300 synchronous serial card driver for Linux
*
- * Copyright (C) 2000-2007 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 2000-2008 Krzysztof Halasa <khc@pm.waw.pl>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
@@ -11,7 +11,7 @@
*
* Sources of information:
* Hitachi HD64572 SCA-II User's Manual
- * Cyclades PC300 Linux driver
+ * Original Cyclades PC300 Linux driver
*
* This driver currently supports only PC300/RSV (V.24/V.35) and
* PC300/X21 cards.
@@ -37,17 +37,11 @@
#include "hd64572.h"
-static const char* version = "Cyclades PC300 driver version: 1.17";
-static const char* devname = "PC300";
-
#undef DEBUG_PKT
#define DEBUG_RINGS
#define PC300_PLX_SIZE 0x80 /* PLX control window size (128 B) */
#define PC300_SCA_SIZE 0x400 /* SCA window size (1 KB) */
-#define ALL_PAGES_ALWAYS_MAPPED
-#define NEED_DETECT_RAM
-#define NEED_SCA_MSCI_INTR
#define MAX_TX_BUFFERS 10
static int pci_clock_freq = 33000000;
@@ -81,7 +75,8 @@ typedef struct {
typedef struct port_s {
- struct net_device *dev;
+ struct napi_struct napi;
+ struct net_device *netdev;
struct card_s *card;
spinlock_t lock; /* TX lock */
sync_serial_settings settings;
@@ -93,7 +88,7 @@ typedef struct port_s {
u16 txin; /* tx ring buffer 'in' and 'last' pointers */
u16 txlast;
u8 rxs, txs, tmc; /* SCA registers */
- u8 phy_node; /* physical port # - 0 or 1 */
+ u8 chan; /* physical port # - 0 or 1 */
}port_t;
@@ -114,21 +109,10 @@ typedef struct card_s {
}card_t;
-#define sca_in(reg, card) readb(card->scabase + (reg))
-#define sca_out(value, reg, card) writeb(value, card->scabase + (reg))
-#define sca_inw(reg, card) readw(card->scabase + (reg))
-#define sca_outw(value, reg, card) writew(value, card->scabase + (reg))
-#define sca_inl(reg, card) readl(card->scabase + (reg))
-#define sca_outl(value, reg, card) writel(value, card->scabase + (reg))
-
-#define port_to_card(port) (port->card)
-#define log_node(port) (port->phy_node)
-#define phy_node(port) (port->phy_node)
-#define winbase(card) (card->rambase)
#define get_port(card, port) ((port) < (card)->n_ports ? \
(&(card)->ports[port]) : (NULL))
-#include "hd6457x.c"
+#include "hd64572.c"
static void pc300_set_iface(port_t *port)
@@ -139,8 +123,8 @@ static void pc300_set_iface(port_t *port)
u8 rxs = port->rxs & CLK_BRG_MASK;
u8 txs = port->txs & CLK_BRG_MASK;
- sca_out(EXS_TES1, (phy_node(port) ? MSCI1_OFFSET : MSCI0_OFFSET) + EXS,
- port_to_card(port));
+ sca_out(EXS_TES1, (port->chan ? MSCI1_OFFSET : MSCI0_OFFSET) + EXS,
+ port->card);
switch(port->settings.clock_type) {
case CLOCK_INT:
rxs |= CLK_BRG; /* BRG output */
@@ -172,10 +156,10 @@ static void pc300_set_iface(port_t *port)
if (port->card->type == PC300_RSV) {
if (port->iface == IF_IFACE_V35)
writel(card->init_ctrl_value |
- PC300_CHMEDIA_MASK(port->phy_node), init_ctrl);
+ PC300_CHMEDIA_MASK(port->chan), init_ctrl);
else
writel(card->init_ctrl_value &
- ~PC300_CHMEDIA_MASK(port->phy_node), init_ctrl);
+ ~PC300_CHMEDIA_MASK(port->chan), init_ctrl);
}
}
@@ -280,10 +264,8 @@ static void pc300_pci_remove_one(struct pci_dev *pdev)
card_t *card = pci_get_drvdata(pdev);
for (i = 0; i < 2; i++)
- if (card->ports[i].card) {
- struct net_device *dev = port_to_dev(&card->ports[i]);
- unregister_hdlc_device(dev);
- }
+ if (card->ports[i].card)
+ unregister_hdlc_device(card->ports[i].netdev);
if (card->irq)
free_irq(card->irq, card);
@@ -298,10 +280,10 @@ static void pc300_pci_remove_one(struct pci_dev *pdev)
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
- if (card->ports[0].dev)
- free_netdev(card->ports[0].dev);
- if (card->ports[1].dev)
- free_netdev(card->ports[1].dev);
+ if (card->ports[0].netdev)
+ free_netdev(card->ports[0].netdev);
+ if (card->ports[1].netdev)
+ free_netdev(card->ports[1].netdev);
kfree(card);
}
@@ -318,12 +300,6 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
u32 scaphys; /* SCA memory base */
u32 plxphys; /* PLX registers memory base */
-#ifndef MODULE
- static int printed_version;
- if (!printed_version++)
- printk(KERN_INFO "%s\n", version);
-#endif
-
i = pci_enable_device(pdev);
if (i)
return i;
@@ -343,27 +319,6 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
}
pci_set_drvdata(pdev, card);
- if (pdev->device == PCI_DEVICE_ID_PC300_TE_1 ||
- pdev->device == PCI_DEVICE_ID_PC300_TE_2)
- card->type = PC300_TE; /* not fully supported */
- else if (card->init_ctrl_value & PC300_CTYPE_MASK)
- card->type = PC300_X21;
- else
- card->type = PC300_RSV;
-
- if (pdev->device == PCI_DEVICE_ID_PC300_RX_1 ||
- pdev->device == PCI_DEVICE_ID_PC300_TE_1)
- card->n_ports = 1;
- else
- card->n_ports = 2;
-
- for (i = 0; i < card->n_ports; i++)
- if (!(card->ports[i].dev = alloc_hdlcdev(&card->ports[i]))) {
- printk(KERN_ERR "pc300: unable to allocate memory\n");
- pc300_pci_remove_one(pdev);
- return -ENOMEM;
- }
-
if (pci_resource_len(pdev, 0) != PC300_PLX_SIZE ||
pci_resource_len(pdev, 2) != PC300_SCA_SIZE ||
pci_resource_len(pdev, 3) < 16384) {
@@ -372,14 +327,14 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
return -EFAULT;
}
- plxphys = pci_resource_start(pdev,0) & PCI_BASE_ADDRESS_MEM_MASK;
+ plxphys = pci_resource_start(pdev, 0) & PCI_BASE_ADDRESS_MEM_MASK;
card->plxbase = ioremap(plxphys, PC300_PLX_SIZE);
- scaphys = pci_resource_start(pdev,2) & PCI_BASE_ADDRESS_MEM_MASK;
+ scaphys = pci_resource_start(pdev, 2) & PCI_BASE_ADDRESS_MEM_MASK;
card->scabase = ioremap(scaphys, PC300_SCA_SIZE);
- ramphys = pci_resource_start(pdev,3) & PCI_BASE_ADDRESS_MEM_MASK;
- card->rambase = ioremap(ramphys, pci_resource_len(pdev,3));
+ ramphys = pci_resource_start(pdev, 3) & PCI_BASE_ADDRESS_MEM_MASK;
+ card->rambase = pci_ioremap_bar(pdev, 3);
if (card->plxbase == NULL ||
card->scabase == NULL ||
@@ -393,6 +348,27 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
card->init_ctrl_value = readl(&((plx9050 __iomem *)card->scabase)->init_ctrl);
pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, plxphys);
+ if (pdev->device == PCI_DEVICE_ID_PC300_TE_1 ||
+ pdev->device == PCI_DEVICE_ID_PC300_TE_2)
+ card->type = PC300_TE; /* not fully supported */
+ else if (card->init_ctrl_value & PC300_CTYPE_MASK)
+ card->type = PC300_X21;
+ else
+ card->type = PC300_RSV;
+
+ if (pdev->device == PCI_DEVICE_ID_PC300_RX_1 ||
+ pdev->device == PCI_DEVICE_ID_PC300_TE_1)
+ card->n_ports = 1;
+ else
+ card->n_ports = 2;
+
+ for (i = 0; i < card->n_ports; i++)
+ if (!(card->ports[i].netdev = alloc_hdlcdev(&card->ports[i]))) {
+ printk(KERN_ERR "pc300: unable to allocate memory\n");
+ pc300_pci_remove_one(pdev);
+ return -ENOMEM;
+ }
+
/* Reset PLX */
p = &card->plxbase->init_ctrl;
writel(card->init_ctrl_value | 0x40000000, p);
@@ -446,7 +422,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
writew(0x0041, &card->plxbase->intr_ctrl_stat);
/* Allocate IRQ */
- if (request_irq(pdev->irq, sca_intr, IRQF_SHARED, devname, card)) {
+ if (request_irq(pdev->irq, sca_intr, IRQF_SHARED, "pc300", card)) {
printk(KERN_WARNING "pc300: could not allocate IRQ%d.\n",
pdev->irq);
pc300_pci_remove_one(pdev);
@@ -463,9 +439,9 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
for (i = 0; i < card->n_ports; i++) {
port_t *port = &card->ports[i];
- struct net_device *dev = port_to_dev(port);
+ struct net_device *dev = port->netdev;
hdlc_device *hdlc = dev_to_hdlc(dev);
- port->phy_node = i;
+ port->chan = i;
spin_lock_init(&port->lock);
dev->irq = card->irq;
@@ -484,6 +460,7 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
else
port->iface = IF_IFACE_V35;
+ sca_init_port(port);
if (register_hdlc_device(dev)) {
printk(KERN_ERR "pc300: unable to register hdlc "
"device\n");
@@ -491,10 +468,9 @@ static int __devinit pc300_pci_init_one(struct pci_dev *pdev,
pc300_pci_remove_one(pdev);
return -ENOBUFS;
}
- sca_init_sync_port(port); /* Set up SCA memory */
- printk(KERN_INFO "%s: PC300 node %d\n",
- dev->name, port->phy_node);
+ printk(KERN_INFO "%s: PC300 channel %d\n",
+ dev->name, port->chan);
}
return 0;
}
@@ -524,9 +500,6 @@ static struct pci_driver pc300_pci_driver = {
static int __init pc300_init_module(void)
{
-#ifdef MODULE
- printk(KERN_INFO "%s\n", version);
-#endif
if (pci_clock_freq < 1000000 || pci_clock_freq > 80000000) {
printk(KERN_ERR "pc300: Invalid PCI clock frequency\n");
return -EINVAL;
diff --git a/drivers/net/wan/pci200syn.c b/drivers/net/wan/pci200syn.c
index b595b64e7538..1104d3a692f7 100644
--- a/drivers/net/wan/pci200syn.c
+++ b/drivers/net/wan/pci200syn.c
@@ -1,7 +1,7 @@
/*
* Goramo PCI200SYN synchronous serial card driver for Linux
*
- * Copyright (C) 2002-2003 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 2002-2008 Krzysztof Halasa <khc@pm.waw.pl>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
@@ -33,17 +33,11 @@
#include "hd64572.h"
-static const char* version = "Goramo PCI200SYN driver version: 1.16";
-static const char* devname = "PCI200SYN";
-
#undef DEBUG_PKT
#define DEBUG_RINGS
#define PCI200SYN_PLX_SIZE 0x80 /* PLX control window size (128b) */
#define PCI200SYN_SCA_SIZE 0x400 /* SCA window size (1Kb) */
-#define ALL_PAGES_ALWAYS_MAPPED
-#define NEED_DETECT_RAM
-#define NEED_SCA_MSCI_INTR
#define MAX_TX_BUFFERS 10
static int pci_clock_freq = 33000000;
@@ -68,7 +62,8 @@ typedef struct {
typedef struct port_s {
- struct net_device *dev;
+ struct napi_struct napi;
+ struct net_device *netdev;
struct card_s *card;
spinlock_t lock; /* TX lock */
sync_serial_settings settings;
@@ -79,7 +74,7 @@ typedef struct port_s {
u16 txin; /* tx ring buffer 'in' and 'last' pointers */
u16 txlast;
u8 rxs, txs, tmc; /* SCA registers */
- u8 phy_node; /* physical port # - 0 or 1 */
+ u8 chan; /* physical port # - 0 or 1 */
}port_t;
@@ -97,17 +92,6 @@ typedef struct card_s {
}card_t;
-#define sca_in(reg, card) readb(card->scabase + (reg))
-#define sca_out(value, reg, card) writeb(value, card->scabase + (reg))
-#define sca_inw(reg, card) readw(card->scabase + (reg))
-#define sca_outw(value, reg, card) writew(value, card->scabase + (reg))
-#define sca_inl(reg, card) readl(card->scabase + (reg))
-#define sca_outl(value, reg, card) writel(value, card->scabase + (reg))
-
-#define port_to_card(port) (port->card)
-#define log_node(port) (port->phy_node)
-#define phy_node(port) (port->phy_node)
-#define winbase(card) (card->rambase)
#define get_port(card, port) (&card->ports[port])
#define sca_flush(card) (sca_in(IER0, card));
@@ -127,7 +111,7 @@ static inline void new_memcpy_toio(char __iomem *dest, char *src, int length)
#undef memcpy_toio
#define memcpy_toio new_memcpy_toio
-#include "hd6457x.c"
+#include "hd64572.c"
static void pci200_set_iface(port_t *port)
@@ -137,8 +121,8 @@ static void pci200_set_iface(port_t *port)
u8 rxs = port->rxs & CLK_BRG_MASK;
u8 txs = port->txs & CLK_BRG_MASK;
- sca_out(EXS_TES1, (phy_node(port) ? MSCI1_OFFSET : MSCI0_OFFSET) + EXS,
- port_to_card(port));
+ sca_out(EXS_TES1, (port->chan ? MSCI1_OFFSET : MSCI0_OFFSET) + EXS,
+ port->card);
switch(port->settings.clock_type) {
case CLOCK_INT:
rxs |= CLK_BRG; /* BRG output */
@@ -180,7 +164,7 @@ static int pci200_open(struct net_device *dev)
sca_open(dev);
pci200_set_iface(port);
- sca_flush(port_to_card(port));
+ sca_flush(port->card);
return 0;
}
@@ -189,7 +173,7 @@ static int pci200_open(struct net_device *dev)
static int pci200_close(struct net_device *dev)
{
sca_close(dev);
- sca_flush(port_to_card(dev_to_port(dev)));
+ sca_flush(dev_to_port(dev)->card);
hdlc_close(dev);
return 0;
}
@@ -242,7 +226,7 @@ static int pci200_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
memcpy(&port->settings, &new_line, size); /* Update settings */
pci200_set_iface(port);
- sca_flush(port_to_card(port));
+ sca_flush(port->card);
return 0;
default:
@@ -258,10 +242,8 @@ static void pci200_pci_remove_one(struct pci_dev *pdev)
card_t *card = pci_get_drvdata(pdev);
for (i = 0; i < 2; i++)
- if (card->ports[i].card) {
- struct net_device *dev = port_to_dev(&card->ports[i]);
- unregister_hdlc_device(dev);
- }
+ if (card->ports[i].card)
+ unregister_hdlc_device(card->ports[i].netdev);
if (card->irq)
free_irq(card->irq, card);
@@ -276,10 +258,10 @@ static void pci200_pci_remove_one(struct pci_dev *pdev)
pci_release_regions(pdev);
pci_disable_device(pdev);
pci_set_drvdata(pdev, NULL);
- if (card->ports[0].dev)
- free_netdev(card->ports[0].dev);
- if (card->ports[1].dev)
- free_netdev(card->ports[1].dev);
+ if (card->ports[0].netdev)
+ free_netdev(card->ports[0].netdev);
+ if (card->ports[1].netdev)
+ free_netdev(card->ports[1].netdev);
kfree(card);
}
@@ -296,12 +278,6 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
u32 scaphys; /* SCA memory base */
u32 plxphys; /* PLX registers memory base */
-#ifndef MODULE
- static int printed_version;
- if (!printed_version++)
- printk(KERN_INFO "%s\n", version);
-#endif
-
i = pci_enable_device(pdev);
if (i)
return i;
@@ -320,9 +296,9 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
return -ENOBUFS;
}
pci_set_drvdata(pdev, card);
- card->ports[0].dev = alloc_hdlcdev(&card->ports[0]);
- card->ports[1].dev = alloc_hdlcdev(&card->ports[1]);
- if (!card->ports[0].dev || !card->ports[1].dev) {
+ card->ports[0].netdev = alloc_hdlcdev(&card->ports[0]);
+ card->ports[1].netdev = alloc_hdlcdev(&card->ports[1]);
+ if (!card->ports[0].netdev || !card->ports[1].netdev) {
printk(KERN_ERR "pci200syn: unable to allocate memory\n");
pci200_pci_remove_one(pdev);
return -ENOMEM;
@@ -343,7 +319,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
card->scabase = ioremap(scaphys, PCI200SYN_SCA_SIZE);
ramphys = pci_resource_start(pdev,3) & PCI_BASE_ADDRESS_MEM_MASK;
- card->rambase = ioremap(ramphys, pci_resource_len(pdev,3));
+ card->rambase = pci_ioremap_bar(pdev, 3);
if (card->plxbase == NULL ||
card->scabase == NULL ||
@@ -398,7 +374,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
writew(readw(p) | 0x0040, p);
/* Allocate IRQ */
- if (request_irq(pdev->irq, sca_intr, IRQF_SHARED, devname, card)) {
+ if (request_irq(pdev->irq, sca_intr, IRQF_SHARED, "pci200syn", card)) {
printk(KERN_WARNING "pci200syn: could not allocate IRQ%d.\n",
pdev->irq);
pci200_pci_remove_one(pdev);
@@ -410,9 +386,9 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
for (i = 0; i < 2; i++) {
port_t *port = &card->ports[i];
- struct net_device *dev = port_to_dev(port);
+ struct net_device *dev = port->netdev;
hdlc_device *hdlc = dev_to_hdlc(dev);
- port->phy_node = i;
+ port->chan = i;
spin_lock_init(&port->lock);
dev->irq = card->irq;
@@ -426,6 +402,7 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
hdlc->xmit = sca_xmit;
port->settings.clock_type = CLOCK_EXT;
port->card = card;
+ sca_init_port(port);
if (register_hdlc_device(dev)) {
printk(KERN_ERR "pci200syn: unable to register hdlc "
"device\n");
@@ -433,10 +410,9 @@ static int __devinit pci200_pci_init_one(struct pci_dev *pdev,
pci200_pci_remove_one(pdev);
return -ENOBUFS;
}
- sca_init_sync_port(port); /* Set up SCA memory */
- printk(KERN_INFO "%s: PCI200SYN node %d\n",
- dev->name, port->phy_node);
+ printk(KERN_INFO "%s: PCI200SYN channel %d\n",
+ dev->name, port->chan);
}
sca_flush(card);
@@ -464,9 +440,6 @@ static struct pci_driver pci200_pci_driver = {
static int __init pci200_init_module(void)
{
-#ifdef MODULE
- printk(KERN_INFO "%s\n", version);
-#endif
if (pci_clock_freq < 1000000 || pci_clock_freq > 80000000) {
printk(KERN_ERR "pci200syn: Invalid PCI clock frequency\n");
return -EINVAL;
diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
index ee51b6a5e605..0aa28e1d4366 100644
--- a/drivers/net/wan/sbni.c
+++ b/drivers/net/wan/sbni.c
@@ -186,6 +186,7 @@ static unsigned int netcard_portlist[ ] __initdata = {
0x2b0, 0x2b4, 0x2c0, 0x2c4, 0x2d0, 0x2d4, 0x2e0, 0x2e4, 0x2f0, 0x2f4,
0 };
+#define NET_LOCAL_LOCK(dev) (((struct net_local *)netdev_priv(dev))->lock)
/*
* Look for SBNI card which addr stored in dev->base_addr, if nonzero.
@@ -287,7 +288,7 @@ static int __init sbni_init(struct net_device *dev)
}
-int __init
+static int __init
sbni_pci_probe( struct net_device *dev )
{
struct pci_dev *pdev = NULL;
@@ -378,22 +379,23 @@ sbni_probe1( struct net_device *dev, unsigned long ioaddr, int irq )
dev->irq = irq;
dev->base_addr = ioaddr;
- /* Allocate dev->priv and fill in sbni-specific dev fields. */
- nl = dev->priv;
+ /* Fill in sbni-specific dev fields. */
+ nl = netdev_priv(dev);
if( !nl ) {
printk( KERN_ERR "%s: unable to get memory!\n", dev->name );
release_region( ioaddr, SBNI_IO_EXTENT );
return NULL;
}
- dev->priv = nl;
memset( nl, 0, sizeof(struct net_local) );
spin_lock_init( &nl->lock );
/* store MAC address (generate if that isn't known) */
*(__be16 *)dev->dev_addr = htons( 0x00ff );
*(__be32 *)(dev->dev_addr + 2) = htonl( 0x01000000 |
- ( (mac[num] ? mac[num] : (u32)((long)dev->priv)) & 0x00ffffff) );
+ ((mac[num] ?
+ mac[num] :
+ (u32)((long)netdev_priv(dev))) & 0x00ffffff));
/* store link settings (speed, receive level ) */
nl->maxframe = DEFAULT_FRAME_LEN;
@@ -447,7 +449,7 @@ sbni_start_xmit( struct sk_buff *skb, struct net_device *dev )
/* Looking for idle device in the list */
for( p = dev; p; ) {
- struct net_local *nl = (struct net_local *) p->priv;
+ struct net_local *nl = netdev_priv(p);
spin_lock( &nl->lock );
if( nl->tx_buf_p || (nl->state & FL_LINE_DOWN) ) {
p = nl->link;
@@ -469,7 +471,7 @@ sbni_start_xmit( struct sk_buff *skb, struct net_device *dev )
static int
sbni_start_xmit( struct sk_buff *skb, struct net_device *dev )
{
- struct net_local *nl = (struct net_local *) dev->priv;
+ struct net_local *nl = netdev_priv(dev);
netif_stop_queue( dev );
spin_lock( &nl->lock );
@@ -503,12 +505,12 @@ static irqreturn_t
sbni_interrupt( int irq, void *dev_id )
{
struct net_device *dev = dev_id;
- struct net_local *nl = dev->priv;
+ struct net_local *nl = netdev_priv(dev);
int repeat;
spin_lock( &nl->lock );
if( nl->second )
- spin_lock( &((struct net_local *) nl->second->priv)->lock );
+ spin_lock(&NET_LOCAL_LOCK(nl->second));
do {
repeat = 0;
@@ -522,7 +524,7 @@ sbni_interrupt( int irq, void *dev_id )
} while( repeat );
if( nl->second )
- spin_unlock( &((struct net_local *)nl->second->priv)->lock );
+ spin_unlock(&NET_LOCAL_LOCK(nl->second));
spin_unlock( &nl->lock );
return IRQ_HANDLED;
}
@@ -531,7 +533,7 @@ sbni_interrupt( int irq, void *dev_id )
static void
handle_channel( struct net_device *dev )
{
- struct net_local *nl = (struct net_local *) dev->priv;
+ struct net_local *nl = netdev_priv(dev);
unsigned long ioaddr = dev->base_addr;
int req_ans;
@@ -540,7 +542,7 @@ handle_channel( struct net_device *dev )
#ifdef CONFIG_SBNI_MULTILINE
/* Lock the master device because we going to change its local data */
if( nl->state & FL_SLAVE )
- spin_lock( &((struct net_local *) nl->master->priv)->lock );
+ spin_lock(&NET_LOCAL_LOCK(nl->master));
#endif
outb( (inb( ioaddr + CSR0 ) & ~EN_INT) | TR_REQ, ioaddr + CSR0 );
@@ -576,7 +578,7 @@ handle_channel( struct net_device *dev )
#ifdef CONFIG_SBNI_MULTILINE
if( nl->state & FL_SLAVE )
- spin_unlock( &((struct net_local *) nl->master->priv)->lock );
+ spin_unlock(&NET_LOCAL_LOCK(nl->master));
#endif
}
@@ -589,7 +591,7 @@ handle_channel( struct net_device *dev )
static int
recv_frame( struct net_device *dev )
{
- struct net_local *nl = (struct net_local *) dev->priv;
+ struct net_local *nl = netdev_priv(dev);
unsigned long ioaddr = dev->base_addr;
u32 crc = CRC32_INITIAL;
@@ -623,7 +625,7 @@ recv_frame( struct net_device *dev )
static void
send_frame( struct net_device *dev )
{
- struct net_local *nl = (struct net_local *) dev->priv;
+ struct net_local *nl = netdev_priv(dev);
u32 crc = CRC32_INITIAL;
@@ -680,7 +682,7 @@ do_send:
static void
download_data( struct net_device *dev, u32 *crc_p )
{
- struct net_local *nl = (struct net_local *) dev->priv;
+ struct net_local *nl = netdev_priv(dev);
struct sk_buff *skb = nl->tx_buf_p;
unsigned len = min_t(unsigned int, skb->len - nl->outpos, nl->framelen);
@@ -699,7 +701,7 @@ static int
upload_data( struct net_device *dev, unsigned framelen, unsigned frameno,
unsigned is_first, u32 crc )
{
- struct net_local *nl = (struct net_local *) dev->priv;
+ struct net_local *nl = netdev_priv(dev);
int frame_ok;
@@ -721,9 +723,9 @@ upload_data( struct net_device *dev, unsigned framelen, unsigned frameno,
nl->wait_frameno = 0,
nl->inppos = 0,
#ifdef CONFIG_SBNI_MULTILINE
- ((struct net_local *) nl->master->priv)
+ ((struct net_local *)netdev_priv(nl->master))
->stats.rx_errors++,
- ((struct net_local *) nl->master->priv)
+ ((struct net_local *)netdev_priv(nl->master))
->stats.rx_missed_errors++;
#else
nl->stats.rx_errors++,
@@ -740,8 +742,10 @@ upload_data( struct net_device *dev, unsigned framelen, unsigned frameno,
*/
nl->wait_frameno = 0,
#ifdef CONFIG_SBNI_MULTILINE
- ((struct net_local *) nl->master->priv)->stats.rx_errors++,
- ((struct net_local *) nl->master->priv)->stats.rx_crc_errors++;
+ ((struct net_local *)netdev_priv(nl->master))
+ ->stats.rx_errors++,
+ ((struct net_local *)netdev_priv(nl->master))
+ ->stats.rx_crc_errors++;
#else
nl->stats.rx_errors++,
nl->stats.rx_crc_errors++;
@@ -755,8 +759,8 @@ static inline void
send_complete( struct net_local *nl )
{
#ifdef CONFIG_SBNI_MULTILINE
- ((struct net_local *) nl->master->priv)->stats.tx_packets++;
- ((struct net_local *) nl->master->priv)->stats.tx_bytes
+ ((struct net_local *)netdev_priv(nl->master))->stats.tx_packets++;
+ ((struct net_local *)netdev_priv(nl->master))->stats.tx_bytes
+= nl->tx_buf_p->len;
#else
nl->stats.tx_packets++;
@@ -775,7 +779,7 @@ send_complete( struct net_local *nl )
static void
interpret_ack( struct net_device *dev, unsigned ack )
{
- struct net_local *nl = (struct net_local *) dev->priv;
+ struct net_local *nl = netdev_priv(dev);
if( ack == FRAME_SENT_OK ) {
nl->state &= ~FL_NEED_RESEND;
@@ -809,7 +813,7 @@ interpret_ack( struct net_device *dev, unsigned ack )
static int
append_frame_to_pkt( struct net_device *dev, unsigned framelen, u32 crc )
{
- struct net_local *nl = (struct net_local *) dev->priv;
+ struct net_local *nl = netdev_priv(dev);
u8 *p;
@@ -840,7 +844,7 @@ append_frame_to_pkt( struct net_device *dev, unsigned framelen, u32 crc )
static void
prepare_to_send( struct sk_buff *skb, struct net_device *dev )
{
- struct net_local *nl = (struct net_local *) dev->priv;
+ struct net_local *nl = netdev_priv(dev);
unsigned int len;
@@ -871,15 +875,15 @@ prepare_to_send( struct sk_buff *skb, struct net_device *dev )
static void
drop_xmit_queue( struct net_device *dev )
{
- struct net_local *nl = (struct net_local *) dev->priv;
+ struct net_local *nl = netdev_priv(dev);
if( nl->tx_buf_p )
dev_kfree_skb_any( nl->tx_buf_p ),
nl->tx_buf_p = NULL,
#ifdef CONFIG_SBNI_MULTILINE
- ((struct net_local *) nl->master->priv)
+ ((struct net_local *)netdev_priv(nl->master))
->stats.tx_errors++,
- ((struct net_local *) nl->master->priv)
+ ((struct net_local *)netdev_priv(nl->master))
->stats.tx_carrier_errors++;
#else
nl->stats.tx_errors++,
@@ -903,7 +907,7 @@ drop_xmit_queue( struct net_device *dev )
static void
send_frame_header( struct net_device *dev, u32 *crc_p )
{
- struct net_local *nl = (struct net_local *) dev->priv;
+ struct net_local *nl = netdev_priv(dev);
u32 crc = *crc_p;
u32 len_field = nl->framelen + 6; /* CRC + frameno + reserved */
@@ -1005,7 +1009,7 @@ get_rx_buf( struct net_device *dev )
static void
indicate_pkt( struct net_device *dev )
{
- struct net_local *nl = (struct net_local *) dev->priv;
+ struct net_local *nl = netdev_priv(dev);
struct sk_buff *skb = nl->rx_buf_p;
skb_put( skb, nl->inppos );
@@ -1013,13 +1017,12 @@ indicate_pkt( struct net_device *dev )
#ifdef CONFIG_SBNI_MULTILINE
skb->protocol = eth_type_trans( skb, nl->master );
netif_rx( skb );
- dev->last_rx = jiffies;
- ++((struct net_local *) nl->master->priv)->stats.rx_packets;
- ((struct net_local *) nl->master->priv)->stats.rx_bytes += nl->inppos;
+ ++((struct net_local *)netdev_priv(nl->master))->stats.rx_packets;
+ ((struct net_local *)netdev_priv(nl->master))->stats.rx_bytes +=
+ nl->inppos;
#else
skb->protocol = eth_type_trans( skb, dev );
netif_rx( skb );
- dev->last_rx = jiffies;
++nl->stats.rx_packets;
nl->stats.rx_bytes += nl->inppos;
#endif
@@ -1038,7 +1041,7 @@ static void
sbni_watchdog( unsigned long arg )
{
struct net_device *dev = (struct net_device *) arg;
- struct net_local *nl = (struct net_local *) dev->priv;
+ struct net_local *nl = netdev_priv(dev);
struct timer_list *w = &nl->watchdog;
unsigned long flags;
unsigned char csr0;
@@ -1091,7 +1094,7 @@ static unsigned char timeout_rxl_tab[] = {
static void
card_start( struct net_device *dev )
{
- struct net_local *nl = (struct net_local *) dev->priv;
+ struct net_local *nl = netdev_priv(dev);
nl->timer_ticks = CHANGE_LEVEL_START_TICKS;
nl->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND);
@@ -1113,7 +1116,7 @@ card_start( struct net_device *dev )
static void
change_level( struct net_device *dev )
{
- struct net_local *nl = (struct net_local *) dev->priv;
+ struct net_local *nl = netdev_priv(dev);
if( nl->delta_rxl == 0 ) /* do not auto-negotiate RxL */
return;
@@ -1137,7 +1140,7 @@ change_level( struct net_device *dev )
static void
timeout_change_level( struct net_device *dev )
{
- struct net_local *nl = (struct net_local *) dev->priv;
+ struct net_local *nl = netdev_priv(dev);
nl->cur_rxl_index = timeout_rxl_tab[ nl->timeout_rxl ];
if( ++nl->timeout_rxl >= 4 )
@@ -1160,7 +1163,7 @@ timeout_change_level( struct net_device *dev )
static int
sbni_open( struct net_device *dev )
{
- struct net_local *nl = (struct net_local *) dev->priv;
+ struct net_local *nl = netdev_priv(dev);
struct timer_list *w = &nl->watchdog;
/*
@@ -1176,7 +1179,7 @@ sbni_open( struct net_device *dev )
|| (*p)->base_addr == dev->base_addr - 4)
&& (*p)->flags & IFF_UP ) {
- ((struct net_local *) ((*p)->priv))
+ ((struct net_local *) (netdev_priv(*p)))
->second = dev;
printk( KERN_NOTICE "%s: using shared irq "
"with %s\n", dev->name, (*p)->name );
@@ -1216,7 +1219,7 @@ handler_attached:
static int
sbni_close( struct net_device *dev )
{
- struct net_local *nl = (struct net_local *) dev->priv;
+ struct net_local *nl = netdev_priv(dev);
if( nl->second && nl->second->flags & IFF_UP ) {
printk( KERN_NOTICE "Secondary channel (%s) is active!\n",
@@ -1300,7 +1303,7 @@ sbni_card_probe( unsigned long ioaddr )
static int
sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd )
{
- struct net_local *nl = (struct net_local *) dev->priv;
+ struct net_local *nl = netdev_priv(dev);
struct sbni_flags flags;
int error = 0;
@@ -1390,8 +1393,8 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd )
static int
enslave( struct net_device *dev, struct net_device *slave_dev )
{
- struct net_local *nl = (struct net_local *) dev->priv;
- struct net_local *snl = (struct net_local *) slave_dev->priv;
+ struct net_local *nl = netdev_priv(dev);
+ struct net_local *snl = netdev_priv(slave_dev);
if( nl->state & FL_SLAVE ) /* This isn't master or free device */
return -EBUSY;
@@ -1425,9 +1428,9 @@ enslave( struct net_device *dev, struct net_device *slave_dev )
static int
emancipate( struct net_device *dev )
{
- struct net_local *snl = (struct net_local *) dev->priv;
+ struct net_local *snl = netdev_priv(dev);
struct net_device *p = snl->master;
- struct net_local *nl = (struct net_local *) p->priv;
+ struct net_local *nl = netdev_priv(p);
if( !(snl->state & FL_SLAVE) )
return -EINVAL;
@@ -1438,7 +1441,7 @@ emancipate( struct net_device *dev )
/* exclude from list */
for(;;) { /* must be in list */
- struct net_local *t = (struct net_local *) p->priv;
+ struct net_local *t = netdev_priv(p);
if( t->link == dev ) {
t->link = snl->link;
break;
@@ -1465,7 +1468,7 @@ emancipate( struct net_device *dev )
static struct net_device_stats *
sbni_get_stats( struct net_device *dev )
{
- return &((struct net_local *) dev->priv)->stats;
+ return &((struct net_local *)netdev_priv(dev))->stats;
}
diff --git a/drivers/net/wan/sdla.c b/drivers/net/wan/sdla.c
index 73e2f2780932..6a07ba9371db 100644
--- a/drivers/net/wan/sdla.c
+++ b/drivers/net/wan/sdla.c
@@ -185,7 +185,7 @@ static void sdla_stop(struct net_device *dev)
{
struct frad_local *flp;
- flp = dev->priv;
+ flp = netdev_priv(dev);
switch(flp->type)
{
case SDLA_S502A:
@@ -212,7 +212,7 @@ static void sdla_start(struct net_device *dev)
{
struct frad_local *flp;
- flp = dev->priv;
+ flp = netdev_priv(dev);
switch(flp->type)
{
case SDLA_S502A:
@@ -432,7 +432,7 @@ static int sdla_cmd(struct net_device *dev, int cmd, short dlci, short flags,
int ret, waiting, len;
long window;
- flp = dev->priv;
+ flp = netdev_priv(dev);
window = flp->type == SDLA_S508 ? SDLA_508_CMD_BUF : SDLA_502_CMD_BUF;
cmd_buf = (struct sdla_cmd *)(dev->mem_start + (window & SDLA_ADDR_MASK));
ret = 0;
@@ -509,7 +509,7 @@ static int sdla_activate(struct net_device *slave, struct net_device *master)
struct frad_local *flp;
int i;
- flp = slave->priv;
+ flp = netdev_priv(slave);
for(i=0;i<CONFIG_DLCI_MAX;i++)
if (flp->master[i] == master)
@@ -531,7 +531,7 @@ static int sdla_deactivate(struct net_device *slave, struct net_device *master)
struct frad_local *flp;
int i;
- flp = slave->priv;
+ flp = netdev_priv(slave);
for(i=0;i<CONFIG_DLCI_MAX;i++)
if (flp->master[i] == master)
@@ -556,7 +556,7 @@ static int sdla_assoc(struct net_device *slave, struct net_device *master)
if (master->type != ARPHRD_DLCI)
return(-EINVAL);
- flp = slave->priv;
+ flp = netdev_priv(slave);
for(i=0;i<CONFIG_DLCI_MAX;i++)
{
@@ -589,7 +589,7 @@ static int sdla_deassoc(struct net_device *slave, struct net_device *master)
struct frad_local *flp;
int i;
- flp = slave->priv;
+ flp = netdev_priv(slave);
for(i=0;i<CONFIG_DLCI_MAX;i++)
if (flp->master[i] == master)
@@ -619,7 +619,7 @@ static int sdla_dlci_conf(struct net_device *slave, struct net_device *master, i
int i;
short len, ret;
- flp = slave->priv;
+ flp = netdev_priv(slave);
for(i=0;i<CONFIG_DLCI_MAX;i++)
if (flp->master[i] == master)
@@ -628,7 +628,7 @@ static int sdla_dlci_conf(struct net_device *slave, struct net_device *master, i
if (i == CONFIG_DLCI_MAX)
return(-ENODEV);
- dlp = master->priv;
+ dlp = netdev_priv(master);
ret = SDLA_RET_OK;
len = sizeof(struct dlci_conf);
@@ -659,7 +659,7 @@ static int sdla_transmit(struct sk_buff *skb, struct net_device *dev)
unsigned long flags;
struct buf_entry *pbuf;
- flp = dev->priv;
+ flp = netdev_priv(dev);
ret = 0;
accept = 1;
@@ -755,7 +755,7 @@ static void sdla_receive(struct net_device *dev)
int i=0, received, success, addr, buf_base, buf_top;
short dlci, len, len2, split;
- flp = dev->priv;
+ flp = netdev_priv(dev);
success = 1;
received = addr = buf_top = buf_base = 0;
len = dlci = 0;
@@ -860,7 +860,7 @@ static void sdla_receive(struct net_device *dev)
if (success)
{
flp->stats.rx_packets++;
- dlp = master->priv;
+ dlp = netdev_priv(master);
(*dlp->receive)(skb, master);
}
@@ -925,7 +925,7 @@ static void sdla_poll(unsigned long device)
struct frad_local *flp;
dev = (struct net_device *) device;
- flp = dev->priv;
+ flp = netdev_priv(dev);
if (sdla_byte(dev, SDLA_502_RCV_BUF))
sdla_receive(dev);
@@ -941,7 +941,7 @@ static int sdla_close(struct net_device *dev)
int len, i;
short dlcis[CONFIG_DLCI_MAX];
- flp = dev->priv;
+ flp = netdev_priv(dev);
len = 0;
for(i=0;i<CONFIG_DLCI_MAX;i++)
@@ -1002,7 +1002,7 @@ static int sdla_open(struct net_device *dev)
int len, i;
char byte;
- flp = dev->priv;
+ flp = netdev_priv(dev);
if (!flp->initialized)
return(-EPERM);
@@ -1079,7 +1079,7 @@ static int sdla_open(struct net_device *dev)
for(i=0;i<CONFIG_DLCI_MAX;i++)
if (flp->dlci[i])
{
- dlp = flp->master[i]->priv;
+ dlp = netdev_priv(flp->master[i]);
if (dlp->configured)
sdla_cmd(dev, SDLA_SET_DLCI_CONFIGURATION, abs(flp->dlci[i]), 0, &dlp->config, sizeof(struct dlci_conf), NULL, NULL);
}
@@ -1099,7 +1099,7 @@ static int sdla_config(struct net_device *dev, struct frad_conf __user *conf, in
if (dev->type == 0xFFFF)
return(-EUNATCH);
- flp = dev->priv;
+ flp = netdev_priv(dev);
if (!get)
{
@@ -1230,7 +1230,7 @@ static int sdla_reconfig(struct net_device *dev)
struct conf_data data;
int i, len;
- flp = dev->priv;
+ flp = netdev_priv(dev);
len = 0;
for(i=0;i<CONFIG_DLCI_MAX;i++)
@@ -1255,7 +1255,7 @@ static int sdla_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if(!capable(CAP_NET_ADMIN))
return -EPERM;
- flp = dev->priv;
+ flp = netdev_priv(dev);
if (!flp->initialized)
return(-EINVAL);
@@ -1321,7 +1321,7 @@ static int sdla_change_mtu(struct net_device *dev, int new_mtu)
{
struct frad_local *flp;
- flp = dev->priv;
+ flp = netdev_priv(dev);
if (netif_running(dev))
return(-EBUSY);
@@ -1338,7 +1338,7 @@ static int sdla_set_config(struct net_device *dev, struct ifmap *map)
unsigned base;
int err = -EINVAL;
- flp = dev->priv;
+ flp = netdev_priv(dev);
if (flp->initialized)
return(-EINVAL);
@@ -1593,14 +1593,14 @@ fail:
static struct net_device_stats *sdla_stats(struct net_device *dev)
{
struct frad_local *flp;
- flp = dev->priv;
+ flp = netdev_priv(dev);
return(&flp->stats);
}
static void setup_sdla(struct net_device *dev)
{
- struct frad_local *flp = dev->priv;
+ struct frad_local *flp = netdev_priv(dev);
netdev_boot_setup_check(dev);
@@ -1651,7 +1651,7 @@ static int __init init_sdla(void)
static void __exit exit_sdla(void)
{
- struct frad_local *flp = sdla->priv;
+ struct frad_local *flp = netdev_priv(sdla);
unregister_netdev(sdla);
if (flp->initialized) {
diff --git a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c
index c0235844a4d5..0941a26f6e3f 100644
--- a/drivers/net/wan/sealevel.c
+++ b/drivers/net/wan/sealevel.c
@@ -68,7 +68,6 @@ static void sealevel_input(struct z8530_channel *c, struct sk_buff *skb)
skb_reset_mac_header(skb);
skb->dev = c->netdevice;
netif_rx(skb);
- c->netdevice->last_rx = jiffies;
}
/*
diff --git a/drivers/net/wan/syncppp.c b/drivers/net/wan/syncppp.c
deleted file mode 100644
index 6e92f7b44b1a..000000000000
--- a/drivers/net/wan/syncppp.c
+++ /dev/null
@@ -1,1480 +0,0 @@
-/*
- * NET3: A (fairly minimal) implementation of synchronous PPP for Linux
- * as well as a CISCO HDLC implementation. See the copyright
- * message below for the original source.
- *
- * 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.
- *
- * Note however. This code is also used in a different form by FreeBSD.
- * Therefore when making any non OS specific change please consider
- * contributing it back to the original author under the terms
- * below in addition.
- * -- Alan
- *
- * Port for Linux-2.1 by Jan "Yenya" Kasprzak <kas@fi.muni.cz>
- */
-
-/*
- * Synchronous PPP/Cisco link level subroutines.
- * Keepalive protocol implemented in both Cisco and PPP modes.
- *
- * Copyright (C) 1994 Cronyx Ltd.
- * Author: Serge Vakulenko, <vak@zebub.msk.su>
- *
- * This software is distributed with NO WARRANTIES, not even the implied
- * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- *
- * Authors grant any other persons or organisations permission to use
- * or modify this software as long as this message is kept with the software,
- * all derivative works or modified versions.
- *
- * Version 1.9, Wed Oct 4 18:58:15 MSK 1995
- *
- * $Id: syncppp.c,v 1.18 2000/04/11 05:25:31 asj Exp $
- */
-#undef DEBUG
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/if_arp.h>
-#include <linux/skbuff.h>
-#include <linux/route.h>
-#include <linux/netdevice.h>
-#include <linux/inetdevice.h>
-#include <linux/random.h>
-#include <linux/pkt_sched.h>
-#include <linux/spinlock.h>
-#include <linux/rcupdate.h>
-
-#include <net/net_namespace.h>
-#include <net/syncppp.h>
-
-#include <asm/byteorder.h>
-#include <asm/uaccess.h>
-
-#define MAXALIVECNT 6 /* max. alive packets */
-
-#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */
-#define PPP_UI 0x03 /* Unnumbered Information */
-#define PPP_IP 0x0021 /* Internet Protocol */
-#define PPP_ISO 0x0023 /* ISO OSI Protocol */
-#define PPP_XNS 0x0025 /* Xerox NS Protocol */
-#define PPP_IPX 0x002b /* Novell IPX Protocol */
-#define PPP_LCP 0xc021 /* Link Control Protocol */
-#define PPP_IPCP 0x8021 /* Internet Protocol Control Protocol */
-
-#define LCP_CONF_REQ 1 /* PPP LCP configure request */
-#define LCP_CONF_ACK 2 /* PPP LCP configure acknowledge */
-#define LCP_CONF_NAK 3 /* PPP LCP configure negative ack */
-#define LCP_CONF_REJ 4 /* PPP LCP configure reject */
-#define LCP_TERM_REQ 5 /* PPP LCP terminate request */
-#define LCP_TERM_ACK 6 /* PPP LCP terminate acknowledge */
-#define LCP_CODE_REJ 7 /* PPP LCP code reject */
-#define LCP_PROTO_REJ 8 /* PPP LCP protocol reject */
-#define LCP_ECHO_REQ 9 /* PPP LCP echo request */
-#define LCP_ECHO_REPLY 10 /* PPP LCP echo reply */
-#define LCP_DISC_REQ 11 /* PPP LCP discard request */
-
-#define LCP_OPT_MRU 1 /* maximum receive unit */
-#define LCP_OPT_ASYNC_MAP 2 /* async control character map */
-#define LCP_OPT_AUTH_PROTO 3 /* authentication protocol */
-#define LCP_OPT_QUAL_PROTO 4 /* quality protocol */
-#define LCP_OPT_MAGIC 5 /* magic number */
-#define LCP_OPT_RESERVED 6 /* reserved */
-#define LCP_OPT_PROTO_COMP 7 /* protocol field compression */
-#define LCP_OPT_ADDR_COMP 8 /* address/control field compression */
-
-#define IPCP_CONF_REQ LCP_CONF_REQ /* PPP IPCP configure request */
-#define IPCP_CONF_ACK LCP_CONF_ACK /* PPP IPCP configure acknowledge */
-#define IPCP_CONF_NAK LCP_CONF_NAK /* PPP IPCP configure negative ack */
-#define IPCP_CONF_REJ LCP_CONF_REJ /* PPP IPCP configure reject */
-#define IPCP_TERM_REQ LCP_TERM_REQ /* PPP IPCP terminate request */
-#define IPCP_TERM_ACK LCP_TERM_ACK /* PPP IPCP terminate acknowledge */
-#define IPCP_CODE_REJ LCP_CODE_REJ /* PPP IPCP code reject */
-
-#define CISCO_MULTICAST 0x8f /* Cisco multicast address */
-#define CISCO_UNICAST 0x0f /* Cisco unicast address */
-#define CISCO_KEEPALIVE 0x8035 /* Cisco keepalive protocol */
-#define CISCO_ADDR_REQ 0 /* Cisco address request */
-#define CISCO_ADDR_REPLY 1 /* Cisco address reply */
-#define CISCO_KEEPALIVE_REQ 2 /* Cisco keepalive request */
-
-struct ppp_header {
- u8 address;
- u8 control;
- __be16 protocol;
-};
-#define PPP_HEADER_LEN sizeof (struct ppp_header)
-
-struct lcp_header {
- u8 type;
- u8 ident;
- __be16 len;
-};
-#define LCP_HEADER_LEN sizeof (struct lcp_header)
-
-struct cisco_packet {
- __be32 type;
- __be32 par1;
- __be32 par2;
- __be16 rel;
- __be16 time0;
- __be16 time1;
-};
-#define CISCO_PACKET_LEN 18
-#define CISCO_BIG_PACKET_LEN 20
-
-static struct sppp *spppq;
-static struct timer_list sppp_keepalive_timer;
-static DEFINE_SPINLOCK(spppq_lock);
-
-/* global xmit queue for sending packets while spinlock is held */
-static struct sk_buff_head tx_queue;
-
-static void sppp_keepalive (unsigned long dummy);
-static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type,
- u8 ident, u16 len, void *data);
-static void sppp_cisco_send (struct sppp *sp, int type, u32 par1, u32 par2);
-static void sppp_lcp_input (struct sppp *sp, struct sk_buff *m);
-static void sppp_cisco_input (struct sppp *sp, struct sk_buff *m);
-static void sppp_ipcp_input (struct sppp *sp, struct sk_buff *m);
-static void sppp_lcp_open (struct sppp *sp);
-static void sppp_ipcp_open (struct sppp *sp);
-static int sppp_lcp_conf_parse_options (struct sppp *sp, struct lcp_header *h,
- int len, u32 *magic);
-static void sppp_cp_timeout (unsigned long arg);
-static char *sppp_lcp_type_name (u8 type);
-static char *sppp_ipcp_type_name (u8 type);
-static void sppp_print_bytes (u8 *p, u16 len);
-
-static int debug;
-
-/* Flush global outgoing packet queue to dev_queue_xmit().
- *
- * dev_queue_xmit() must be called with interrupts enabled
- * which means it can't be called with spinlocks held.
- * If a packet needs to be sent while a spinlock is held,
- * then put the packet into tx_queue, and call sppp_flush_xmit()
- * after spinlock is released.
- */
-static void sppp_flush_xmit(void)
-{
- struct sk_buff *skb;
- while ((skb = skb_dequeue(&tx_queue)) != NULL)
- dev_queue_xmit(skb);
-}
-
-/*
- * Interface down stub
- */
-
-static void if_down(struct net_device *dev)
-{
- struct sppp *sp = (struct sppp *)sppp_of(dev);
-
- sp->pp_link_state=SPPP_LINK_DOWN;
-}
-
-/*
- * Timeout routine activations.
- */
-
-static void sppp_set_timeout(struct sppp *p,int s)
-{
- if (! (p->pp_flags & PP_TIMO))
- {
- init_timer(&p->pp_timer);
- p->pp_timer.function=sppp_cp_timeout;
- p->pp_timer.expires=jiffies+s*HZ;
- p->pp_timer.data=(unsigned long)p;
- p->pp_flags |= PP_TIMO;
- add_timer(&p->pp_timer);
- }
-}
-
-static void sppp_clear_timeout(struct sppp *p)
-{
- if (p->pp_flags & PP_TIMO)
- {
- del_timer(&p->pp_timer);
- p->pp_flags &= ~PP_TIMO;
- }
-}
-
-/**
- * sppp_input - receive and process a WAN PPP frame
- * @skb: The buffer to process
- * @dev: The device it arrived on
- *
- * This can be called directly by cards that do not have
- * timing constraints but is normally called from the network layer
- * after interrupt servicing to process frames queued via netif_rx().
- *
- * We process the options in the card. If the frame is destined for
- * the protocol stacks then it requeues the frame for the upper level
- * protocol. If it is a control from it is processed and discarded
- * here.
- */
-
-static void sppp_input (struct net_device *dev, struct sk_buff *skb)
-{
- struct ppp_header *h;
- struct sppp *sp = (struct sppp *)sppp_of(dev);
- unsigned long flags;
-
- skb->dev=dev;
- skb_reset_mac_header(skb);
-
- if (!pskb_may_pull(skb, PPP_HEADER_LEN)) {
- /* Too small packet, drop it. */
- if (sp->pp_flags & PP_DEBUG)
- printk (KERN_DEBUG "%s: input packet is too small, %d bytes\n",
- dev->name, skb->len);
- kfree_skb(skb);
- return;
- }
-
- /* Get PPP header. */
- h = (struct ppp_header *)skb->data;
- skb_pull(skb,sizeof(struct ppp_header));
-
- spin_lock_irqsave(&sp->lock, flags);
-
- switch (h->address) {
- default: /* Invalid PPP packet. */
- goto invalid;
- case PPP_ALLSTATIONS:
- if (h->control != PPP_UI)
- goto invalid;
- if (sp->pp_flags & PP_CISCO) {
- if (sp->pp_flags & PP_DEBUG)
- printk (KERN_WARNING "%s: PPP packet in Cisco mode <0x%x 0x%x 0x%x>\n",
- dev->name,
- h->address, h->control, ntohs (h->protocol));
- goto drop;
- }
- switch (ntohs (h->protocol)) {
- default:
- if (sp->lcp.state == LCP_STATE_OPENED)
- sppp_cp_send (sp, PPP_LCP, LCP_PROTO_REJ,
- ++sp->pp_seq, skb->len + 2,
- &h->protocol);
- if (sp->pp_flags & PP_DEBUG)
- printk (KERN_WARNING "%s: invalid input protocol <0x%x 0x%x 0x%x>\n",
- dev->name,
- h->address, h->control, ntohs (h->protocol));
- goto drop;
- case PPP_LCP:
- sppp_lcp_input (sp, skb);
- goto drop;
- case PPP_IPCP:
- if (sp->lcp.state == LCP_STATE_OPENED)
- sppp_ipcp_input (sp, skb);
- else
- printk(KERN_DEBUG "IPCP when still waiting LCP finish.\n");
- goto drop;
- case PPP_IP:
- if (sp->ipcp.state == IPCP_STATE_OPENED) {
- if(sp->pp_flags&PP_DEBUG)
- printk(KERN_DEBUG "Yow an IP frame.\n");
- skb->protocol=htons(ETH_P_IP);
- netif_rx(skb);
- dev->last_rx = jiffies;
- goto done;
- }
- break;
-#ifdef IPX
- case PPP_IPX:
- /* IPX IPXCP not implemented yet */
- if (sp->lcp.state == LCP_STATE_OPENED) {
- skb->protocol=htons(ETH_P_IPX);
- netif_rx(skb);
- dev->last_rx = jiffies;
- goto done;
- }
- break;
-#endif
- }
- break;
- case CISCO_MULTICAST:
- case CISCO_UNICAST:
- /* Don't check the control field here (RFC 1547). */
- if (! (sp->pp_flags & PP_CISCO)) {
- if (sp->pp_flags & PP_DEBUG)
- printk (KERN_WARNING "%s: Cisco packet in PPP mode <0x%x 0x%x 0x%x>\n",
- dev->name,
- h->address, h->control, ntohs (h->protocol));
- goto drop;
- }
- switch (ntohs (h->protocol)) {
- default:
- goto invalid;
- case CISCO_KEEPALIVE:
- sppp_cisco_input (sp, skb);
- goto drop;
-#ifdef CONFIG_INET
- case ETH_P_IP:
- skb->protocol=htons(ETH_P_IP);
- netif_rx(skb);
- dev->last_rx = jiffies;
- goto done;
-#endif
-#ifdef CONFIG_IPX
- case ETH_P_IPX:
- skb->protocol=htons(ETH_P_IPX);
- netif_rx(skb);
- dev->last_rx = jiffies;
- goto done;
-#endif
- }
- break;
- }
- goto drop;
-
-invalid:
- if (sp->pp_flags & PP_DEBUG)
- printk (KERN_WARNING "%s: invalid input packet <0x%x 0x%x 0x%x>\n",
- dev->name, h->address, h->control, ntohs (h->protocol));
-drop:
- kfree_skb(skb);
-done:
- spin_unlock_irqrestore(&sp->lock, flags);
- sppp_flush_xmit();
- return;
-}
-
-/*
- * Handle transmit packets.
- */
-
-static int sppp_hard_header(struct sk_buff *skb,
- struct net_device *dev, __u16 type,
- const void *daddr, const void *saddr,
- unsigned int len)
-{
- struct sppp *sp = (struct sppp *)sppp_of(dev);
- struct ppp_header *h;
- skb_push(skb,sizeof(struct ppp_header));
- h=(struct ppp_header *)skb->data;
- if(sp->pp_flags&PP_CISCO)
- {
- h->address = CISCO_UNICAST;
- h->control = 0;
- }
- else
- {
- h->address = PPP_ALLSTATIONS;
- h->control = PPP_UI;
- }
- if(sp->pp_flags & PP_CISCO)
- {
- h->protocol = htons(type);
- }
- else switch(type)
- {
- case ETH_P_IP:
- h->protocol = htons(PPP_IP);
- break;
- case ETH_P_IPX:
- h->protocol = htons(PPP_IPX);
- break;
- }
- return sizeof(struct ppp_header);
-}
-
-static const struct header_ops sppp_header_ops = {
- .create = sppp_hard_header,
-};
-
-/*
- * Send keepalive packets, every 10 seconds.
- */
-
-static void sppp_keepalive (unsigned long dummy)
-{
- struct sppp *sp;
- unsigned long flags;
-
- spin_lock_irqsave(&spppq_lock, flags);
-
- for (sp=spppq; sp; sp=sp->pp_next)
- {
- struct net_device *dev = sp->pp_if;
-
- /* Keepalive mode disabled or channel down? */
- if (! (sp->pp_flags & PP_KEEPALIVE) ||
- ! (dev->flags & IFF_UP))
- continue;
-
- spin_lock(&sp->lock);
-
- /* No keepalive in PPP mode if LCP not opened yet. */
- if (! (sp->pp_flags & PP_CISCO) &&
- sp->lcp.state != LCP_STATE_OPENED) {
- spin_unlock(&sp->lock);
- continue;
- }
-
- if (sp->pp_alivecnt == MAXALIVECNT) {
- /* No keepalive packets got. Stop the interface. */
- printk (KERN_WARNING "%s: protocol down\n", dev->name);
- if_down (dev);
- if (! (sp->pp_flags & PP_CISCO)) {
- /* Shut down the PPP link. */
- sp->lcp.magic = jiffies;
- sp->lcp.state = LCP_STATE_CLOSED;
- sp->ipcp.state = IPCP_STATE_CLOSED;
- sppp_clear_timeout (sp);
- /* Initiate negotiation. */
- sppp_lcp_open (sp);
- }
- }
- if (sp->pp_alivecnt <= MAXALIVECNT)
- ++sp->pp_alivecnt;
- if (sp->pp_flags & PP_CISCO)
- sppp_cisco_send (sp, CISCO_KEEPALIVE_REQ, ++sp->pp_seq,
- sp->pp_rseq);
- else if (sp->lcp.state == LCP_STATE_OPENED) {
- __be32 nmagic = htonl (sp->lcp.magic);
- sp->lcp.echoid = ++sp->pp_seq;
- sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REQ,
- sp->lcp.echoid, 4, &nmagic);
- }
-
- spin_unlock(&sp->lock);
- }
- spin_unlock_irqrestore(&spppq_lock, flags);
- sppp_flush_xmit();
- sppp_keepalive_timer.expires=jiffies+10*HZ;
- add_timer(&sppp_keepalive_timer);
-}
-
-/*
- * Handle incoming PPP Link Control Protocol packets.
- */
-
-static void sppp_lcp_input (struct sppp *sp, struct sk_buff *skb)
-{
- struct lcp_header *h;
- struct net_device *dev = sp->pp_if;
- int len = skb->len;
- u8 *p, opt[6];
- u32 rmagic = 0;
-
- if (!pskb_may_pull(skb, sizeof(struct lcp_header))) {
- if (sp->pp_flags & PP_DEBUG)
- printk (KERN_WARNING "%s: invalid lcp packet length: %d bytes\n",
- dev->name, len);
- return;
- }
- h = (struct lcp_header *)skb->data;
- skb_pull(skb,sizeof(struct lcp_header *));
-
- if (sp->pp_flags & PP_DEBUG)
- {
- char state = '?';
- switch (sp->lcp.state) {
- case LCP_STATE_CLOSED: state = 'C'; break;
- case LCP_STATE_ACK_RCVD: state = 'R'; break;
- case LCP_STATE_ACK_SENT: state = 'S'; break;
- case LCP_STATE_OPENED: state = 'O'; break;
- }
- printk (KERN_WARNING "%s: lcp input(%c): %d bytes <%s id=%xh len=%xh",
- dev->name, state, len,
- sppp_lcp_type_name (h->type), h->ident, ntohs (h->len));
- if (len > 4)
- sppp_print_bytes ((u8*) (h+1), len-4);
- printk (">\n");
- }
- if (len > ntohs (h->len))
- len = ntohs (h->len);
- switch (h->type) {
- default:
- /* Unknown packet type -- send Code-Reject packet. */
- sppp_cp_send (sp, PPP_LCP, LCP_CODE_REJ, ++sp->pp_seq,
- skb->len, h);
- break;
- case LCP_CONF_REQ:
- if (len < 4) {
- if (sp->pp_flags & PP_DEBUG)
- printk (KERN_DEBUG"%s: invalid lcp configure request packet length: %d bytes\n",
- dev->name, len);
- break;
- }
- if (len>4 && !sppp_lcp_conf_parse_options (sp, h, len, &rmagic))
- goto badreq;
- if (rmagic == sp->lcp.magic) {
- /* Local and remote magics equal -- loopback? */
- if (sp->pp_loopcnt >= MAXALIVECNT*5) {
- printk (KERN_WARNING "%s: loopback\n",
- dev->name);
- sp->pp_loopcnt = 0;
- if (dev->flags & IFF_UP) {
- if_down (dev);
- }
- } else if (sp->pp_flags & PP_DEBUG)
- printk (KERN_DEBUG "%s: conf req: magic glitch\n",
- dev->name);
- ++sp->pp_loopcnt;
-
- /* MUST send Conf-Nack packet. */
- rmagic = ~sp->lcp.magic;
- opt[0] = LCP_OPT_MAGIC;
- opt[1] = sizeof (opt);
- opt[2] = rmagic >> 24;
- opt[3] = rmagic >> 16;
- opt[4] = rmagic >> 8;
- opt[5] = rmagic;
- sppp_cp_send (sp, PPP_LCP, LCP_CONF_NAK,
- h->ident, sizeof (opt), &opt);
-badreq:
- switch (sp->lcp.state) {
- case LCP_STATE_OPENED:
- /* Initiate renegotiation. */
- sppp_lcp_open (sp);
- /* fall through... */
- case LCP_STATE_ACK_SENT:
- /* Go to closed state. */
- sp->lcp.state = LCP_STATE_CLOSED;
- sp->ipcp.state = IPCP_STATE_CLOSED;
- }
- break;
- }
- /* Send Configure-Ack packet. */
- sp->pp_loopcnt = 0;
- if (sp->lcp.state != LCP_STATE_OPENED) {
- sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK,
- h->ident, len-4, h+1);
- }
- /* Change the state. */
- switch (sp->lcp.state) {
- case LCP_STATE_CLOSED:
- sp->lcp.state = LCP_STATE_ACK_SENT;
- break;
- case LCP_STATE_ACK_RCVD:
- sp->lcp.state = LCP_STATE_OPENED;
- sppp_ipcp_open (sp);
- break;
- case LCP_STATE_OPENED:
- /* Remote magic changed -- close session. */
- sp->lcp.state = LCP_STATE_CLOSED;
- sp->ipcp.state = IPCP_STATE_CLOSED;
- /* Initiate renegotiation. */
- sppp_lcp_open (sp);
- /* Send ACK after our REQ in attempt to break loop */
- sppp_cp_send (sp, PPP_LCP, LCP_CONF_ACK,
- h->ident, len-4, h+1);
- sp->lcp.state = LCP_STATE_ACK_SENT;
- break;
- }
- break;
- case LCP_CONF_ACK:
- if (h->ident != sp->lcp.confid)
- break;
- sppp_clear_timeout (sp);
- if ((sp->pp_link_state != SPPP_LINK_UP) &&
- (dev->flags & IFF_UP)) {
- /* Coming out of loopback mode. */
- sp->pp_link_state=SPPP_LINK_UP;
- printk (KERN_INFO "%s: protocol up\n", dev->name);
- }
- switch (sp->lcp.state) {
- case LCP_STATE_CLOSED:
- sp->lcp.state = LCP_STATE_ACK_RCVD;
- sppp_set_timeout (sp, 5);
- break;
- case LCP_STATE_ACK_SENT:
- sp->lcp.state = LCP_STATE_OPENED;
- sppp_ipcp_open (sp);
- break;
- }
- break;
- case LCP_CONF_NAK:
- if (h->ident != sp->lcp.confid)
- break;
- p = (u8*) (h+1);
- if (len>=10 && p[0] == LCP_OPT_MAGIC && p[1] >= 4) {
- rmagic = (u32)p[2] << 24 |
- (u32)p[3] << 16 | p[4] << 8 | p[5];
- if (rmagic == ~sp->lcp.magic) {
- int newmagic;
- if (sp->pp_flags & PP_DEBUG)
- printk (KERN_DEBUG "%s: conf nak: magic glitch\n",
- dev->name);
- get_random_bytes(&newmagic, sizeof(newmagic));
- sp->lcp.magic += newmagic;
- } else
- sp->lcp.magic = rmagic;
- }
- if (sp->lcp.state != LCP_STATE_ACK_SENT) {
- /* Go to closed state. */
- sp->lcp.state = LCP_STATE_CLOSED;
- sp->ipcp.state = IPCP_STATE_CLOSED;
- }
- /* The link will be renegotiated after timeout,
- * to avoid endless req-nack loop. */
- sppp_clear_timeout (sp);
- sppp_set_timeout (sp, 2);
- break;
- case LCP_CONF_REJ:
- if (h->ident != sp->lcp.confid)
- break;
- sppp_clear_timeout (sp);
- /* Initiate renegotiation. */
- sppp_lcp_open (sp);
- if (sp->lcp.state != LCP_STATE_ACK_SENT) {
- /* Go to closed state. */
- sp->lcp.state = LCP_STATE_CLOSED;
- sp->ipcp.state = IPCP_STATE_CLOSED;
- }
- break;
- case LCP_TERM_REQ:
- sppp_clear_timeout (sp);
- /* Send Terminate-Ack packet. */
- sppp_cp_send (sp, PPP_LCP, LCP_TERM_ACK, h->ident, 0, NULL);
- /* Go to closed state. */
- sp->lcp.state = LCP_STATE_CLOSED;
- sp->ipcp.state = IPCP_STATE_CLOSED;
- /* Initiate renegotiation. */
- sppp_lcp_open (sp);
- break;
- case LCP_TERM_ACK:
- case LCP_CODE_REJ:
- case LCP_PROTO_REJ:
- /* Ignore for now. */
- break;
- case LCP_DISC_REQ:
- /* Discard the packet. */
- break;
- case LCP_ECHO_REQ:
- if (sp->lcp.state != LCP_STATE_OPENED)
- break;
- if (len < 8) {
- if (sp->pp_flags & PP_DEBUG)
- printk (KERN_WARNING "%s: invalid lcp echo request packet length: %d bytes\n",
- dev->name, len);
- break;
- }
- if (ntohl (*(__be32*)(h+1)) == sp->lcp.magic) {
- /* Line loopback mode detected. */
- printk (KERN_WARNING "%s: loopback\n", dev->name);
- if_down (dev);
-
- /* Shut down the PPP link. */
- sp->lcp.state = LCP_STATE_CLOSED;
- sp->ipcp.state = IPCP_STATE_CLOSED;
- sppp_clear_timeout (sp);
- /* Initiate negotiation. */
- sppp_lcp_open (sp);
- break;
- }
- *(__be32 *)(h+1) = htonl (sp->lcp.magic);
- sppp_cp_send (sp, PPP_LCP, LCP_ECHO_REPLY, h->ident, len-4, h+1);
- break;
- case LCP_ECHO_REPLY:
- if (h->ident != sp->lcp.echoid)
- break;
- if (len < 8) {
- if (sp->pp_flags & PP_DEBUG)
- printk (KERN_WARNING "%s: invalid lcp echo reply packet length: %d bytes\n",
- dev->name, len);
- break;
- }
- if (ntohl(*(__be32 *)(h+1)) != sp->lcp.magic)
- sp->pp_alivecnt = 0;
- break;
- }
-}
-
-/*
- * Handle incoming Cisco keepalive protocol packets.
- */
-
-static void sppp_cisco_input (struct sppp *sp, struct sk_buff *skb)
-{
- struct cisco_packet *h;
- struct net_device *dev = sp->pp_if;
-
- if (!pskb_may_pull(skb, sizeof(struct cisco_packet))
- || (skb->len != CISCO_PACKET_LEN
- && skb->len != CISCO_BIG_PACKET_LEN)) {
- if (sp->pp_flags & PP_DEBUG)
- printk (KERN_WARNING "%s: invalid cisco packet length: %d bytes\n",
- dev->name, skb->len);
- return;
- }
- h = (struct cisco_packet *)skb->data;
- skb_pull(skb, sizeof(struct cisco_packet*));
- if (sp->pp_flags & PP_DEBUG)
- printk (KERN_WARNING "%s: cisco input: %d bytes <%xh %xh %xh %xh %xh-%xh>\n",
- dev->name, skb->len,
- ntohl (h->type), h->par1, h->par2, h->rel,
- h->time0, h->time1);
- switch (ntohl (h->type)) {
- default:
- if (sp->pp_flags & PP_DEBUG)
- printk (KERN_WARNING "%s: unknown cisco packet type: 0x%x\n",
- dev->name, ntohl (h->type));
- break;
- case CISCO_ADDR_REPLY:
- /* Reply on address request, ignore */
- break;
- case CISCO_KEEPALIVE_REQ:
- sp->pp_alivecnt = 0;
- sp->pp_rseq = ntohl (h->par1);
- if (sp->pp_seq == sp->pp_rseq) {
- /* Local and remote sequence numbers are equal.
- * Probably, the line is in loopback mode. */
- int newseq;
- if (sp->pp_loopcnt >= MAXALIVECNT) {
- printk (KERN_WARNING "%s: loopback\n",
- dev->name);
- sp->pp_loopcnt = 0;
- if (dev->flags & IFF_UP) {
- if_down (dev);
- }
- }
- ++sp->pp_loopcnt;
-
- /* Generate new local sequence number */
- get_random_bytes(&newseq, sizeof(newseq));
- sp->pp_seq ^= newseq;
- break;
- }
- sp->pp_loopcnt = 0;
- if (sp->pp_link_state==SPPP_LINK_DOWN &&
- (dev->flags & IFF_UP)) {
- sp->pp_link_state=SPPP_LINK_UP;
- printk (KERN_INFO "%s: protocol up\n", dev->name);
- }
- break;
- case CISCO_ADDR_REQ:
- /* Stolen from net/ipv4/devinet.c -- SIOCGIFADDR ioctl */
- {
- __be32 addr = 0, mask = htonl(~0U); /* FIXME: is the mask correct? */
-#ifdef CONFIG_INET
- struct in_device *in_dev;
- struct in_ifaddr *ifa;
-
- rcu_read_lock();
- if ((in_dev = __in_dev_get_rcu(dev)) != NULL)
- {
- for (ifa=in_dev->ifa_list; ifa != NULL;
- ifa=ifa->ifa_next) {
- if (strcmp(dev->name, ifa->ifa_label) == 0)
- {
- addr = ifa->ifa_local;
- mask = ifa->ifa_mask;
- break;
- }
- }
- }
- rcu_read_unlock();
-#endif
- sppp_cisco_send (sp, CISCO_ADDR_REPLY, ntohl(addr), ntohl(mask));
- break;
- }
- }
-}
-
-
-/*
- * Send PPP LCP packet.
- */
-
-static void sppp_cp_send (struct sppp *sp, u16 proto, u8 type,
- u8 ident, u16 len, void *data)
-{
- struct ppp_header *h;
- struct lcp_header *lh;
- struct sk_buff *skb;
- struct net_device *dev = sp->pp_if;
-
- skb=alloc_skb(dev->hard_header_len+PPP_HEADER_LEN+LCP_HEADER_LEN+len,
- GFP_ATOMIC);
- if (skb==NULL)
- return;
-
- skb_reserve(skb,dev->hard_header_len);
-
- h = (struct ppp_header *)skb_put(skb, sizeof(struct ppp_header));
- h->address = PPP_ALLSTATIONS; /* broadcast address */
- h->control = PPP_UI; /* Unnumbered Info */
- h->protocol = htons (proto); /* Link Control Protocol */
-
- lh = (struct lcp_header *)skb_put(skb, sizeof(struct lcp_header));
- lh->type = type;
- lh->ident = ident;
- lh->len = htons (LCP_HEADER_LEN + len);
-
- if (len)
- memcpy(skb_put(skb,len),data, len);
-
- if (sp->pp_flags & PP_DEBUG) {
- printk (KERN_WARNING "%s: %s output <%s id=%xh len=%xh",
- dev->name,
- proto==PPP_LCP ? "lcp" : "ipcp",
- proto==PPP_LCP ? sppp_lcp_type_name (lh->type) :
- sppp_ipcp_type_name (lh->type), lh->ident,
- ntohs (lh->len));
- if (len)
- sppp_print_bytes ((u8*) (lh+1), len);
- printk (">\n");
- }
- /* Control is high priority so it doesn't get queued behind data */
- skb->priority=TC_PRIO_CONTROL;
- skb->dev = dev;
- skb_queue_tail(&tx_queue, skb);
-}
-
-/*
- * Send Cisco keepalive packet.
- */
-
-static void sppp_cisco_send (struct sppp *sp, int type, u32 par1, u32 par2)
-{
- struct ppp_header *h;
- struct cisco_packet *ch;
- struct sk_buff *skb;
- struct net_device *dev = sp->pp_if;
- u32 t = jiffies * 1000/HZ;
-
- skb=alloc_skb(dev->hard_header_len+PPP_HEADER_LEN+CISCO_PACKET_LEN,
- GFP_ATOMIC);
-
- if(skb==NULL)
- return;
-
- skb_reserve(skb, dev->hard_header_len);
- h = (struct ppp_header *)skb_put (skb, sizeof(struct ppp_header));
- h->address = CISCO_MULTICAST;
- h->control = 0;
- h->protocol = htons (CISCO_KEEPALIVE);
-
- ch = (struct cisco_packet*)skb_put(skb, CISCO_PACKET_LEN);
- ch->type = htonl (type);
- ch->par1 = htonl (par1);
- ch->par2 = htonl (par2);
- ch->rel = htons(0xffff);
- ch->time0 = htons ((u16) (t >> 16));
- ch->time1 = htons ((u16) t);
-
- if (sp->pp_flags & PP_DEBUG)
- printk (KERN_WARNING "%s: cisco output: <%xh %xh %xh %xh %xh-%xh>\n",
- dev->name, ntohl (ch->type), ch->par1,
- ch->par2, ch->rel, ch->time0, ch->time1);
- skb->priority=TC_PRIO_CONTROL;
- skb->dev = dev;
- skb_queue_tail(&tx_queue, skb);
-}
-
-/**
- * sppp_close - close down a synchronous PPP or Cisco HDLC link
- * @dev: The network device to drop the link of
- *
- * This drops the logical interface to the channel. It is not
- * done politely as we assume we will also be dropping DTR. Any
- * timeouts are killed.
- */
-
-int sppp_close (struct net_device *dev)
-{
- struct sppp *sp = (struct sppp *)sppp_of(dev);
- unsigned long flags;
-
- spin_lock_irqsave(&sp->lock, flags);
- sp->pp_link_state = SPPP_LINK_DOWN;
- sp->lcp.state = LCP_STATE_CLOSED;
- sp->ipcp.state = IPCP_STATE_CLOSED;
- sppp_clear_timeout (sp);
- spin_unlock_irqrestore(&sp->lock, flags);
-
- return 0;
-}
-
-EXPORT_SYMBOL(sppp_close);
-
-/**
- * sppp_open - open a synchronous PPP or Cisco HDLC link
- * @dev: Network device to activate
- *
- * Close down any existing synchronous session and commence
- * from scratch. In the PPP case this means negotiating LCP/IPCP
- * and friends, while for Cisco HDLC we simply need to start sending
- * keepalives
- */
-
-int sppp_open (struct net_device *dev)
-{
- struct sppp *sp = (struct sppp *)sppp_of(dev);
- unsigned long flags;
-
- sppp_close(dev);
-
- spin_lock_irqsave(&sp->lock, flags);
- if (!(sp->pp_flags & PP_CISCO)) {
- sppp_lcp_open (sp);
- }
- sp->pp_link_state = SPPP_LINK_DOWN;
- spin_unlock_irqrestore(&sp->lock, flags);
- sppp_flush_xmit();
-
- return 0;
-}
-
-EXPORT_SYMBOL(sppp_open);
-
-/**
- * sppp_reopen - notify of physical link loss
- * @dev: Device that lost the link
- *
- * This function informs the synchronous protocol code that
- * the underlying link died (for example a carrier drop on X.21)
- *
- * We increment the magic numbers to ensure that if the other end
- * failed to notice we will correctly start a new session. It happens
- * do to the nature of telco circuits is that you can lose carrier on
- * one endonly.
- *
- * Having done this we go back to negotiating. This function may
- * be called from an interrupt context.
- */
-
-int sppp_reopen (struct net_device *dev)
-{
- struct sppp *sp = (struct sppp *)sppp_of(dev);
- unsigned long flags;
-
- sppp_close(dev);
-
- spin_lock_irqsave(&sp->lock, flags);
- if (!(sp->pp_flags & PP_CISCO))
- {
- sp->lcp.magic = jiffies;
- ++sp->pp_seq;
- sp->lcp.state = LCP_STATE_CLOSED;
- sp->ipcp.state = IPCP_STATE_CLOSED;
- /* Give it a moment for the line to settle then go */
- sppp_set_timeout (sp, 1);
- }
- sp->pp_link_state=SPPP_LINK_DOWN;
- spin_unlock_irqrestore(&sp->lock, flags);
-
- return 0;
-}
-
-EXPORT_SYMBOL(sppp_reopen);
-
-/**
- * sppp_change_mtu - Change the link MTU
- * @dev: Device to change MTU on
- * @new_mtu: New MTU
- *
- * Change the MTU on the link. This can only be called with
- * the link down. It returns an error if the link is up or
- * the mtu is out of range.
- */
-
-static int sppp_change_mtu(struct net_device *dev, int new_mtu)
-{
- if(new_mtu<128||new_mtu>PPP_MTU||(dev->flags&IFF_UP))
- return -EINVAL;
- dev->mtu=new_mtu;
- return 0;
-}
-
-/**
- * sppp_do_ioctl - Ioctl handler for ppp/hdlc
- * @dev: Device subject to ioctl
- * @ifr: Interface request block from the user
- * @cmd: Command that is being issued
- *
- * This function handles the ioctls that may be issued by the user
- * to control the settings of a PPP/HDLC link. It does both busy
- * and security checks. This function is intended to be wrapped by
- * callers who wish to add additional ioctl calls of their own.
- */
-
-int sppp_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
- struct sppp *sp = (struct sppp *)sppp_of(dev);
-
- if(dev->flags&IFF_UP)
- return -EBUSY;
-
- if(!capable(CAP_NET_ADMIN))
- return -EPERM;
-
- switch(cmd)
- {
- case SPPPIOCCISCO:
- sp->pp_flags|=PP_CISCO;
- dev->type = ARPHRD_HDLC;
- break;
- case SPPPIOCPPP:
- sp->pp_flags&=~PP_CISCO;
- dev->type = ARPHRD_PPP;
- break;
- case SPPPIOCDEBUG:
- sp->pp_flags&=~PP_DEBUG;
- if(ifr->ifr_flags)
- sp->pp_flags|=PP_DEBUG;
- break;
- case SPPPIOCGFLAGS:
- if(copy_to_user(ifr->ifr_data, &sp->pp_flags, sizeof(sp->pp_flags)))
- return -EFAULT;
- break;
- case SPPPIOCSFLAGS:
- if(copy_from_user(&sp->pp_flags, ifr->ifr_data, sizeof(sp->pp_flags)))
- return -EFAULT;
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-EXPORT_SYMBOL(sppp_do_ioctl);
-
-/**
- * sppp_attach - attach synchronous PPP/HDLC to a device
- * @pd: PPP device to initialise
- *
- * This initialises the PPP/HDLC support on an interface. At the
- * time of calling the dev element must point to the network device
- * that this interface is attached to. The interface should not yet
- * be registered.
- */
-
-void sppp_attach(struct ppp_device *pd)
-{
- struct net_device *dev = pd->dev;
- struct sppp *sp = &pd->sppp;
- unsigned long flags;
-
- /* Make sure embedding is safe for sppp_of */
- BUG_ON(sppp_of(dev) != sp);
-
- spin_lock_irqsave(&spppq_lock, flags);
- /* Initialize keepalive handler. */
- if (! spppq)
- {
- init_timer(&sppp_keepalive_timer);
- sppp_keepalive_timer.expires=jiffies+10*HZ;
- sppp_keepalive_timer.function=sppp_keepalive;
- add_timer(&sppp_keepalive_timer);
- }
- /* Insert new entry into the keepalive list. */
- sp->pp_next = spppq;
- spppq = sp;
- spin_unlock_irqrestore(&spppq_lock, flags);
-
- sp->pp_loopcnt = 0;
- sp->pp_alivecnt = 0;
- sp->pp_seq = 0;
- sp->pp_rseq = 0;
- sp->pp_flags = PP_KEEPALIVE|PP_CISCO|debug;/*PP_DEBUG;*/
- sp->lcp.magic = 0;
- sp->lcp.state = LCP_STATE_CLOSED;
- sp->ipcp.state = IPCP_STATE_CLOSED;
- sp->pp_if = dev;
- spin_lock_init(&sp->lock);
-
- /*
- * Device specific setup. All but interrupt handler and
- * hard_start_xmit.
- */
-
- dev->header_ops = &sppp_header_ops;
-
- dev->tx_queue_len = 10;
- dev->type = ARPHRD_HDLC;
- dev->addr_len = 0;
- dev->hard_header_len = sizeof(struct ppp_header);
- dev->mtu = PPP_MTU;
- /*
- * These 4 are callers but MUST also call sppp_ functions
- */
- dev->do_ioctl = sppp_do_ioctl;
-#if 0
- dev->get_stats = NULL; /* Let the driver override these */
- dev->open = sppp_open;
- dev->stop = sppp_close;
-#endif
- dev->change_mtu = sppp_change_mtu;
- dev->flags = IFF_MULTICAST|IFF_POINTOPOINT|IFF_NOARP;
-}
-
-EXPORT_SYMBOL(sppp_attach);
-
-/**
- * sppp_detach - release PPP resources from a device
- * @dev: Network device to release
- *
- * Stop and free up any PPP/HDLC resources used by this
- * interface. This must be called before the device is
- * freed.
- */
-
-void sppp_detach (struct net_device *dev)
-{
- struct sppp **q, *p, *sp = (struct sppp *)sppp_of(dev);
- unsigned long flags;
-
- spin_lock_irqsave(&spppq_lock, flags);
- /* Remove the entry from the keepalive list. */
- for (q = &spppq; (p = *q); q = &p->pp_next)
- if (p == sp) {
- *q = p->pp_next;
- break;
- }
-
- /* Stop keepalive handler. */
- if (! spppq)
- del_timer(&sppp_keepalive_timer);
- sppp_clear_timeout (sp);
- spin_unlock_irqrestore(&spppq_lock, flags);
-}
-
-EXPORT_SYMBOL(sppp_detach);
-
-/*
- * Analyze the LCP Configure-Request options list
- * for the presence of unknown options.
- * If the request contains unknown options, build and
- * send Configure-reject packet, containing only unknown options.
- */
-static int
-sppp_lcp_conf_parse_options (struct sppp *sp, struct lcp_header *h,
- int len, u32 *magic)
-{
- u8 *buf, *r, *p;
- int rlen;
-
- len -= 4;
- buf = r = kmalloc (len, GFP_ATOMIC);
- if (! buf)
- return (0);
-
- p = (void*) (h+1);
- for (rlen=0; len>1 && p[1]; len-=p[1], p+=p[1]) {
- switch (*p) {
- case LCP_OPT_MAGIC:
- /* Magic number -- extract. */
- if (len >= 6 && p[1] == 6) {
- *magic = (u32)p[2] << 24 |
- (u32)p[3] << 16 | p[4] << 8 | p[5];
- continue;
- }
- break;
- case LCP_OPT_ASYNC_MAP:
- /* Async control character map -- check to be zero. */
- if (len >= 6 && p[1] == 6 && ! p[2] && ! p[3] &&
- ! p[4] && ! p[5])
- continue;
- break;
- case LCP_OPT_MRU:
- /* Maximum receive unit -- always OK. */
- continue;
- default:
- /* Others not supported. */
- break;
- }
- /* Add the option to rejected list. */
- memcpy(r, p, p[1]);
- r += p[1];
- rlen += p[1];
- }
- if (rlen)
- sppp_cp_send (sp, PPP_LCP, LCP_CONF_REJ, h->ident, rlen, buf);
- kfree(buf);
- return (rlen == 0);
-}
-
-static void sppp_ipcp_input (struct sppp *sp, struct sk_buff *skb)
-{
- struct lcp_header *h;
- struct net_device *dev = sp->pp_if;
- int len = skb->len;
-
- if (!pskb_may_pull(skb, sizeof(struct lcp_header))) {
- if (sp->pp_flags & PP_DEBUG)
- printk (KERN_WARNING "%s: invalid ipcp packet length: %d bytes\n",
- dev->name, len);
- return;
- }
- h = (struct lcp_header *)skb->data;
- skb_pull(skb,sizeof(struct lcp_header));
- if (sp->pp_flags & PP_DEBUG) {
- printk (KERN_WARNING "%s: ipcp input: %d bytes <%s id=%xh len=%xh",
- dev->name, len,
- sppp_ipcp_type_name (h->type), h->ident, ntohs (h->len));
- if (len > 4)
- sppp_print_bytes ((u8*) (h+1), len-4);
- printk (">\n");
- }
- if (len > ntohs (h->len))
- len = ntohs (h->len);
- switch (h->type) {
- default:
- /* Unknown packet type -- send Code-Reject packet. */
- sppp_cp_send (sp, PPP_IPCP, IPCP_CODE_REJ, ++sp->pp_seq, len, h);
- break;
- case IPCP_CONF_REQ:
- if (len < 4) {
- if (sp->pp_flags & PP_DEBUG)
- printk (KERN_WARNING "%s: invalid ipcp configure request packet length: %d bytes\n",
- dev->name, len);
- return;
- }
- if (len > 4) {
- sppp_cp_send (sp, PPP_IPCP, LCP_CONF_REJ, h->ident,
- len-4, h+1);
-
- switch (sp->ipcp.state) {
- case IPCP_STATE_OPENED:
- /* Initiate renegotiation. */
- sppp_ipcp_open (sp);
- /* fall through... */
- case IPCP_STATE_ACK_SENT:
- /* Go to closed state. */
- sp->ipcp.state = IPCP_STATE_CLOSED;
- }
- } else {
- /* Send Configure-Ack packet. */
- sppp_cp_send (sp, PPP_IPCP, IPCP_CONF_ACK, h->ident,
- 0, NULL);
- /* Change the state. */
- if (sp->ipcp.state == IPCP_STATE_ACK_RCVD)
- sp->ipcp.state = IPCP_STATE_OPENED;
- else
- sp->ipcp.state = IPCP_STATE_ACK_SENT;
- }
- break;
- case IPCP_CONF_ACK:
- if (h->ident != sp->ipcp.confid)
- break;
- sppp_clear_timeout (sp);
- switch (sp->ipcp.state) {
- case IPCP_STATE_CLOSED:
- sp->ipcp.state = IPCP_STATE_ACK_RCVD;
- sppp_set_timeout (sp, 5);
- break;
- case IPCP_STATE_ACK_SENT:
- sp->ipcp.state = IPCP_STATE_OPENED;
- break;
- }
- break;
- case IPCP_CONF_NAK:
- case IPCP_CONF_REJ:
- if (h->ident != sp->ipcp.confid)
- break;
- sppp_clear_timeout (sp);
- /* Initiate renegotiation. */
- sppp_ipcp_open (sp);
- if (sp->ipcp.state != IPCP_STATE_ACK_SENT)
- /* Go to closed state. */
- sp->ipcp.state = IPCP_STATE_CLOSED;
- break;
- case IPCP_TERM_REQ:
- /* Send Terminate-Ack packet. */
- sppp_cp_send (sp, PPP_IPCP, IPCP_TERM_ACK, h->ident, 0, NULL);
- /* Go to closed state. */
- sp->ipcp.state = IPCP_STATE_CLOSED;
- /* Initiate renegotiation. */
- sppp_ipcp_open (sp);
- break;
- case IPCP_TERM_ACK:
- /* Ignore for now. */
- case IPCP_CODE_REJ:
- /* Ignore for now. */
- break;
- }
-}
-
-static void sppp_lcp_open (struct sppp *sp)
-{
- char opt[6];
-
- if (! sp->lcp.magic)
- sp->lcp.magic = jiffies;
- opt[0] = LCP_OPT_MAGIC;
- opt[1] = sizeof (opt);
- opt[2] = sp->lcp.magic >> 24;
- opt[3] = sp->lcp.magic >> 16;
- opt[4] = sp->lcp.magic >> 8;
- opt[5] = sp->lcp.magic;
- sp->lcp.confid = ++sp->pp_seq;
- sppp_cp_send (sp, PPP_LCP, LCP_CONF_REQ, sp->lcp.confid,
- sizeof (opt), &opt);
- sppp_set_timeout (sp, 2);
-}
-
-static void sppp_ipcp_open (struct sppp *sp)
-{
- sp->ipcp.confid = ++sp->pp_seq;
- sppp_cp_send (sp, PPP_IPCP, IPCP_CONF_REQ, sp->ipcp.confid, 0, NULL);
- sppp_set_timeout (sp, 2);
-}
-
-/*
- * Process PPP control protocol timeouts.
- */
-
-static void sppp_cp_timeout (unsigned long arg)
-{
- struct sppp *sp = (struct sppp*) arg;
- unsigned long flags;
-
- spin_lock_irqsave(&sp->lock, flags);
-
- sp->pp_flags &= ~PP_TIMO;
- if (! (sp->pp_if->flags & IFF_UP) || (sp->pp_flags & PP_CISCO)) {
- spin_unlock_irqrestore(&sp->lock, flags);
- return;
- }
- switch (sp->lcp.state) {
- case LCP_STATE_CLOSED:
- /* No ACK for Configure-Request, retry. */
- sppp_lcp_open (sp);
- break;
- case LCP_STATE_ACK_RCVD:
- /* ACK got, but no Configure-Request for peer, retry. */
- sppp_lcp_open (sp);
- sp->lcp.state = LCP_STATE_CLOSED;
- break;
- case LCP_STATE_ACK_SENT:
- /* ACK sent but no ACK for Configure-Request, retry. */
- sppp_lcp_open (sp);
- break;
- case LCP_STATE_OPENED:
- /* LCP is already OK, try IPCP. */
- switch (sp->ipcp.state) {
- case IPCP_STATE_CLOSED:
- /* No ACK for Configure-Request, retry. */
- sppp_ipcp_open (sp);
- break;
- case IPCP_STATE_ACK_RCVD:
- /* ACK got, but no Configure-Request for peer, retry. */
- sppp_ipcp_open (sp);
- sp->ipcp.state = IPCP_STATE_CLOSED;
- break;
- case IPCP_STATE_ACK_SENT:
- /* ACK sent but no ACK for Configure-Request, retry. */
- sppp_ipcp_open (sp);
- break;
- case IPCP_STATE_OPENED:
- /* IPCP is OK. */
- break;
- }
- break;
- }
- spin_unlock_irqrestore(&sp->lock, flags);
- sppp_flush_xmit();
-}
-
-static char *sppp_lcp_type_name (u8 type)
-{
- static char buf [8];
- switch (type) {
- case LCP_CONF_REQ: return ("conf-req");
- case LCP_CONF_ACK: return ("conf-ack");
- case LCP_CONF_NAK: return ("conf-nack");
- case LCP_CONF_REJ: return ("conf-rej");
- case LCP_TERM_REQ: return ("term-req");
- case LCP_TERM_ACK: return ("term-ack");
- case LCP_CODE_REJ: return ("code-rej");
- case LCP_PROTO_REJ: return ("proto-rej");
- case LCP_ECHO_REQ: return ("echo-req");
- case LCP_ECHO_REPLY: return ("echo-reply");
- case LCP_DISC_REQ: return ("discard-req");
- }
- sprintf (buf, "%xh", type);
- return (buf);
-}
-
-static char *sppp_ipcp_type_name (u8 type)
-{
- static char buf [8];
- switch (type) {
- case IPCP_CONF_REQ: return ("conf-req");
- case IPCP_CONF_ACK: return ("conf-ack");
- case IPCP_CONF_NAK: return ("conf-nack");
- case IPCP_CONF_REJ: return ("conf-rej");
- case IPCP_TERM_REQ: return ("term-req");
- case IPCP_TERM_ACK: return ("term-ack");
- case IPCP_CODE_REJ: return ("code-rej");
- }
- sprintf (buf, "%xh", type);
- return (buf);
-}
-
-static void sppp_print_bytes (u_char *p, u16 len)
-{
- printk (" %x", *p++);
- while (--len > 0)
- printk ("-%x", *p++);
-}
-
-/**
- * sppp_rcv - receive and process a WAN PPP frame
- * @skb: The buffer to process
- * @dev: The device it arrived on
- * @p: Unused
- * @orig_dev: Unused
- *
- * Protocol glue. This drives the deferred processing mode the poorer
- * cards use. This can be called directly by cards that do not have
- * timing constraints but is normally called from the network layer
- * after interrupt servicing to process frames queued via netif_rx.
- */
-
-static int sppp_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *p, struct net_device *orig_dev)
-{
- if (dev_net(dev) != &init_net) {
- kfree_skb(skb);
- return 0;
- }
-
- if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
- return NET_RX_DROP;
- sppp_input(dev,skb);
- return 0;
-}
-
-static struct packet_type sppp_packet_type = {
- .type = __constant_htons(ETH_P_WAN_PPP),
- .func = sppp_rcv,
-};
-
-static char banner[] __initdata =
- KERN_INFO "Cronyx Ltd, Synchronous PPP and CISCO HDLC (c) 1994\n"
- KERN_INFO "Linux port (c) 1998 Building Number Three Ltd & "
- "Jan \"Yenya\" Kasprzak.\n";
-
-static int __init sync_ppp_init(void)
-{
- if(debug)
- debug=PP_DEBUG;
- printk(banner);
- skb_queue_head_init(&tx_queue);
- dev_add_pack(&sppp_packet_type);
- return 0;
-}
-
-
-static void __exit sync_ppp_cleanup(void)
-{
- dev_remove_pack(&sppp_packet_type);
-}
-
-module_init(sync_ppp_init);
-module_exit(sync_ppp_cleanup);
-module_param(debug, int, 0);
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
index a8a5ca0ee6c2..4bffb67ebcae 100644
--- a/drivers/net/wan/wanxl.c
+++ b/drivers/net/wan/wanxl.c
@@ -220,7 +220,6 @@ static inline void wanxl_rx_intr(card_t *card)
#endif
dev->stats.rx_packets++;
dev->stats.rx_bytes += skb->len;
- dev->last_rx = jiffies;
skb->protocol = hdlc_type_trans(skb, dev);
netif_rx(skb);
skb = NULL;
@@ -411,12 +410,12 @@ static int wanxl_open(struct net_device *dev)
writel(1 << (DOORBELL_TO_CARD_OPEN_0 + port->node), dbr);
timeout = jiffies + HZ;
- do
+ do {
if (get_status(port)->open) {
netif_start_queue(dev);
return 0;
}
- while (time_after(timeout, jiffies));
+ } while (time_after(timeout, jiffies));
printk(KERN_ERR "%s: unable to open port\n", dev->name);
/* ask the card to close the port, should it be still alive */
@@ -438,10 +437,10 @@ static int wanxl_close(struct net_device *dev)
port->card->plx + PLX_DOORBELL_TO_CARD);
timeout = jiffies + HZ;
- do
+ do {
if (!get_status(port)->open)
break;
- while (time_after(timeout, jiffies));
+ } while (time_after(timeout, jiffies));
if (get_status(port)->open)
printk(KERN_ERR "%s: unable to close port\n", dev->name);
diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c
index 2a6c7a60756f..e6e2ce3e7bcf 100644
--- a/drivers/net/wan/x25_asy.c
+++ b/drivers/net/wan/x25_asy.c
@@ -64,7 +64,7 @@ static struct x25_asy *x25_asy_alloc(void)
if (dev == NULL)
break;
- sl = dev->priv;
+ sl = netdev_priv(dev);
/* Not in use ? */
if (!test_and_set_bit(SLF_INUSE, &sl->flags))
return sl;
@@ -86,7 +86,7 @@ static struct x25_asy *x25_asy_alloc(void)
return NULL;
/* Initialize channel control data */
- sl = dev->priv;
+ sl = netdev_priv(dev);
dev->base_addr = i;
/* register device so that it can be ifconfig'ed */
@@ -120,7 +120,7 @@ static void x25_asy_free(struct x25_asy *sl)
static int x25_asy_change_mtu(struct net_device *dev, int newmtu)
{
- struct x25_asy *sl = dev->priv;
+ struct x25_asy *sl = netdev_priv(dev);
unsigned char *xbuff, *rbuff;
int len = 2 * newmtu;
@@ -211,7 +211,6 @@ static void x25_asy_bump(struct x25_asy *sl)
printk(KERN_DEBUG "x25_asy: data received err - %d\n", err);
} else {
netif_rx(skb);
- sl->dev->last_rx = jiffies;
sl->stats.rx_packets++;
}
}
@@ -243,7 +242,7 @@ static void x25_asy_encaps(struct x25_asy *sl, unsigned char *icp, int len)
* if we did not request it before write operation.
* 14 Oct 1994 Dmitry Gorodchanin.
*/
- sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
+ set_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
actual = sl->tty->ops->write(sl->tty, sl->xbuff, count);
sl->xleft = count - actual;
sl->xhead = sl->xbuff + actual;
@@ -258,7 +257,7 @@ static void x25_asy_encaps(struct x25_asy *sl, unsigned char *icp, int len)
static void x25_asy_write_wakeup(struct tty_struct *tty)
{
int actual;
- struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
+ struct x25_asy *sl = tty->disc_data;
/* First make sure we're connected. */
if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev))
@@ -268,7 +267,7 @@ static void x25_asy_write_wakeup(struct tty_struct *tty)
/* Now serial buffer is almost free & we can start
* transmission of another packet */
sl->stats.tx_packets++;
- tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+ clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
x25_asy_unlock(sl);
return;
}
@@ -280,7 +279,7 @@ static void x25_asy_write_wakeup(struct tty_struct *tty)
static void x25_asy_timeout(struct net_device *dev)
{
- struct x25_asy *sl = dev->priv;
+ struct x25_asy *sl = netdev_priv(dev);
spin_lock(&sl->lock);
if (netif_queue_stopped(dev)) {
@@ -291,7 +290,7 @@ static void x25_asy_timeout(struct net_device *dev)
(tty_chars_in_buffer(sl->tty) || sl->xleft) ?
"bad line quality" : "driver error");
sl->xleft = 0;
- sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+ clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
x25_asy_unlock(sl);
}
spin_unlock(&sl->lock);
@@ -301,7 +300,7 @@ static void x25_asy_timeout(struct net_device *dev)
static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct x25_asy *sl = dev->priv;
+ struct x25_asy *sl = netdev_priv(dev);
int err;
if (!netif_running(sl->dev)) {
@@ -361,7 +360,6 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb)
{
- skb->dev->last_rx = jiffies;
return netif_rx(skb);
}
@@ -373,7 +371,7 @@ static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb)
static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb)
{
- struct x25_asy *sl = dev->priv;
+ struct x25_asy *sl = netdev_priv(dev);
spin_lock(&sl->lock);
if (netif_queue_stopped(sl->dev) || sl->tty == NULL) {
@@ -398,7 +396,7 @@ static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb)
static void x25_asy_connected(struct net_device *dev, int reason)
{
- struct x25_asy *sl = dev->priv;
+ struct x25_asy *sl = netdev_priv(dev);
struct sk_buff *skb;
unsigned char *ptr;
@@ -413,12 +411,11 @@ static void x25_asy_connected(struct net_device *dev, int reason)
skb->protocol = x25_type_trans(skb, sl->dev);
netif_rx(skb);
- sl->dev->last_rx = jiffies;
}
static void x25_asy_disconnected(struct net_device *dev, int reason)
{
- struct x25_asy *sl = dev->priv;
+ struct x25_asy *sl = netdev_priv(dev);
struct sk_buff *skb;
unsigned char *ptr;
@@ -433,7 +430,6 @@ static void x25_asy_disconnected(struct net_device *dev, int reason)
skb->protocol = x25_type_trans(skb, sl->dev);
netif_rx(skb);
- sl->dev->last_rx = jiffies;
}
static struct lapb_register_struct x25_asy_callbacks = {
@@ -450,7 +446,7 @@ static struct lapb_register_struct x25_asy_callbacks = {
/* Open the low-level part of the X.25 channel. Easy! */
static int x25_asy_open(struct net_device *dev)
{
- struct x25_asy *sl = dev->priv;
+ struct x25_asy *sl = netdev_priv(dev);
unsigned long len;
int err;
@@ -499,12 +495,12 @@ norbuff:
/* Close the low-level part of the X.25 channel. Easy! */
static int x25_asy_close(struct net_device *dev)
{
- struct x25_asy *sl = dev->priv;
+ struct x25_asy *sl = netdev_priv(dev);
int err;
spin_lock(&sl->lock);
if (sl->tty)
- sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+ clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
netif_stop_queue(dev);
sl->rcount = 0;
@@ -527,7 +523,7 @@ static int x25_asy_close(struct net_device *dev)
static void x25_asy_receive_buf(struct tty_struct *tty,
const unsigned char *cp, char *fp, int count)
{
- struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
+ struct x25_asy *sl = tty->disc_data;
if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev))
return;
@@ -555,7 +551,7 @@ static void x25_asy_receive_buf(struct tty_struct *tty,
static int x25_asy_open_tty(struct tty_struct *tty)
{
- struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
+ struct x25_asy *sl = tty->disc_data;
int err;
if (tty->ops->write == NULL)
@@ -596,7 +592,7 @@ static int x25_asy_open_tty(struct tty_struct *tty)
*/
static void x25_asy_close_tty(struct tty_struct *tty)
{
- struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
+ struct x25_asy *sl = tty->disc_data;
/* First make sure we're connected. */
if (!sl || sl->magic != X25_ASY_MAGIC)
@@ -615,7 +611,7 @@ static void x25_asy_close_tty(struct tty_struct *tty)
static struct net_device_stats *x25_asy_get_stats(struct net_device *dev)
{
- struct x25_asy *sl = dev->priv;
+ struct x25_asy *sl = netdev_priv(dev);
return &sl->stats;
}
@@ -624,7 +620,7 @@ static struct net_device_stats *x25_asy_get_stats(struct net_device *dev)
* STANDARD X.25 ENCAPSULATION *
************************************************************************/
-int x25_asy_esc(unsigned char *s, unsigned char *d, int len)
+static int x25_asy_esc(unsigned char *s, unsigned char *d, int len)
{
unsigned char *ptr = d;
unsigned char c;
@@ -696,7 +692,7 @@ static void x25_asy_unesc(struct x25_asy *sl, unsigned char s)
static int x25_asy_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
- struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
+ struct x25_asy *sl = tty->disc_data;
/* First make sure we're connected. */
if (!sl || sl->magic != X25_ASY_MAGIC)
@@ -717,7 +713,7 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file,
static int x25_asy_open_dev(struct net_device *dev)
{
- struct x25_asy *sl = dev->priv;
+ struct x25_asy *sl = netdev_priv(dev);
if (sl->tty == NULL)
return -ENODEV;
return 0;
@@ -726,7 +722,7 @@ static int x25_asy_open_dev(struct net_device *dev)
/* Initialise the X.25 driver. Called by the device init code */
static void x25_asy_setup(struct net_device *dev)
{
- struct x25_asy *sl = dev->priv;
+ struct x25_asy *sl = netdev_priv(dev);
sl->magic = X25_ASY_MAGIC;
sl->dev = dev;
@@ -793,7 +789,7 @@ static void __exit exit_x25_asy(void)
for (i = 0; i < x25_asy_maxdev; i++) {
dev = x25_asy_devs[i];
if (dev) {
- struct x25_asy *sl = dev->priv;
+ struct x25_asy *sl = netdev_priv(dev);
spin_lock_bh(&sl->lock);
if (sl->tty)
diff --git a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c
index 5bf7e01ef0e9..3d00971fe5ee 100644
--- a/drivers/net/wan/z85230.c
+++ b/drivers/net/wan/z85230.c
@@ -601,24 +601,18 @@ static void z8530_dma_status(struct z8530_channel *chan)
write_zsctrl(chan, RES_H_IUS);
}
-struct z8530_irqhandler z8530_dma_sync=
-{
+static struct z8530_irqhandler z8530_dma_sync = {
z8530_dma_rx,
z8530_dma_tx,
z8530_dma_status
};
-EXPORT_SYMBOL(z8530_dma_sync);
-
-struct z8530_irqhandler z8530_txdma_sync=
-{
+static struct z8530_irqhandler z8530_txdma_sync = {
z8530_rx,
z8530_dma_tx,
z8530_dma_status
};
-EXPORT_SYMBOL(z8530_txdma_sync);
-
/**
* z8530_rx_clear - Handle RX events from a stopped chip
* @c: Z8530 channel to shut up
@@ -710,7 +704,7 @@ EXPORT_SYMBOL(z8530_nop);
irqreturn_t z8530_interrupt(int irq, void *dev_id)
{
struct z8530_dev *dev=dev_id;
- u8 intr;
+ u8 uninitialized_var(intr);
static volatile int locker=0;
int work=0;
struct z8530_irqhandler *irqs;
diff --git a/drivers/net/wd.c b/drivers/net/wd.c
index fa14255282af..3c1edda08d3d 100644
--- a/drivers/net/wd.c
+++ b/drivers/net/wd.c
@@ -147,6 +147,20 @@ out:
}
#endif
+static const struct net_device_ops wd_netdev_ops = {
+ .ndo_open = wd_open,
+ .ndo_stop = wd_close,
+ .ndo_start_xmit = ei_start_xmit,
+ .ndo_tx_timeout = ei_tx_timeout,
+ .ndo_get_stats = ei_get_stats,
+ .ndo_set_multicast_list = ei_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = ei_poll,
+#endif
+};
+
static int __init wd_probe1(struct net_device *dev, int ioaddr)
{
int i;
@@ -156,7 +170,6 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr)
int word16 = 0; /* 0 = 8 bit, 1 = 16 bit */
const char *model_name;
static unsigned version_printed;
- DECLARE_MAC_BUF(mac);
for (i = 0; i < 8; i++)
checksum += inb(ioaddr + 8 + i);
@@ -178,8 +191,8 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr)
for (i = 0; i < 6; i++)
dev->dev_addr[i] = inb(ioaddr + 8 + i);
- printk("%s: WD80x3 at %#3x, %s",
- dev->name, ioaddr, print_mac(mac, dev->dev_addr));
+ printk("%s: WD80x3 at %#3x, %pM",
+ dev->name, ioaddr, dev->dev_addr);
/* The following PureData probe code was contributed by
Mike Jagdis <jaggy@purplet.demon.co.uk>. Puredata does software
@@ -332,11 +345,8 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr)
ei_status.block_input = &wd_block_input;
ei_status.block_output = &wd_block_output;
ei_status.get_8390_hdr = &wd_get_8390_hdr;
- dev->open = &wd_open;
- dev->stop = &wd_close;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = ei_poll;
-#endif
+
+ dev->netdev_ops = &wd_netdev_ops;
NS8390_init(dev, 0);
#if 1
@@ -366,8 +376,7 @@ wd_open(struct net_device *dev)
outb(ei_status.reg5, ioaddr+WD_CMDREG5);
outb(ei_status.reg0, ioaddr); /* WD_CMDREG */
- ei_open(dev);
- return 0;
+ return ei_open(dev);
}
static void
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 45bdf0b339bb..ea543fcf2687 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -123,154 +123,11 @@ config PCMCIA_RAYCS
To compile this driver as a module, choose M here: the module will be
called ray_cs. If unsure, say N.
-config IPW2100
- tristate "Intel PRO/Wireless 2100 Network Connection"
- depends on PCI && WLAN_80211
- select WIRELESS_EXT
- select FW_LOADER
- select IEEE80211
- ---help---
- A driver for the Intel PRO/Wireless 2100 Network
- Connection 802.11b wireless network adapter.
-
- See <file:Documentation/networking/README.ipw2100> for information on
- the capabilities currently enabled in this driver and for tips
- for debugging issues and problems.
-
- In order to use this driver, you will need a firmware image for it.
- You can obtain the firmware from
- <http://ipw2100.sf.net/>. Once you have the firmware image, you
- will need to place it in /lib/firmware.
-
- You will also very likely need the Wireless Tools in order to
- configure your card:
-
- <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
-
- It is recommended that you compile this driver as a module (M)
- rather than built-in (Y). This driver requires firmware at device
- initialization time, and when built-in this typically happens
- before the filesystem is accessible (hence firmware will be
- unavailable and initialization will fail). If you do choose to build
- this driver into your kernel image, you can avoid this problem by
- including the firmware and a firmware loader in an initramfs.
-
-config IPW2100_MONITOR
- bool "Enable promiscuous mode"
- depends on IPW2100
- ---help---
- Enables promiscuous/monitor mode support for the ipw2100 driver.
- With this feature compiled into the driver, you can switch to
- promiscuous mode via the Wireless Tool's Monitor mode. While in this
- mode, no packets can be sent.
-
-config IPW2100_DEBUG
- bool "Enable full debugging output in IPW2100 module."
- depends on IPW2100
- ---help---
- This option will enable debug tracing output for the IPW2100.
-
- This will result in the kernel module being ~60k larger. You can
- control which debug output is sent to the kernel log by setting the
- value in
-
- /sys/bus/pci/drivers/ipw2100/debug_level
-
- This entry will only exist if this option is enabled.
-
- If you are not trying to debug or develop the IPW2100 driver, you
- most likely want to say N here.
-
-config IPW2200
- tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection"
- depends on PCI && WLAN_80211
- select WIRELESS_EXT
- select FW_LOADER
- select IEEE80211
- ---help---
- A driver for the Intel PRO/Wireless 2200BG and 2915ABG Network
- Connection adapters.
-
- See <file:Documentation/networking/README.ipw2200> for
- information on the capabilities currently enabled in this
- driver and for tips for debugging issues and problems.
-
- In order to use this driver, you will need a firmware image for it.
- You can obtain the firmware from
- <http://ipw2200.sf.net/>. See the above referenced README.ipw2200
- for information on where to install the firmware images.
-
- You will also very likely need the Wireless Tools in order to
- configure your card:
-
- <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
-
- It is recommended that you compile this driver as a module (M)
- rather than built-in (Y). This driver requires firmware at device
- initialization time, and when built-in this typically happens
- before the filesystem is accessible (hence firmware will be
- unavailable and initialization will fail). If you do choose to build
- this driver into your kernel image, you can avoid this problem by
- including the firmware and a firmware loader in an initramfs.
-
-config IPW2200_MONITOR
- bool "Enable promiscuous mode"
- depends on IPW2200
- ---help---
- Enables promiscuous/monitor mode support for the ipw2200 driver.
- With this feature compiled into the driver, you can switch to
- promiscuous mode via the Wireless Tool's Monitor mode. While in this
- mode, no packets can be sent.
-
-config IPW2200_RADIOTAP
- bool "Enable radiotap format 802.11 raw packet support"
- depends on IPW2200_MONITOR
-
-config IPW2200_PROMISCUOUS
- bool "Enable creation of a RF radiotap promiscuous interface"
- depends on IPW2200_MONITOR
- select IPW2200_RADIOTAP
- ---help---
- Enables the creation of a second interface prefixed 'rtap'.
- This second interface will provide every received in radiotap
- format.
-
- This is useful for performing wireless network analysis while
- maintaining an active association.
-
- Example usage:
-
- % modprobe ipw2200 rtap_iface=1
- % ifconfig rtap0 up
- % tethereal -i rtap0
-
- If you do not specify 'rtap_iface=1' as a module parameter then
- the rtap interface will not be created and you will need to turn
- it on via sysfs:
-
- % echo 1 > /sys/bus/pci/drivers/ipw2200/*/rtap_iface
-
-config IPW2200_QOS
- bool "Enable QoS support"
- depends on IPW2200 && EXPERIMENTAL
-
-config IPW2200_DEBUG
- bool "Enable full debugging output in IPW2200 module."
- depends on IPW2200
- ---help---
- This option will enable low level debug tracing output for IPW2200.
-
- Note, normal debug code is already compiled in. This low level
- debug option enables debug on hot paths (e.g Tx, Rx, ISR) and
- will result in the kernel module being ~70 larger. Most users
- will typically not need this high verbosity debug information.
-
- If you are not sure, say N here.
-
config LIBERTAS
tristate "Marvell 8xxx Libertas WLAN driver support"
depends on WLAN_80211
select WIRELESS_EXT
+ select LIB80211
select FW_LOADER
---help---
A library for Marvell Libertas 8xxx devices.
@@ -357,6 +214,21 @@ config HERMES
configure your card and that /etc/pcmcia/wireless.opts works :
<http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>
+config HERMES_CACHE_FW_ON_INIT
+ bool "Cache Hermes firmware on driver initialisation"
+ depends on HERMES
+ default y
+ ---help---
+ Say Y to cache any firmware required by the Hermes drivers
+ on startup. The firmware will remain cached until the
+ driver is unloaded. The cache uses 64K of RAM.
+
+ Otherwise load the firmware from userspace as required. In
+ this case the driver should be unloaded and restarted
+ whenever the firmware is changed.
+
+ If you are not sure, say Y.
+
config APPLE_AIRPORT
tristate "Apple Airport support (built-in)"
depends on PPC_PMAC && HERMES
@@ -651,7 +523,7 @@ config RTL8180
config RTL8187
tristate "Realtek 8187 and 8187B USB support"
- depends on MAC80211 && USB && WLAN_80211 && EXPERIMENTAL
+ depends on MAC80211 && USB && WLAN_80211
select EEPROM_93CX6
---help---
This is a driver for RTL8187 and RTL8187B based cards.
@@ -711,6 +583,7 @@ config MAC80211_HWSIM
source "drivers/net/wireless/p54/Kconfig"
source "drivers/net/wireless/ath5k/Kconfig"
source "drivers/net/wireless/ath9k/Kconfig"
+source "drivers/net/wireless/ipw2x00/Kconfig"
source "drivers/net/wireless/iwlwifi/Kconfig"
source "drivers/net/wireless/hostap/Kconfig"
source "drivers/net/wireless/b43/Kconfig"
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index 59d2d805f60b..ac590e1ca8be 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -2,9 +2,8 @@
# Makefile for the Linux Wireless network device drivers.
#
-obj-$(CONFIG_IPW2100) += ipw2100.o
-
-obj-$(CONFIG_IPW2200) += ipw2200.o
+obj-$(CONFIG_IPW2100) += ipw2x00/
+obj-$(CONFIG_IPW2200) += ipw2x00/
obj-$(CONFIG_STRIP) += strip.o
obj-$(CONFIG_ARLAN) += arlan.o
@@ -16,14 +15,7 @@ obj-$(CONFIG_WAVELAN) += wavelan.o
obj-$(CONFIG_PCMCIA_NETWAVE) += netwave_cs.o
obj-$(CONFIG_PCMCIA_WAVELAN) += wavelan_cs.o
-obj-$(CONFIG_HERMES) += orinoco.o hermes.o hermes_dld.o
-obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o
-obj-$(CONFIG_APPLE_AIRPORT) += airport.o
-obj-$(CONFIG_PLX_HERMES) += orinoco_plx.o
-obj-$(CONFIG_PCI_HERMES) += orinoco_pci.o
-obj-$(CONFIG_TMD_HERMES) += orinoco_tmd.o
-obj-$(CONFIG_NORTEL_HERMES) += orinoco_nortel.o
-obj-$(CONFIG_PCMCIA_SPECTRUM) += spectrum_cs.o
+obj-$(CONFIG_HERMES) += orinoco/
obj-$(CONFIG_AIRO) += airo.o
obj-$(CONFIG_AIRO_CS) += airo_cs.o airo.o
@@ -38,6 +30,8 @@ obj-$(CONFIG_HOSTAP) += hostap/
obj-$(CONFIG_B43) += b43/
obj-$(CONFIG_B43LEGACY) += b43legacy/
obj-$(CONFIG_ZD1211RW) += zd1211rw/
+obj-$(CONFIG_RTL8180) += rtl818x/
+obj-$(CONFIG_RTL8187) += rtl818x/
# 16-bit wireless PCMCIA client drivers
obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o
@@ -50,12 +44,6 @@ obj-$(CONFIG_LIBERTAS) += libertas/
obj-$(CONFIG_LIBERTAS_THINFIRM) += libertas_tf/
-rtl8180-objs := rtl8180_dev.o rtl8180_rtl8225.o rtl8180_sa2400.o rtl8180_max2820.o rtl8180_grf5101.o
-rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o
-
-obj-$(CONFIG_RTL8180) += rtl8180.o
-obj-$(CONFIG_RTL8187) += rtl8187.o
-
obj-$(CONFIG_ADM8211) += adm8211.o
obj-$(CONFIG_IWLWIFI) += iwlwifi/
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c
index b2c050b68890..fc0897fb2239 100644
--- a/drivers/net/wireless/adm8211.c
+++ b/drivers/net/wireless/adm8211.c
@@ -341,15 +341,14 @@ static void adm8211_interrupt_tci(struct ieee80211_hw *dev)
pci_unmap_single(priv->pdev, info->mapping,
info->skb->len, PCI_DMA_TODEVICE);
- memset(&txi->status, 0, sizeof(txi->status));
+ ieee80211_tx_info_clear_status(txi);
+
skb_pull(skb, sizeof(struct adm8211_tx_hdr));
memcpy(skb_push(skb, info->hdrlen), skb->cb, info->hdrlen);
- if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK)) {
- if (status & TDES0_STATUS_ES)
- txi->status.excessive_retries = 1;
- else
- txi->flags |= IEEE80211_TX_STAT_ACK;
- }
+ if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) &&
+ !(status & TDES0_STATUS_ES))
+ txi->flags |= IEEE80211_TX_STAT_ACK;
+
ieee80211_tx_status_irqsafe(dev, skb);
info->skb = NULL;
@@ -1298,25 +1297,10 @@ static void adm8211_set_bssid(struct ieee80211_hw *dev, const u8 *bssid)
ADM8211_CSR_WRITE(ABDA1, reg);
}
-static int adm8211_set_ssid(struct ieee80211_hw *dev, u8 *ssid, size_t ssid_len)
-{
- struct adm8211_priv *priv = dev->priv;
- u8 buf[36];
-
- if (ssid_len > 32)
- return -EINVAL;
-
- memset(buf, 0, sizeof(buf));
- buf[0] = ssid_len;
- memcpy(buf + 1, ssid, ssid_len);
- adm8211_write_sram_bytes(dev, ADM8211_SRAM_SSID, buf, 33);
- /* TODO: configure beacon for adhoc? */
- return 0;
-}
-
-static int adm8211_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+static int adm8211_config(struct ieee80211_hw *dev, u32 changed)
{
struct adm8211_priv *priv = dev->priv;
+ struct ieee80211_conf *conf = &dev->conf;
int channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
if (channel != priv->channel) {
@@ -1338,13 +1322,6 @@ static int adm8211_config_interface(struct ieee80211_hw *dev,
memcpy(priv->bssid, conf->bssid, ETH_ALEN);
}
- if (conf->ssid_len != priv->ssid_len ||
- memcmp(conf->ssid, priv->ssid, conf->ssid_len)) {
- adm8211_set_ssid(dev, conf->ssid, conf->ssid_len);
- priv->ssid_len = conf->ssid_len;
- memcpy(priv->ssid, conf->ssid, conf->ssid_len);
- }
-
return 0;
}
@@ -1690,8 +1667,10 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
struct ieee80211_hdr *hdr;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_rate *txrate = ieee80211_get_tx_rate(dev, info);
+ u8 rc_flags;
- short_preamble = !!(txrate->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE);
+ rc_flags = info->control.rates[0].flags;
+ short_preamble = !!(rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
plcp_signal = txrate->bitrate;
hdr = (struct ieee80211_hdr *)skb->data;
@@ -1723,10 +1702,10 @@ static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
if (short_preamble)
txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_SHORT_PREAMBLE);
- if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
+ if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS)
txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_ENABLE_RTS);
- txhdr->retry_limit = info->control.retry_limit;
+ txhdr->retry_limit = info->control.rates[0].count;
adm8211_tx_raw(dev, skb, plcp_signal, hdrlen);
@@ -1791,7 +1770,6 @@ static int __devinit adm8211_probe(struct pci_dev *pdev,
int err;
u32 reg;
u8 perm_addr[ETH_ALEN];
- DECLARE_MAC_BUF(mac);
err = pci_enable_device(pdev);
if (err) {
@@ -1925,8 +1903,8 @@ static int __devinit adm8211_probe(struct pci_dev *pdev,
goto err_free_desc;
}
- printk(KERN_INFO "%s: hwaddr %s, Rev 0x%02x\n",
- wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr),
+ printk(KERN_INFO "%s: hwaddr %pM, Rev 0x%02x\n",
+ wiphy_name(dev->wiphy), dev->wiphy->perm_addr,
pdev->revision);
return 0;
diff --git a/drivers/net/wireless/adm8211.h b/drivers/net/wireless/adm8211.h
index 9b190ee26e90..4f6ab1322189 100644
--- a/drivers/net/wireless/adm8211.h
+++ b/drivers/net/wireless/adm8211.h
@@ -553,8 +553,6 @@ struct adm8211_priv {
int channel;
u8 bssid[ETH_ALEN];
- u8 ssid[32];
- size_t ssid_len;
u8 soft_rx_crc;
u8 retry_limit;
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 370133e492d2..fc4322ca669f 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -47,10 +47,11 @@
#include <linux/ioport.h>
#include <linux/pci.h>
#include <asm/uaccess.h>
-#include <net/ieee80211.h>
#include <linux/kthread.h>
#include <linux/freezer.h>
+#include <linux/ieee80211.h>
+
#include "airo.h"
#define DRV_NAME "airo"
@@ -1270,6 +1271,7 @@ static int flashrestart(struct airo_info *ai,struct net_device *dev);
#define airo_print_err(name, fmt, args...) \
airo_print(KERN_ERR, name, fmt, ##args)
+#define AIRO_FLASH(dev) (((struct airo_info *)dev->ml_priv)->flash)
/***********************************************************************
* MIC ROUTINES *
@@ -1865,7 +1867,7 @@ static void try_auto_wep(struct airo_info *ai)
}
static int airo_open(struct net_device *dev) {
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
int rc = 0;
if (test_bit(FLAG_FLASHING, &ai->flags))
@@ -1912,7 +1914,7 @@ static int airo_open(struct net_device *dev) {
static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) {
int npacks, pending;
unsigned long flags;
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
if (!skb) {
airo_print_err(dev->name, "%s: skb == NULL!",__func__);
@@ -1956,7 +1958,7 @@ static int mpi_send_packet (struct net_device *dev)
unsigned char *buffer;
s16 len;
__le16 *payloadLen;
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
u8 *sendbuf;
/* get a packet to send */
@@ -2085,7 +2087,7 @@ static void get_tx_error(struct airo_info *ai, s32 fid)
static void airo_end_xmit(struct net_device *dev) {
u16 status;
int i;
- struct airo_info *priv = dev->priv;
+ struct airo_info *priv = dev->ml_priv;
struct sk_buff *skb = priv->xmit.skb;
int fid = priv->xmit.fid;
u32 *fids = priv->fids;
@@ -2111,7 +2113,7 @@ static void airo_end_xmit(struct net_device *dev) {
static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
s16 len;
int i, j;
- struct airo_info *priv = dev->priv;
+ struct airo_info *priv = dev->ml_priv;
u32 *fids = priv->fids;
if ( skb == NULL ) {
@@ -2150,7 +2152,7 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
static void airo_end_xmit11(struct net_device *dev) {
u16 status;
int i;
- struct airo_info *priv = dev->priv;
+ struct airo_info *priv = dev->ml_priv;
struct sk_buff *skb = priv->xmit11.skb;
int fid = priv->xmit11.fid;
u32 *fids = priv->fids;
@@ -2176,7 +2178,7 @@ static void airo_end_xmit11(struct net_device *dev) {
static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
s16 len;
int i, j;
- struct airo_info *priv = dev->priv;
+ struct airo_info *priv = dev->ml_priv;
u32 *fids = priv->fids;
if (test_bit(FLAG_MPI, &priv->flags)) {
@@ -2220,7 +2222,7 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
static void airo_read_stats(struct net_device *dev)
{
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
StatsRid stats_rid;
__le32 *vals = stats_rid.vals;
@@ -2254,7 +2256,7 @@ static void airo_read_stats(struct net_device *dev)
static struct net_device_stats *airo_get_stats(struct net_device *dev)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
if (!test_bit(JOB_STATS, &local->jobs)) {
/* Get stats out of the card if available */
@@ -2281,7 +2283,7 @@ static void airo_set_promisc(struct airo_info *ai) {
}
static void airo_set_multicast_list(struct net_device *dev) {
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
if ((dev->flags ^ ai->flags) & IFF_PROMISC) {
change_bit(FLAG_PROMISC, &ai->flags);
@@ -2299,7 +2301,7 @@ static void airo_set_multicast_list(struct net_device *dev) {
static int airo_set_mac_address(struct net_device *dev, void *p)
{
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
struct sockaddr *addr = p;
readConfigRid(ai, 1);
@@ -2339,7 +2341,7 @@ static void del_airo_dev(struct airo_info *ai)
}
static int airo_close(struct net_device *dev) {
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
netif_stop_queue(dev);
@@ -2365,7 +2367,7 @@ static int airo_close(struct net_device *dev) {
void stop_airo_card( struct net_device *dev, int freeres )
{
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
set_bit(FLAG_RADIO_DOWN, &ai->flags);
disable_MAC(ai, 1);
@@ -2665,7 +2667,7 @@ static struct net_device *init_wifidev(struct airo_info *ai,
struct net_device *dev = alloc_netdev(0, "wifi%d", wifi_setup);
if (!dev)
return NULL;
- dev->priv = ethdev->priv;
+ dev->ml_priv = ethdev->ml_priv;
dev->irq = ethdev->irq;
dev->base_addr = ethdev->base_addr;
dev->wireless_data = ethdev->wireless_data;
@@ -2680,7 +2682,7 @@ static struct net_device *init_wifidev(struct airo_info *ai,
}
static int reset_card( struct net_device *dev , int lock) {
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
if (lock && down_interruptible(&ai->sem))
return -1;
@@ -2757,7 +2759,6 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
struct net_device *dev;
struct airo_info *ai;
int i, rc;
- DECLARE_MAC_BUF(mac);
/* Create the network device object. */
dev = alloc_netdev(sizeof(*ai), "", ether_setup);
@@ -2766,7 +2767,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
return NULL;
}
- ai = dev->priv;
+ ai = dev->ml_priv = netdev_priv(dev);
ai->wifidev = NULL;
ai->flags = 1 << FLAG_RADIO_DOWN;
ai->jobs = 0;
@@ -2860,15 +2861,14 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
goto err_out_reg;
set_bit(FLAG_REGISTERED,&ai->flags);
- airo_print_info(dev->name, "MAC enabled %s",
- print_mac(mac, dev->dev_addr));
+ airo_print_info(dev->name, "MAC enabled %pM", dev->dev_addr);
/* Allocate the transmit buffers */
if (probe && !test_bit(FLAG_MPI,&ai->flags))
for( i = 0; i < MAX_FIDS; i++ )
ai->fids[i] = transmit_allocate(ai,AIRO_DEF_MTU,i>=MAX_FIDS/2);
- if (setup_proc_entry(dev, dev->priv) < 0)
+ if (setup_proc_entry(dev, dev->ml_priv) < 0)
goto err_out_wifi;
return dev;
@@ -2917,8 +2917,7 @@ static int waitbusy (struct airo_info *ai) {
int reset_airo_card( struct net_device *dev )
{
int i;
- struct airo_info *ai = dev->priv;
- DECLARE_MAC_BUF(mac);
+ struct airo_info *ai = dev->ml_priv;
if (reset_card (dev, 1))
return -1;
@@ -2927,8 +2926,7 @@ int reset_airo_card( struct net_device *dev )
airo_print_err(dev->name, "MAC could not be enabled");
return -1;
}
- airo_print_info(dev->name, "MAC enabled %s",
- print_mac(mac, dev->dev_addr));
+ airo_print_info(dev->name, "MAC enabled %pM", dev->dev_addr);
/* Allocate the transmit buffers if needed */
if (!test_bit(FLAG_MPI,&ai->flags))
for( i = 0; i < MAX_FIDS; i++ )
@@ -2942,7 +2940,7 @@ int reset_airo_card( struct net_device *dev )
EXPORT_SYMBOL(reset_airo_card);
static void airo_send_event(struct net_device *dev) {
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
union iwreq_data wrqu;
StatusRid status_rid;
@@ -3019,7 +3017,7 @@ out:
static int airo_thread(void *data) {
struct net_device *dev = data;
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
int locked;
set_freezable();
@@ -3134,7 +3132,7 @@ static irqreturn_t airo_interrupt(int irq, void *dev_id)
struct net_device *dev = dev_id;
u16 status;
u16 fid;
- struct airo_info *apriv = dev->priv;
+ struct airo_info *apriv = dev->ml_priv;
u16 savedInterrupts = 0;
int handled = 0;
@@ -3369,7 +3367,6 @@ badrx:
skb->protocol = htons(ETH_P_802_2);
} else
skb->protocol = eth_type_trans(skb,dev);
- skb->dev->last_rx = jiffies;
skb->ip_summed = CHECKSUM_NONE;
netif_rx( skb );
@@ -3599,7 +3596,6 @@ badmic:
skb->ip_summed = CHECKSUM_NONE;
skb->protocol = eth_type_trans(skb, ai->dev);
- skb->dev->last_rx = jiffies;
netif_rx(skb);
}
badrx:
@@ -3611,7 +3607,7 @@ badrx:
}
}
-void mpi_receive_802_11 (struct airo_info *ai)
+static void mpi_receive_802_11(struct airo_info *ai)
{
RxFid rxd;
struct sk_buff *skb = NULL;
@@ -3693,7 +3689,6 @@ void mpi_receive_802_11 (struct airo_info *ai)
skb->pkt_type = PACKET_OTHERHOST;
skb->dev = ai->wifidev;
skb->protocol = htons(ETH_P_802_2);
- skb->dev->last_rx = jiffies;
skb->ip_summed = CHECKSUM_NONE;
netif_rx( skb );
badrx:
@@ -4604,7 +4599,7 @@ static int proc_status_open(struct inode *inode, struct file *file)
struct proc_data *data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
- struct airo_info *apriv = dev->priv;
+ struct airo_info *apriv = dev->ml_priv;
CapabilityRid cap_rid;
StatusRid status_rid;
u16 mode;
@@ -4687,7 +4682,7 @@ static int proc_stats_rid_open( struct inode *inode,
struct proc_data *data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
- struct airo_info *apriv = dev->priv;
+ struct airo_info *apriv = dev->ml_priv;
StatsRid stats;
int i, j;
__le32 *vals = stats.vals;
@@ -4750,7 +4745,7 @@ static void proc_config_on_close(struct inode *inode, struct file *file)
struct proc_data *data = file->private_data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
char *line;
if ( !data->writelen ) return;
@@ -4962,7 +4957,7 @@ static int proc_config_open(struct inode *inode, struct file *file)
struct proc_data *data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
int i;
__le16 mode;
@@ -5053,7 +5048,7 @@ static void proc_SSID_on_close(struct inode *inode, struct file *file)
struct proc_data *data = (struct proc_data *)file->private_data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
SsidRid SSID_rid;
int i;
char *p = data->wbuffer;
@@ -5096,7 +5091,7 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) {
struct proc_data *data = (struct proc_data *)file->private_data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
APListRid APList_rid;
int i;
@@ -5191,7 +5186,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
struct proc_data *data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
int i;
char key[16];
u16 index = 0;
@@ -5233,7 +5228,7 @@ static int proc_wepkey_open( struct inode *inode, struct file *file )
struct proc_data *data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
char *ptr;
WepKeyRid wkr;
__le16 lastindex;
@@ -5282,7 +5277,7 @@ static int proc_SSID_open(struct inode *inode, struct file *file)
struct proc_data *data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
int i;
char *ptr;
SsidRid SSID_rid;
@@ -5326,11 +5321,10 @@ static int proc_APList_open( struct inode *inode, struct file *file ) {
struct proc_data *data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
int i;
char *ptr;
APListRid APList_rid;
- DECLARE_MAC_BUF(mac);
if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
return -ENOMEM;
@@ -5354,8 +5348,7 @@ static int proc_APList_open( struct inode *inode, struct file *file ) {
// We end when we find a zero MAC
if ( !*(int*)APList_rid.ap[i] &&
!*(int*)&APList_rid.ap[i][2]) break;
- ptr += sprintf(ptr, "%s\n",
- print_mac(mac, APList_rid.ap[i]));
+ ptr += sprintf(ptr, "%pM\n", APList_rid.ap[i]);
}
if (i==0) ptr += sprintf(ptr, "Not using specific APs\n");
@@ -5368,13 +5361,12 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) {
struct proc_data *data;
struct proc_dir_entry *dp = PDE(inode);
struct net_device *dev = dp->data;
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
char *ptr;
BSSListRid BSSList_rid;
int rc;
/* If doLoseSync is not 1, we won't do a Lose Sync */
int doLoseSync = -1;
- DECLARE_MAC_BUF(mac);
if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
return -ENOMEM;
@@ -5411,8 +5403,8 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) {
we have to add a spin lock... */
rc = readBSSListRid(ai, doLoseSync, &BSSList_rid);
while(rc == 0 && BSSList_rid.index != cpu_to_le16(0xffff)) {
- ptr += sprintf(ptr, "%s %*s rssi = %d",
- print_mac(mac, BSSList_rid.bssid),
+ ptr += sprintf(ptr, "%pM %*s rssi = %d",
+ BSSList_rid.bssid,
(int)BSSList_rid.ssidLen,
BSSList_rid.ssid,
le16_to_cpu(BSSList_rid.dBm));
@@ -5447,7 +5439,7 @@ static int proc_close( struct inode *inode, struct file *file )
associated we will check every minute to see if anything has
changed. */
static void timer_func( struct net_device *dev ) {
- struct airo_info *apriv = dev->priv;
+ struct airo_info *apriv = dev->ml_priv;
/* We don't have a link so try changing the authtype */
readConfigRid(apriv, 0);
@@ -5518,7 +5510,7 @@ static void __devexit airo_pci_remove(struct pci_dev *pdev)
static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata(pdev);
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
Cmd cmd;
Resp rsp;
@@ -5550,7 +5542,7 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
static int airo_pci_resume(struct pci_dev *pdev)
{
struct net_device *dev = pci_get_drvdata(pdev);
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
pci_power_t prev_state = pdev->current_state;
pci_set_power_state(pdev, PCI_D0);
@@ -5729,7 +5721,7 @@ static int airo_set_freq(struct net_device *dev,
struct iw_freq *fwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
int rc = -EINPROGRESS; /* Call commit handler */
/* If setting by frequency, convert to a channel */
@@ -5774,7 +5766,7 @@ static int airo_get_freq(struct net_device *dev,
struct iw_freq *fwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
StatusRid status_rid; /* Card status info */
int ch;
@@ -5805,7 +5797,7 @@ static int airo_set_essid(struct net_device *dev,
struct iw_point *dwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
SsidRid SSID_rid; /* SSIDs */
/* Reload the list of current SSID */
@@ -5851,7 +5843,7 @@ static int airo_get_essid(struct net_device *dev,
struct iw_point *dwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
StatusRid status_rid; /* Card status info */
readStatusRid(local, &status_rid, 1);
@@ -5879,7 +5871,7 @@ static int airo_set_wap(struct net_device *dev,
struct sockaddr *awrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
Cmd cmd;
Resp rsp;
APListRid APList_rid;
@@ -5916,7 +5908,7 @@ static int airo_get_wap(struct net_device *dev,
struct sockaddr *awrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
StatusRid status_rid; /* Card status info */
readStatusRid(local, &status_rid, 1);
@@ -5937,7 +5929,7 @@ static int airo_set_nick(struct net_device *dev,
struct iw_point *dwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
/* Check the size of the string */
if(dwrq->length > 16) {
@@ -5960,7 +5952,7 @@ static int airo_get_nick(struct net_device *dev,
struct iw_point *dwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
readConfigRid(local, 1);
strncpy(extra, local->config.nodeName, 16);
@@ -5979,7 +5971,7 @@ static int airo_set_rate(struct net_device *dev,
struct iw_param *vwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
CapabilityRid cap_rid; /* Card capability info */
u8 brate = 0;
int i;
@@ -6049,7 +6041,7 @@ static int airo_get_rate(struct net_device *dev,
struct iw_param *vwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
StatusRid status_rid; /* Card status info */
readStatusRid(local, &status_rid, 1);
@@ -6071,7 +6063,7 @@ static int airo_set_rts(struct net_device *dev,
struct iw_param *vwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
int rthr = vwrq->value;
if(vwrq->disabled)
@@ -6095,7 +6087,7 @@ static int airo_get_rts(struct net_device *dev,
struct iw_param *vwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
readConfigRid(local, 1);
vwrq->value = le16_to_cpu(local->config.rtsThres);
@@ -6114,7 +6106,7 @@ static int airo_set_frag(struct net_device *dev,
struct iw_param *vwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
int fthr = vwrq->value;
if(vwrq->disabled)
@@ -6139,7 +6131,7 @@ static int airo_get_frag(struct net_device *dev,
struct iw_param *vwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
readConfigRid(local, 1);
vwrq->value = le16_to_cpu(local->config.fragThresh);
@@ -6158,7 +6150,7 @@ static int airo_set_mode(struct net_device *dev,
__u32 *uwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
int reset = 0;
readConfigRid(local, 1);
@@ -6221,7 +6213,7 @@ static int airo_get_mode(struct net_device *dev,
__u32 *uwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
readConfigRid(local, 1);
/* If not managed, assume it's ad-hoc */
@@ -6258,7 +6250,7 @@ static int airo_set_encode(struct net_device *dev,
struct iw_point *dwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
CapabilityRid cap_rid; /* Card capability info */
int perm = ( dwrq->flags & IW_ENCODE_TEMP ? 0 : 1 );
__le16 currentAuthType = local->config.authType;
@@ -6345,7 +6337,7 @@ static int airo_get_encode(struct net_device *dev,
struct iw_point *dwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
CapabilityRid cap_rid; /* Card capability info */
@@ -6393,7 +6385,7 @@ static int airo_set_encodeext(struct net_device *dev,
union iwreq_data *wrqu,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
struct iw_point *encoding = &wrqu->encoding;
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
CapabilityRid cap_rid; /* Card capability info */
@@ -6479,7 +6471,7 @@ static int airo_get_encodeext(struct net_device *dev,
union iwreq_data *wrqu,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
struct iw_point *encoding = &wrqu->encoding;
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
CapabilityRid cap_rid; /* Card capability info */
@@ -6542,7 +6534,7 @@ static int airo_set_auth(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
struct iw_param *param = &wrqu->param;
__le16 currentAuthType = local->config.authType;
@@ -6610,7 +6602,7 @@ static int airo_get_auth(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
struct iw_param *param = &wrqu->param;
__le16 currentAuthType = local->config.authType;
@@ -6659,7 +6651,7 @@ static int airo_set_txpow(struct net_device *dev,
struct iw_param *vwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
CapabilityRid cap_rid; /* Card capability info */
int i;
int rc = -EINVAL;
@@ -6696,7 +6688,7 @@ static int airo_get_txpow(struct net_device *dev,
struct iw_param *vwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
readConfigRid(local, 1);
vwrq->value = le16_to_cpu(local->config.txPower);
@@ -6716,7 +6708,7 @@ static int airo_set_retry(struct net_device *dev,
struct iw_param *vwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
int rc = -EINVAL;
if(vwrq->disabled) {
@@ -6754,7 +6746,7 @@ static int airo_get_retry(struct net_device *dev,
struct iw_param *vwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
vwrq->disabled = 0; /* Can't be disabled */
@@ -6785,7 +6777,7 @@ static int airo_get_range(struct net_device *dev,
struct iw_point *dwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
struct iw_range *range = (struct iw_range *) extra;
CapabilityRid cap_rid; /* Card capability info */
int i;
@@ -6910,7 +6902,7 @@ static int airo_set_power(struct net_device *dev,
struct iw_param *vwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
readConfigRid(local, 1);
if (vwrq->disabled) {
@@ -6967,7 +6959,7 @@ static int airo_get_power(struct net_device *dev,
struct iw_param *vwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
__le16 mode;
readConfigRid(local, 1);
@@ -6998,7 +6990,7 @@ static int airo_set_sens(struct net_device *dev,
struct iw_param *vwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
readConfigRid(local, 1);
local->config.rssiThreshold =
@@ -7017,7 +7009,7 @@ static int airo_get_sens(struct net_device *dev,
struct iw_param *vwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
readConfigRid(local, 1);
vwrq->value = le16_to_cpu(local->config.rssiThreshold);
@@ -7037,7 +7029,7 @@ static int airo_get_aplist(struct net_device *dev,
struct iw_point *dwrq,
char *extra)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
struct sockaddr *address = (struct sockaddr *) extra;
struct iw_quality qual[IW_MAX_AP];
BSSListRid BSSList;
@@ -7110,7 +7102,7 @@ static int airo_set_scan(struct net_device *dev,
struct iw_point *dwrq,
char *extra)
{
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
Cmd cmd;
Resp rsp;
int wake = 0;
@@ -7156,7 +7148,7 @@ static inline char *airo_translate_scan(struct net_device *dev,
char *end_buf,
BSSListRid *bss)
{
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
struct iw_event iwe; /* Temporary buffer */
__le16 capabilities;
char * current_val; /* For rates */
@@ -7274,56 +7266,53 @@ static inline char *airo_translate_scan(struct net_device *dev,
if (test_bit(FLAG_WPA_CAPABLE, &ai->flags)) {
unsigned int num_null_ies = 0;
u16 length = sizeof (bss->extra.iep);
- struct ieee80211_info_element *info_element =
- (struct ieee80211_info_element *) &bss->extra.iep;
+ u8 *ie = (void *)&bss->extra.iep;
- while ((length >= sizeof(*info_element)) && (num_null_ies < 2)) {
- if (sizeof(*info_element) + info_element->len > length) {
+ while ((length >= 2) && (num_null_ies < 2)) {
+ if (2 + ie[1] > length) {
/* Invalid element, don't continue parsing IE */
break;
}
- switch (info_element->id) {
- case MFIE_TYPE_SSID:
+ switch (ie[0]) {
+ case WLAN_EID_SSID:
/* Two zero-length SSID elements
* mean we're done parsing elements */
- if (!info_element->len)
+ if (!ie[1])
num_null_ies++;
break;
- case MFIE_TYPE_GENERIC:
- if (info_element->len >= 4 &&
- info_element->data[0] == 0x00 &&
- info_element->data[1] == 0x50 &&
- info_element->data[2] == 0xf2 &&
- info_element->data[3] == 0x01) {
+ case WLAN_EID_GENERIC:
+ if (ie[1] >= 4 &&
+ ie[2] == 0x00 &&
+ ie[3] == 0x50 &&
+ ie[4] == 0xf2 &&
+ ie[5] == 0x01) {
iwe.cmd = IWEVGENIE;
- iwe.u.data.length = min(info_element->len + 2,
- MAX_WPA_IE_LEN);
+ /* 64 is an arbitrary cut-off */
+ iwe.u.data.length = min(ie[1] + 2,
+ 64);
current_ev = iwe_stream_add_point(
info, current_ev,
- end_buf, &iwe,
- (char *) info_element);
+ end_buf, &iwe, ie);
}
break;
- case MFIE_TYPE_RSN:
+ case WLAN_EID_RSN:
iwe.cmd = IWEVGENIE;
- iwe.u.data.length = min(info_element->len + 2,
- MAX_WPA_IE_LEN);
+ /* 64 is an arbitrary cut-off */
+ iwe.u.data.length = min(ie[1] + 2, 64);
current_ev = iwe_stream_add_point(
info, current_ev, end_buf,
- &iwe, (char *) info_element);
+ &iwe, ie);
break;
default:
break;
}
- length -= sizeof(*info_element) + info_element->len;
- info_element =
- (struct ieee80211_info_element *)&info_element->
- data[info_element->len];
+ length -= 2 + ie[1];
+ ie += 2 + ie[1];
}
}
return current_ev;
@@ -7338,7 +7327,7 @@ static int airo_get_scan(struct net_device *dev,
struct iw_point *dwrq,
char *extra)
{
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
BSSListElement *net;
int err = 0;
char *current_ev = extra;
@@ -7382,7 +7371,7 @@ static int airo_config_commit(struct net_device *dev,
void *zwrq, /* NULL */
char *extra) /* NULL */
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
if (!test_bit (FLAG_COMMIT, &local->flags))
return 0;
@@ -7527,7 +7516,7 @@ static const struct iw_handler_def airo_handler_def =
static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
int rc = 0;
- struct airo_info *ai = (struct airo_info *)dev->priv;
+ struct airo_info *ai = dev->ml_priv;
if (ai->power.event)
return 0;
@@ -7655,7 +7644,7 @@ static void airo_read_wireless_stats(struct airo_info *local)
static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
{
- struct airo_info *local = dev->priv;
+ struct airo_info *local = dev->ml_priv;
if (!test_bit(JOB_WSTATS, &local->jobs)) {
/* Get stats out of the card if available */
@@ -7680,7 +7669,7 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
unsigned short ridcode;
unsigned char *iobuf;
int len;
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
if (test_bit(FLAG_FLASHING, &ai->flags))
return -EIO;
@@ -7746,7 +7735,7 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
*/
static int writerids(struct net_device *dev, aironet_ioctl *comp) {
- struct airo_info *ai = dev->priv;
+ struct airo_info *ai = dev->ml_priv;
int ridcode;
int enabled;
static int (* writer)(struct airo_info *, u16 rid, const void *, int, int);
@@ -7869,41 +7858,41 @@ static int flashcard(struct net_device *dev, aironet_ioctl *comp) {
switch(comp->command)
{
case AIROFLSHRST:
- return cmdreset((struct airo_info *)dev->priv);
+ return cmdreset((struct airo_info *)dev->ml_priv);
case AIROFLSHSTFL:
- if (!((struct airo_info *)dev->priv)->flash &&
- (((struct airo_info *)dev->priv)->flash = kmalloc (FLASHSIZE, GFP_KERNEL)) == NULL)
+ if (!AIRO_FLASH(dev) &&
+ (AIRO_FLASH(dev) = kmalloc(FLASHSIZE, GFP_KERNEL)) == NULL)
return -ENOMEM;
- return setflashmode((struct airo_info *)dev->priv);
+ return setflashmode((struct airo_info *)dev->ml_priv);
case AIROFLSHGCHR: /* Get char from aux */
if(comp->len != sizeof(int))
return -EINVAL;
if (copy_from_user(&z,comp->data,comp->len))
return -EFAULT;
- return flashgchar((struct airo_info *)dev->priv,z,8000);
+ return flashgchar((struct airo_info *)dev->ml_priv, z, 8000);
case AIROFLSHPCHR: /* Send char to card. */
if(comp->len != sizeof(int))
return -EINVAL;
if (copy_from_user(&z,comp->data,comp->len))
return -EFAULT;
- return flashpchar((struct airo_info *)dev->priv,z,8000);
+ return flashpchar((struct airo_info *)dev->ml_priv, z, 8000);
case AIROFLPUTBUF: /* Send 32k to card */
- if (!((struct airo_info *)dev->priv)->flash)
+ if (!AIRO_FLASH(dev))
return -ENOMEM;
if(comp->len > FLASHSIZE)
return -EINVAL;
- if(copy_from_user(((struct airo_info *)dev->priv)->flash,comp->data,comp->len))
+ if (copy_from_user(AIRO_FLASH(dev), comp->data, comp->len))
return -EFAULT;
- flashputbuf((struct airo_info *)dev->priv);
+ flashputbuf((struct airo_info *)dev->ml_priv);
return 0;
case AIRORESTART:
- if(flashrestart((struct airo_info *)dev->priv,dev))
+ if (flashrestart((struct airo_info *)dev->ml_priv, dev))
return -EIO;
return 0;
}
diff --git a/drivers/net/wireless/arlan-main.c b/drivers/net/wireless/arlan-main.c
index dec5e874a54d..bfca15da6f0f 100644
--- a/drivers/net/wireless/arlan-main.c
+++ b/drivers/net/wireless/arlan-main.c
@@ -1467,19 +1467,17 @@ static void arlan_rx_interrupt(struct net_device *dev, u_char rxStatus, u_short
else if (hw_dst_addr[1] == 0x40)
printk(KERN_ERR "%s m/bcast 0x0140 \n", dev->name);
while (dmi)
- { if (dmi->dmi_addrlen == 6)
- {
- DECLARE_MAC_BUF(mac);
+ {
+ if (dmi->dmi_addrlen == 6) {
if (arlan_debug & ARLAN_DEBUG_HEADER_DUMP)
- printk(KERN_ERR "%s mcl %s\n",
- dev->name, print_mac(mac, dmi->dmi_addr));
+ printk(KERN_ERR "%s mcl %pM\n",
+ dev->name, dmi->dmi_addr);
for (i = 0; i < 6; i++)
if (dmi->dmi_addr[i] != hw_dst_addr[i])
break;
if (i == 6)
break;
- }
- else
+ } else
printk(KERN_ERR "%s: invalid multicast address length given.\n", dev->name);
dmi = dmi->next;
}
@@ -1512,18 +1510,14 @@ static void arlan_rx_interrupt(struct net_device *dev, u_char rxStatus, u_short
{
char immedDestAddress[6];
char immedSrcAddress[6];
- DECLARE_MAC_BUF(mac);
- DECLARE_MAC_BUF(mac2);
- DECLARE_MAC_BUF(mac3);
- DECLARE_MAC_BUF(mac4);
memcpy_fromio(immedDestAddress, arlan->immedDestAddress, 6);
memcpy_fromio(immedSrcAddress, arlan->immedSrcAddress, 6);
- printk(KERN_WARNING "%s t %s f %s imd %s ims %s\n",
- dev->name, print_mac(mac, skbtmp),
- print_mac(mac2, &skbtmp[6]),
- print_mac(mac3, immedDestAddress),
- print_mac(mac4, immedSrcAddress));
+ printk(KERN_WARNING "%s t %pM f %pM imd %pM ims %pM\n",
+ dev->name, skbtmp,
+ &skbtmp[6],
+ immedDestAddress,
+ immedSrcAddress);
}
skb->protocol = eth_type_trans(skb, dev);
IFDEBUG(ARLAN_DEBUG_HEADER_DUMP)
@@ -1535,7 +1529,6 @@ static void arlan_rx_interrupt(struct net_device *dev, u_char rxStatus, u_short
printk(KERN_WARNING "arlan kernel pkt type trans %x \n", skb->protocol);
}
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
}
diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h
index 53ea439aff48..183ffc8e62ca 100644
--- a/drivers/net/wireless/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath5k/ath5k.h
@@ -507,11 +507,15 @@ enum ath5k_tx_queue_id {
#define AR5K_TXQ_FLAG_TXEOLINT_ENABLE 0x0004 /* Enable TXEOL interrupt -not used- */
#define AR5K_TXQ_FLAG_TXDESCINT_ENABLE 0x0008 /* Enable TXDESC interrupt -not used- */
#define AR5K_TXQ_FLAG_TXURNINT_ENABLE 0x0010 /* Enable TXURN interrupt */
-#define AR5K_TXQ_FLAG_BACKOFF_DISABLE 0x0020 /* Disable random post-backoff */
-#define AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE 0x0040 /* Enable ready time expiry policy (?)*/
-#define AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE 0x0080 /* Enable backoff while bursting */
-#define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS 0x0100 /* Disable backoff while bursting */
-#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x0200 /* Enable hw compression -not implemented-*/
+#define AR5K_TXQ_FLAG_CBRORNINT_ENABLE 0x0020 /* Enable CBRORN interrupt */
+#define AR5K_TXQ_FLAG_CBRURNINT_ENABLE 0x0040 /* Enable CBRURN interrupt */
+#define AR5K_TXQ_FLAG_QTRIGINT_ENABLE 0x0080 /* Enable QTRIG interrupt */
+#define AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE 0x0100 /* Enable TXNOFRM interrupt */
+#define AR5K_TXQ_FLAG_BACKOFF_DISABLE 0x0200 /* Disable random post-backoff */
+#define AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE 0x0300 /* Enable ready time expiry policy (?)*/
+#define AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE 0x0800 /* Enable backoff while bursting */
+#define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS 0x1000 /* Disable backoff while bursting */
+#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x2000 /* Enable hw compression -not implemented-*/
/*
* A struct to hold tx queue's parameters
@@ -817,13 +821,6 @@ struct ath5k_athchan_2ghz {
return (false); \
} while (0)
-enum ath5k_ant_setting {
- AR5K_ANT_VARIABLE = 0, /* variable by programming */
- AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */
- AR5K_ANT_FIXED_B = 2, /* fixed to 11b frequencies */
- AR5K_ANT_MAX = 3,
-};
-
/*
* Hardware interrupt abstraction
*/
@@ -853,7 +850,7 @@ enum ath5k_ant_setting {
* checked. We should do this with ath5k_hw_update_mib_counters() but
* it seems we should also then do some noise immunity work.
* @AR5K_INT_RXPHY: RX PHY Error
- * @AR5K_INT_RXKCM: ??
+ * @AR5K_INT_RXKCM: RX Key cache miss
* @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a
* beacon that must be handled in software. The alternative is if you
* have VEOL support, in that case you let the hardware deal with things.
@@ -869,7 +866,7 @@ enum ath5k_ant_setting {
* @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA
* errors. These types of errors we can enable seem to be of type
* AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR.
- * @AR5K_INT_GLOBAL: Seems to be used to clear and set the IER
+ * @AR5K_INT_GLOBAL: Used to clear and set the IER
* @AR5K_INT_NOCARD: signals the card has been removed
* @AR5K_INT_COMMON: common interrupts shared amogst MACs with the same
* bit value
@@ -881,36 +878,61 @@ enum ath5k_ant_setting {
* MACs.
*/
enum ath5k_int {
- AR5K_INT_RX = 0x00000001, /* Not common */
+ AR5K_INT_RXOK = 0x00000001,
AR5K_INT_RXDESC = 0x00000002,
+ AR5K_INT_RXERR = 0x00000004,
AR5K_INT_RXNOFRM = 0x00000008,
AR5K_INT_RXEOL = 0x00000010,
AR5K_INT_RXORN = 0x00000020,
- AR5K_INT_TX = 0x00000040, /* Not common */
+ AR5K_INT_TXOK = 0x00000040,
AR5K_INT_TXDESC = 0x00000080,
+ AR5K_INT_TXERR = 0x00000100,
+ AR5K_INT_TXNOFRM = 0x00000200,
+ AR5K_INT_TXEOL = 0x00000400,
AR5K_INT_TXURN = 0x00000800,
AR5K_INT_MIB = 0x00001000,
+ AR5K_INT_SWI = 0x00002000,
AR5K_INT_RXPHY = 0x00004000,
AR5K_INT_RXKCM = 0x00008000,
AR5K_INT_SWBA = 0x00010000,
+ AR5K_INT_BRSSI = 0x00020000,
AR5K_INT_BMISS = 0x00040000,
- AR5K_INT_BNR = 0x00100000, /* Not common */
- AR5K_INT_GPIO = 0x01000000,
- AR5K_INT_FATAL = 0x40000000, /* Not common */
- AR5K_INT_GLOBAL = 0x80000000,
-
- AR5K_INT_COMMON = AR5K_INT_RXNOFRM
- | AR5K_INT_RXDESC
- | AR5K_INT_RXEOL
- | AR5K_INT_RXORN
- | AR5K_INT_TXURN
- | AR5K_INT_TXDESC
- | AR5K_INT_MIB
- | AR5K_INT_RXPHY
- | AR5K_INT_RXKCM
- | AR5K_INT_SWBA
- | AR5K_INT_BMISS
- | AR5K_INT_GPIO,
+ AR5K_INT_FATAL = 0x00080000, /* Non common */
+ AR5K_INT_BNR = 0x00100000, /* Non common */
+ AR5K_INT_TIM = 0x00200000, /* Non common */
+ AR5K_INT_DTIM = 0x00400000, /* Non common */
+ AR5K_INT_DTIM_SYNC = 0x00800000, /* Non common */
+ AR5K_INT_GPIO = 0x01000000,
+ AR5K_INT_BCN_TIMEOUT = 0x02000000, /* Non common */
+ AR5K_INT_CAB_TIMEOUT = 0x04000000, /* Non common */
+ AR5K_INT_RX_DOPPLER = 0x08000000, /* Non common */
+ AR5K_INT_QCBRORN = 0x10000000, /* Non common */
+ AR5K_INT_QCBRURN = 0x20000000, /* Non common */
+ AR5K_INT_QTRIG = 0x40000000, /* Non common */
+ AR5K_INT_GLOBAL = 0x80000000,
+
+ AR5K_INT_COMMON = AR5K_INT_RXOK
+ | AR5K_INT_RXDESC
+ | AR5K_INT_RXERR
+ | AR5K_INT_RXNOFRM
+ | AR5K_INT_RXEOL
+ | AR5K_INT_RXORN
+ | AR5K_INT_TXOK
+ | AR5K_INT_TXDESC
+ | AR5K_INT_TXERR
+ | AR5K_INT_TXNOFRM
+ | AR5K_INT_TXEOL
+ | AR5K_INT_TXURN
+ | AR5K_INT_MIB
+ | AR5K_INT_SWI
+ | AR5K_INT_RXPHY
+ | AR5K_INT_RXKCM
+ | AR5K_INT_SWBA
+ | AR5K_INT_BRSSI
+ | AR5K_INT_BMISS
+ | AR5K_INT_GPIO
+ | AR5K_INT_GLOBAL,
+
AR5K_INT_NOCARD = 0xffffffff
};
@@ -1030,6 +1052,7 @@ struct ath5k_hw {
bool ah_calibration;
bool ah_running;
bool ah_single_chip;
+ bool ah_combined_mic;
enum ath5k_rfgain ah_rf_gain;
u32 ah_mac_srev;
@@ -1064,10 +1087,11 @@ struct ath5k_hw {
u8 ah_sta_id[ETH_ALEN];
- /* Current BSSID we are trying to assoc to / creating.
+ /* Current BSSID we are trying to assoc to / create.
* This is passed by mac80211 on config_interface() and cached here for
* use in resets */
u8 ah_bssid[ETH_ALEN];
+ u8 ah_bssid_mask[ETH_ALEN];
u32 ah_gpio[AR5K_MAX_GPIO];
int ah_gpio_npins;
@@ -1081,6 +1105,11 @@ struct ath5k_hw {
u32 ah_txq_imr_txurn;
u32 ah_txq_imr_txdesc;
u32 ah_txq_imr_txeol;
+ u32 ah_txq_imr_cbrorn;
+ u32 ah_txq_imr_cbrurn;
+ u32 ah_txq_imr_qtrig;
+ u32 ah_txq_imr_nofrm;
+ u32 ah_txq_isr;
u32 *ah_rf_banks;
size_t ah_rf_banks_size;
struct ath5k_gain ah_gain;
@@ -1321,4 +1350,9 @@ static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits)
return retval;
}
+static inline int ath5k_pad_size(int hdrlen)
+{
+ return (hdrlen < 24) ? 0 : hdrlen & 3;
+}
+
#endif
diff --git a/drivers/net/wireless/ath5k/attach.c b/drivers/net/wireless/ath5k/attach.c
index 51d569883cdd..dea378f76731 100644
--- a/drivers/net/wireless/ath5k/attach.c
+++ b/drivers/net/wireless/ath5k/attach.c
@@ -106,7 +106,7 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
{
struct ath5k_hw *ah;
struct pci_dev *pdev = sc->pdev;
- u8 mac[ETH_ALEN];
+ u8 mac[ETH_ALEN] = {};
int ret;
u32 srev;
@@ -317,15 +317,15 @@ struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc, u8 mac_version)
goto err_free;
}
- /* Set MAC address */
- ret = ath5k_eeprom_read_mac(ah, mac);
- if (ret) {
- ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n",
- sc->pdev->device);
- goto err_free;
+ if (srev >= AR5K_SREV_AR2414) {
+ ah->ah_combined_mic = true;
+ AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE,
+ AR5K_MISC_MODE_COMBINED_MIC);
}
+ /* MAC address is cleared until add_interface */
ath5k_hw_set_lladdr(ah, mac);
+
/* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */
memset(ah->ah_bssid, 0xff, ETH_ALEN);
ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 2d14255eb103..4af2607deec0 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -60,6 +60,9 @@
#include "debug.h"
static int ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */
+static int modparam_nohwcrypt;
+module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
/******************\
@@ -197,7 +200,7 @@ static int ath5k_pci_resume(struct pci_dev *pdev);
#endif /* CONFIG_PM */
static struct pci_driver ath5k_pci_driver = {
- .name = "ath5k_pci",
+ .name = KBUILD_MODNAME,
.id_table = ath5k_pci_id_table,
.probe = ath5k_pci_probe,
.remove = __devexit_p(ath5k_pci_remove),
@@ -219,8 +222,7 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf);
static void ath5k_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf);
-static int ath5k_config(struct ieee80211_hw *hw,
- struct ieee80211_conf *conf);
+static int ath5k_config(struct ieee80211_hw *hw, u32 changed);
static int ath5k_config_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_if_conf *conf);
@@ -238,7 +240,7 @@ static int ath5k_get_tx_stats(struct ieee80211_hw *hw,
struct ieee80211_tx_queue_stats *stats);
static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
static void ath5k_reset_tsf(struct ieee80211_hw *hw);
-static int ath5k_beacon_update(struct ieee80211_hw *hw,
+static int ath5k_beacon_update(struct ath5k_softc *sc,
struct sk_buff *skb);
static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -548,8 +550,8 @@ ath5k_pci_probe(struct pci_dev *pdev,
/* set up multi-rate retry capabilities */
if (sc->ah->ah_version == AR5K_AR5212) {
- hw->max_altrates = 3;
- hw->max_altrate_tries = 11;
+ hw->max_rates = 4;
+ hw->max_rate_tries = 11;
}
/* Finish private driver data initialization */
@@ -711,7 +713,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
{
struct ath5k_softc *sc = hw->priv;
struct ath5k_hw *ah = sc->ah;
- u8 mac[ETH_ALEN];
+ u8 mac[ETH_ALEN] = {};
int ret;
ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device);
@@ -781,7 +783,13 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc);
setup_timer(&sc->calib_tim, ath5k_calibrate, (unsigned long)sc);
- ath5k_hw_get_lladdr(ah, mac);
+ ret = ath5k_eeprom_read_mac(ah, mac);
+ if (ret) {
+ ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n",
+ sc->pdev->device);
+ goto err_queues;
+ }
+
SET_IEEE80211_PERM_ADDR(hw, mac);
/* All MAC address bits matter for ACKs */
memset(sc->bssidmask, 0xff, ETH_ALEN);
@@ -1188,7 +1196,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL,
(sc->power_level * 2),
ieee80211_get_tx_rate(sc->hw, info)->hw_value,
- info->control.retry_limit, keyidx, 0, flags, 0, 0);
+ info->control.rates[0].count, keyidx, 0, flags, 0, 0);
if (ret)
goto err_unmap;
@@ -1200,7 +1208,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf)
break;
mrr_rate[i] = rate->hw_value;
- mrr_tries[i] = info->control.retries[i].limit;
+ mrr_tries[i] = info->control.rates[i + 1].count;
}
ah->ah_setup_mrr_tx_desc(ah, ds,
@@ -1660,7 +1668,7 @@ ath5k_tasklet_rx(unsigned long data)
struct ath5k_desc *ds;
int ret;
int hdrlen;
- int pad;
+ int padsize;
spin_lock(&sc->rxbuflock);
if (list_empty(&sc->rxbuf)) {
@@ -1745,16 +1753,19 @@ accept:
skb_put(skb, rs.rs_datalen);
- /*
- * the hardware adds a padding to 4 byte boundaries between
- * the header and the payload data if the header length is
- * not multiples of 4 - remove it
- */
+ /* The MAC header is padded to have 32-bit boundary if the
+ * packet payload is non-zero. The general calculation for
+ * padsize would take into account odd header lengths:
+ * padsize = (4 - hdrlen % 4) % 4; However, since only
+ * even-length headers are used, padding can only be 0 or 2
+ * bytes and we can optimize this a bit. In addition, we must
+ * not try to remove padding from short control frames that do
+ * not have payload. */
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
- if (hdrlen & 3) {
- pad = hdrlen % 4;
- memmove(skb->data + pad, skb->data, hdrlen);
- skb_pull(skb, pad);
+ padsize = ath5k_pad_size(hdrlen);
+ if (padsize) {
+ memmove(skb->data + padsize, skb->data, hdrlen);
+ skb_pull(skb, padsize);
}
/*
@@ -1785,7 +1796,17 @@ accept:
rxs.noise = sc->ah->ah_noise_floor;
rxs.signal = rxs.noise + rs.rs_rssi;
- rxs.qual = rs.rs_rssi * 100 / 64;
+
+ /* An rssi of 35 indicates you should be able use
+ * 54 Mbps reliably. A more elaborate scheme can be used
+ * here but it requires a map of SNR/throughput for each
+ * possible mode used */
+ rxs.qual = rs.rs_rssi * 100 / 35;
+
+ /* rssi can be more than 35 though, anything above that
+ * should be considered at 100% */
+ if (rxs.qual > 100)
+ rxs.qual = 100;
rxs.antenna = rs.rs_antenna;
rxs.rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate);
@@ -1846,30 +1867,26 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq)
pci_unmap_single(sc->pdev, bf->skbaddr, skb->len,
PCI_DMA_TODEVICE);
- memset(&info->status, 0, sizeof(info->status));
- info->tx_rate_idx = ath5k_hw_to_driver_rix(sc,
- ts.ts_rate[ts.ts_final_idx]);
- info->status.retry_count = ts.ts_longretry;
-
+ ieee80211_tx_info_clear_status(info);
for (i = 0; i < 4; i++) {
- struct ieee80211_tx_altrate *r =
- &info->status.retries[i];
+ struct ieee80211_tx_rate *r =
+ &info->status.rates[i];
if (ts.ts_rate[i]) {
- r->rate_idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]);
- r->limit = ts.ts_retry[i];
+ r->idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]);
+ r->count = ts.ts_retry[i];
} else {
- r->rate_idx = -1;
- r->limit = 0;
+ r->idx = -1;
+ r->count = 0;
}
}
- info->status.excessive_retries = 0;
+ /* count the successful attempt as well */
+ info->status.rates[ts.ts_final_idx].count++;
+
if (unlikely(ts.ts_status)) {
sc->ll_stats.dot11ACKFailureCount++;
- if (ts.ts_status & AR5K_TXERR_XRETRY)
- info->status.excessive_retries = 1;
- else if (ts.ts_status & AR5K_TXERR_FILT)
+ if (ts.ts_status & AR5K_TXERR_FILT)
info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
} else {
info->flags |= IEEE80211_TX_STAT_ACK;
@@ -2143,8 +2160,6 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
*
* In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
* interrupts to detect TSF updates only.
- *
- * AP mode is missing.
*/
static void
ath5k_beacon_config(struct ath5k_softc *sc)
@@ -2157,7 +2172,9 @@ ath5k_beacon_config(struct ath5k_softc *sc)
if (sc->opmode == NL80211_IFTYPE_STATION) {
sc->imask |= AR5K_INT_BMISS;
- } else if (sc->opmode == NL80211_IFTYPE_ADHOC) {
+ } else if (sc->opmode == NL80211_IFTYPE_ADHOC ||
+ sc->opmode == NL80211_IFTYPE_MESH_POINT ||
+ sc->opmode == NL80211_IFTYPE_AP) {
/*
* In IBSS mode we use a self-linked tx descriptor and let the
* hardware send the beacons automatically. We have to load it
@@ -2169,13 +2186,15 @@ ath5k_beacon_config(struct ath5k_softc *sc)
sc->imask |= AR5K_INT_SWBA;
- if (ath5k_hw_hasveol(ah)) {
- spin_lock(&sc->block);
- ath5k_beacon_send(sc);
- spin_unlock(&sc->block);
- }
+ if (sc->opmode == NL80211_IFTYPE_ADHOC) {
+ if (ath5k_hw_hasveol(ah)) {
+ spin_lock(&sc->block);
+ ath5k_beacon_send(sc);
+ spin_unlock(&sc->block);
+ }
+ } else
+ ath5k_beacon_update_timers(sc, -1);
}
- /* TODO else AP */
ath5k_hw_set_imr(ah, sc->imask);
}
@@ -2215,9 +2234,9 @@ ath5k_init(struct ath5k_softc *sc, bool is_resume)
*/
sc->curchan = sc->hw->conf.channel;
sc->curband = &sc->sbands[sc->curchan->band];
- sc->imask = AR5K_INT_RX | AR5K_INT_TX | AR5K_INT_RXEOL |
- AR5K_INT_RXORN | AR5K_INT_FATAL | AR5K_INT_GLOBAL |
- AR5K_INT_MIB;
+ sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL |
+ AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL |
+ AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_MIB;
ret = ath5k_reset(sc, false, false);
if (ret)
goto done;
@@ -2409,9 +2428,10 @@ ath5k_intr(int irq, void *dev_id)
/* bump tx trigger level */
ath5k_hw_update_tx_triglevel(ah, true);
}
- if (status & AR5K_INT_RX)
+ if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR))
tasklet_schedule(&sc->rxtq);
- if (status & AR5K_INT_TX)
+ if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC
+ | AR5K_INT_TXERR | AR5K_INT_TXEOL))
tasklet_schedule(&sc->txtq);
if (status & AR5K_INT_BMISS) {
}
@@ -2527,8 +2547,7 @@ ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led,
led->led_dev.brightness_set = ath5k_led_brightness_set;
err = led_classdev_register(&sc->pdev->dev, &led->led_dev);
- if (err)
- {
+ if (err) {
ATH5K_WARN(sc, "could not register LED %s\n", name);
led->sc = NULL;
}
@@ -2607,7 +2626,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
struct ath5k_buf *bf;
unsigned long flags;
int hdrlen;
- int pad;
+ int padsize;
ath5k_debug_dump_skb(sc, skb, "TX ", 1);
@@ -2619,15 +2638,16 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
* if this is not the case we add the padding after the header
*/
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
- if (hdrlen & 3) {
- pad = hdrlen % 4;
- if (skb_headroom(skb) < pad) {
+ padsize = ath5k_pad_size(hdrlen);
+ if (padsize) {
+
+ if (skb_headroom(skb) < padsize) {
ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough"
- " headroom to pad %d\n", hdrlen, pad);
+ " headroom to pad %d\n", hdrlen, padsize);
return -1;
}
- skb_push(skb, pad);
- memmove(skb->data, skb->data+pad, hdrlen);
+ skb_push(skb, padsize);
+ memmove(skb->data, skb->data+padsize, hdrlen);
}
spin_lock_irqsave(&sc->txbuflock, flags);
@@ -2746,8 +2766,10 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
sc->vif = conf->vif;
switch (conf->type) {
+ case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_MONITOR:
sc->opmode = conf->type;
break;
@@ -2759,6 +2781,7 @@ static int ath5k_add_interface(struct ieee80211_hw *hw,
/* Set to a reasonable value. Note that this will
* be set to mac80211's value at ath5k_config(). */
sc->bintval = 1000;
+ ath5k_hw_set_lladdr(sc->ah, conf->mac_addr);
ret = 0;
end:
@@ -2771,11 +2794,13 @@ ath5k_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
{
struct ath5k_softc *sc = hw->priv;
+ u8 mac[ETH_ALEN] = {};
mutex_lock(&sc->lock);
if (sc->vif != conf->vif)
goto end;
+ ath5k_hw_set_lladdr(sc->ah, mac);
sc->vif = NULL;
end:
mutex_unlock(&sc->lock);
@@ -2785,10 +2810,10 @@ end:
* TODO: Phy disable/diversity etc
*/
static int
-ath5k_config(struct ieee80211_hw *hw,
- struct ieee80211_conf *conf)
+ath5k_config(struct ieee80211_hw *hw, u32 changed)
{
struct ath5k_softc *sc = hw->priv;
+ struct ieee80211_conf *conf = &hw->conf;
sc->bintval = conf->beacon_int;
sc->power_level = conf->power_level;
@@ -2809,7 +2834,7 @@ ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
ret = -EIO;
goto unlock;
}
- if (conf->bssid) {
+ if (conf->changed & IEEE80211_IFCC_BSSID && conf->bssid) {
/* Cache for later use during resets */
memcpy(ah->ah_bssid, conf->bssid, ETH_ALEN);
/* XXX: assoc id is set to 0 for now, mac80211 doesn't have
@@ -2817,18 +2842,17 @@ ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
mmiowb();
}
-
if (conf->changed & IEEE80211_IFCC_BEACON &&
- vif->type == NL80211_IFTYPE_ADHOC) {
+ (vif->type == NL80211_IFTYPE_ADHOC ||
+ vif->type == NL80211_IFTYPE_MESH_POINT ||
+ vif->type == NL80211_IFTYPE_AP)) {
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
if (!beacon) {
ret = -ENOMEM;
goto unlock;
}
- /* call old handler for now */
- ath5k_beacon_update(hw, beacon);
+ ath5k_beacon_update(sc, beacon);
}
-
mutex_unlock(&sc->lock);
return ath5k_reset_wake(sc);
@@ -2888,9 +2912,9 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
if (*new_flags & FIF_PROMISC_IN_BSS) {
rfilt |= AR5K_RX_FILTER_PROM;
__set_bit(ATH_STAT_PROMISC, sc->status);
- }
- else
+ } else {
__clear_bit(ATH_STAT_PROMISC, sc->status);
+ }
}
/* Note, AR5K_RX_FILTER_MCAST is already enabled */
@@ -2948,12 +2972,15 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
test_bit(ATH_STAT_PROMISC, sc->status))
rfilt |= AR5K_RX_FILTER_PROM;
if ((sc->opmode == NL80211_IFTYPE_STATION && sc->assoc) ||
- sc->opmode == NL80211_IFTYPE_ADHOC) {
+ sc->opmode == NL80211_IFTYPE_ADHOC ||
+ sc->opmode == NL80211_IFTYPE_AP)
rfilt |= AR5K_RX_FILTER_BEACON;
- }
+ if (sc->opmode == NL80211_IFTYPE_MESH_POINT)
+ rfilt |= AR5K_RX_FILTER_CONTROL | AR5K_RX_FILTER_BEACON |
+ AR5K_RX_FILTER_PROBEREQ | AR5K_RX_FILTER_PROM;
/* Set filters */
- ath5k_hw_set_rx_filter(ah,rfilt);
+ ath5k_hw_set_rx_filter(ah, rfilt);
/* Set multicast bits */
ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]);
@@ -2970,12 +2997,13 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ath5k_softc *sc = hw->priv;
int ret = 0;
- switch(key->alg) {
+ if (modparam_nohwcrypt)
+ return -EOPNOTSUPP;
+
+ switch (key->alg) {
case ALG_WEP:
- /* XXX: fix hardware encryption, its not working. For now
- * allow software encryption */
- /* break; */
case ALG_TKIP:
+ break;
case ALG_CCMP:
return -EOPNOTSUPP;
default:
@@ -2994,6 +3022,8 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
}
__set_bit(key->keyidx, sc->keymap);
key->hw_key_idx = key->keyidx;
+ key->flags |= (IEEE80211_KEY_FLAG_GENERATE_IV |
+ IEEE80211_KEY_FLAG_GENERATE_MMIC);
break;
case DISABLE_KEY:
ath5k_hw_reset_key(sc->ah, key->keyidx);
@@ -3060,19 +3090,13 @@ ath5k_reset_tsf(struct ieee80211_hw *hw)
}
static int
-ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
+ath5k_beacon_update(struct ath5k_softc *sc, struct sk_buff *skb)
{
- struct ath5k_softc *sc = hw->priv;
unsigned long flags;
int ret;
ath5k_debug_dump_skb(sc, skb, "BC ", 1);
- if (sc->opmode != NL80211_IFTYPE_ADHOC) {
- ret = -EIO;
- goto end;
- }
-
spin_lock_irqsave(&sc->block, flags);
ath5k_txbuf_free(sc, sc->bbuf);
sc->bbuf->skb = skb;
@@ -3085,7 +3109,6 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
mmiowb();
}
-end:
return ret;
}
static void
diff --git a/drivers/net/wireless/ath5k/desc.c b/drivers/net/wireless/ath5k/desc.c
index 5e362a7a3620..b40a9287a39a 100644
--- a/drivers/net/wireless/ath5k/desc.c
+++ b/drivers/net/wireless/ath5k/desc.c
@@ -71,7 +71,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
/* Verify and set frame length */
/* remove padding we might have added before */
- frame_len = pkt_len - (hdr_len & 3) + FCS_LEN;
+ frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN;
if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
return -EINVAL;
@@ -202,7 +202,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
/* Verify and set frame length */
/* remove padding we might have added before */
- frame_len = pkt_len - (hdr_len & 3) + FCS_LEN;
+ frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN;
if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
return -EINVAL;
diff --git a/drivers/net/wireless/ath5k/dma.c b/drivers/net/wireless/ath5k/dma.c
index 7adceb2c7fab..7e2b1a67e5da 100644
--- a/drivers/net/wireless/ath5k/dma.c
+++ b/drivers/net/wireless/ath5k/dma.c
@@ -472,9 +472,6 @@ bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah)
*
* NOTE: We use read-and-clear register, so after this function is called ISR
* is zeroed.
- *
- * XXX: Why filter interrupts in sw with interrupt_mask ? No benefit at all
- * plus it can be misleading (one might thing that we save interrupts this way)
*/
int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
{
@@ -494,11 +491,16 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
}
} else {
/*
- * Read interrupt status from the Read-And-Clear
- * shadow register.
+ * Read interrupt status from Interrupt
+ * Status Register shadow copy (Read And Clear)
+ *
* Note: PISR/SISR Not available on 5210
*/
data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR);
+ if (unlikely(data == AR5K_INT_NOCARD)) {
+ *interrupt_mask = data;
+ return -ENODEV;
+ }
}
/*
@@ -506,17 +508,9 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
*/
*interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr;
- if (unlikely(data == AR5K_INT_NOCARD))
- return -ENODEV;
-
- if (data & (AR5K_ISR_RXOK | AR5K_ISR_RXERR))
- *interrupt_mask |= AR5K_INT_RX;
-
- if (data & (AR5K_ISR_TXOK | AR5K_ISR_TXERR
- | AR5K_ISR_TXDESC | AR5K_ISR_TXEOL))
- *interrupt_mask |= AR5K_INT_TX;
-
if (ah->ah_version != AR5K_AR5210) {
+ u32 sisr2 = ath5k_hw_reg_read(ah, AR5K_RAC_SISR2);
+
/*HIU = Host Interface Unit (PCI etc)*/
if (unlikely(data & (AR5K_ISR_HIUERR)))
*interrupt_mask |= AR5K_INT_FATAL;
@@ -524,24 +518,93 @@ int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask)
/*Beacon Not Ready*/
if (unlikely(data & (AR5K_ISR_BNR)))
*interrupt_mask |= AR5K_INT_BNR;
- }
- /*
- * XXX: BMISS interrupts may occur after association.
- * I found this on 5210 code but it needs testing. If this is
- * true we should disable them before assoc and re-enable them
- * after a successfull assoc + some jiffies.
- */
-#if 0
- interrupt_mask &= ~AR5K_INT_BMISS;
-#endif
+ if (unlikely(sisr2 & (AR5K_SISR2_SSERR |
+ AR5K_SISR2_DPERR |
+ AR5K_SISR2_MCABT)))
+ *interrupt_mask |= AR5K_INT_FATAL;
+
+ if (data & AR5K_ISR_TIM)
+ *interrupt_mask |= AR5K_INT_TIM;
+
+ if (data & AR5K_ISR_BCNMISC) {
+ if (sisr2 & AR5K_SISR2_TIM)
+ *interrupt_mask |= AR5K_INT_TIM;
+ if (sisr2 & AR5K_SISR2_DTIM)
+ *interrupt_mask |= AR5K_INT_DTIM;
+ if (sisr2 & AR5K_SISR2_DTIM_SYNC)
+ *interrupt_mask |= AR5K_INT_DTIM_SYNC;
+ if (sisr2 & AR5K_SISR2_BCN_TIMEOUT)
+ *interrupt_mask |= AR5K_INT_BCN_TIMEOUT;
+ if (sisr2 & AR5K_SISR2_CAB_TIMEOUT)
+ *interrupt_mask |= AR5K_INT_CAB_TIMEOUT;
+ }
+
+ if (data & AR5K_ISR_RXDOPPLER)
+ *interrupt_mask |= AR5K_INT_RX_DOPPLER;
+ if (data & AR5K_ISR_QCBRORN) {
+ *interrupt_mask |= AR5K_INT_QCBRORN;
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
+ AR5K_SISR3_QCBRORN);
+ }
+ if (data & AR5K_ISR_QCBRURN) {
+ *interrupt_mask |= AR5K_INT_QCBRURN;
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR3),
+ AR5K_SISR3_QCBRURN);
+ }
+ if (data & AR5K_ISR_QTRIG) {
+ *interrupt_mask |= AR5K_INT_QTRIG;
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR4),
+ AR5K_SISR4_QTRIG);
+ }
+
+ if (data & AR5K_ISR_TXOK)
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
+ AR5K_SISR0_QCU_TXOK);
+
+ if (data & AR5K_ISR_TXDESC)
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR0),
+ AR5K_SISR0_QCU_TXDESC);
+
+ if (data & AR5K_ISR_TXERR)
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
+ AR5K_SISR1_QCU_TXERR);
+
+ if (data & AR5K_ISR_TXEOL)
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR1),
+ AR5K_SISR1_QCU_TXEOL);
+
+ if (data & AR5K_ISR_TXURN)
+ ah->ah_txq_isr |= AR5K_REG_MS(
+ ath5k_hw_reg_read(ah, AR5K_RAC_SISR2),
+ AR5K_SISR2_QCU_TXURN);
+ } else {
+ if (unlikely(data & (AR5K_ISR_SSERR | AR5K_ISR_MCABT
+ | AR5K_ISR_HIUERR | AR5K_ISR_DPERR)))
+ *interrupt_mask |= AR5K_INT_FATAL;
+
+ /*
+ * XXX: BMISS interrupts may occur after association.
+ * I found this on 5210 code but it needs testing. If this is
+ * true we should disable them before assoc and re-enable them
+ * after a successfull assoc + some jiffies.
+ interrupt_mask &= ~AR5K_INT_BMISS;
+ */
+ }
/*
* In case we didn't handle anything,
* print the register value.
*/
if (unlikely(*interrupt_mask == 0 && net_ratelimit()))
- ATH5K_PRINTF("0x%08x\n", data);
+ ATH5K_PRINTF("ISR: 0x%08x IMR: 0x%08x\n", data, ah->ah_imr);
return 0;
}
@@ -560,14 +623,17 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
{
enum ath5k_int old_mask, int_mask;
+ old_mask = ah->ah_imr;
+
/*
* Disable card interrupts to prevent any race conditions
- * (they will be re-enabled afterwards).
+ * (they will be re-enabled afterwards if AR5K_INT GLOBAL
+ * is set again on the new mask).
*/
- ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER);
- ath5k_hw_reg_read(ah, AR5K_IER);
-
- old_mask = ah->ah_imr;
+ if (old_mask & AR5K_INT_GLOBAL) {
+ ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER);
+ ath5k_hw_reg_read(ah, AR5K_IER);
+ }
/*
* Add additional, chipset-dependent interrupt mask flags
@@ -575,30 +641,64 @@ enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask)
*/
int_mask = new_mask & AR5K_INT_COMMON;
- if (new_mask & AR5K_INT_RX)
- int_mask |= AR5K_IMR_RXOK | AR5K_IMR_RXERR | AR5K_IMR_RXORN |
- AR5K_IMR_RXDESC;
-
- if (new_mask & AR5K_INT_TX)
- int_mask |= AR5K_IMR_TXOK | AR5K_IMR_TXERR | AR5K_IMR_TXDESC |
- AR5K_IMR_TXURN;
-
if (ah->ah_version != AR5K_AR5210) {
+ /* Preserve per queue TXURN interrupt mask */
+ u32 simr2 = ath5k_hw_reg_read(ah, AR5K_SIMR2)
+ & AR5K_SIMR2_QCU_TXURN;
+
if (new_mask & AR5K_INT_FATAL) {
int_mask |= AR5K_IMR_HIUERR;
- AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_MCABT |
- AR5K_SIMR2_SSERR | AR5K_SIMR2_DPERR);
+ simr2 |= (AR5K_SIMR2_MCABT | AR5K_SIMR2_SSERR
+ | AR5K_SIMR2_DPERR);
}
+
+ /*Beacon Not Ready*/
+ if (new_mask & AR5K_INT_BNR)
+ int_mask |= AR5K_INT_BNR;
+
+ if (new_mask & AR5K_INT_TIM)
+ int_mask |= AR5K_IMR_TIM;
+
+ if (new_mask & AR5K_INT_TIM)
+ simr2 |= AR5K_SISR2_TIM;
+ if (new_mask & AR5K_INT_DTIM)
+ simr2 |= AR5K_SISR2_DTIM;
+ if (new_mask & AR5K_INT_DTIM_SYNC)
+ simr2 |= AR5K_SISR2_DTIM_SYNC;
+ if (new_mask & AR5K_INT_BCN_TIMEOUT)
+ simr2 |= AR5K_SISR2_BCN_TIMEOUT;
+ if (new_mask & AR5K_INT_CAB_TIMEOUT)
+ simr2 |= AR5K_SISR2_CAB_TIMEOUT;
+
+ if (new_mask & AR5K_INT_RX_DOPPLER)
+ int_mask |= AR5K_IMR_RXDOPPLER;
+
+ /* Note: Per queue interrupt masks
+ * are set via reset_tx_queue (qcu.c) */
+ ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
+ ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2);
+
+ } else {
+ if (new_mask & AR5K_INT_FATAL)
+ int_mask |= (AR5K_IMR_SSERR | AR5K_IMR_MCABT
+ | AR5K_IMR_HIUERR | AR5K_IMR_DPERR);
+
+ ath5k_hw_reg_write(ah, int_mask, AR5K_IMR);
}
- ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR);
+ /* If RXNOFRM interrupt is masked disable it
+ * by setting AR5K_RXNOFRM to zero */
+ if (!(new_mask & AR5K_INT_RXNOFRM))
+ ath5k_hw_reg_write(ah, 0, AR5K_RXNOFRM);
/* Store new interrupt mask */
ah->ah_imr = new_mask;
- /* ..re-enable interrupts */
- ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER);
- ath5k_hw_reg_read(ah, AR5K_IER);
+ /* ..re-enable interrupts if AR5K_INT_GLOBAL is set */
+ if (new_mask & AR5K_INT_GLOBAL) {
+ ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER);
+ ath5k_hw_reg_read(ah, AR5K_IER);
+ }
return old_mask;
}
diff --git a/drivers/net/wireless/ath5k/eeprom.c b/drivers/net/wireless/ath5k/eeprom.c
index a883839b6a9f..1cb7edfae625 100644
--- a/drivers/net/wireless/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath5k/eeprom.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
* Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
+ * Copyright (c) 2008 Felix Fietkau <nbd@openwrt.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -63,8 +64,8 @@ static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
/*
* Translate binary channel representation in EEPROM to frequency
*/
-static u16 ath5k_eeprom_bin2freq(struct ath5k_hw *ah, u16 bin,
- unsigned int mode)
+static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin,
+ unsigned int mode)
{
u16 val;
@@ -72,13 +73,13 @@ static u16 ath5k_eeprom_bin2freq(struct ath5k_hw *ah, u16 bin,
return bin;
if (mode == AR5K_EEPROM_MODE_11A) {
- if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
+ if (ee->ee_version > AR5K_EEPROM_VERSION_3_2)
val = (5 * bin) + 4800;
else
val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 :
(bin * 10) + 5100;
} else {
- if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
+ if (ee->ee_version > AR5K_EEPROM_VERSION_3_2)
val = bin + 2300;
else
val = bin + 2400;
@@ -88,6 +89,71 @@ static u16 ath5k_eeprom_bin2freq(struct ath5k_hw *ah, u16 bin,
}
/*
+ * Initialize eeprom & capabilities structs
+ */
+static int
+ath5k_eeprom_init_header(struct ath5k_hw *ah)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ int ret;
+ u16 val;
+
+ /* Initial TX thermal adjustment values */
+ ee->ee_tx_clip = 4;
+ ee->ee_pwd_84 = ee->ee_pwd_90 = 1;
+ ee->ee_gain_select = 1;
+
+ /*
+ * Read values from EEPROM and store them in the capability structure
+ */
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header);
+
+ /* Return if we have an old EEPROM */
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
+ return 0;
+
+#ifdef notyet
+ /*
+ * Validate the checksum of the EEPROM date. There are some
+ * devices with invalid EEPROMs.
+ */
+ for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) {
+ AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
+ cksum ^= val;
+ }
+ if (cksum != AR5K_EEPROM_INFO_CKSUM) {
+ ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum);
+ return -EIO;
+ }
+#endif
+
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version),
+ ee_ant_gain);
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
+ AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
+ }
+
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
+ AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val);
+ ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7;
+ ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7;
+
+ AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val);
+ ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7;
+ ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
+ }
+
+ return 0;
+}
+
+
+/*
* Read antenna infos from eeprom
*/
static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
@@ -100,7 +166,7 @@ static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
AR5K_EEPROM_READ(o++, val);
ee->ee_switch_settling[mode] = (val >> 8) & 0x7f;
- ee->ee_ant_tx_rx[mode] = (val >> 2) & 0x3f;
+ ee->ee_atn_tx_rx[mode] = (val >> 2) & 0x3f;
ee->ee_ant_control[mode][i] = (val << 4) & 0x3f;
AR5K_EEPROM_READ(o++, val);
@@ -157,6 +223,30 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
u16 val;
int ret;
+ ee->ee_n_piers[mode] = 0;
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
+ switch(mode) {
+ case AR5K_EEPROM_MODE_11A:
+ ee->ee_ob[mode][3] = (val >> 5) & 0x7;
+ ee->ee_db[mode][3] = (val >> 2) & 0x7;
+ ee->ee_ob[mode][2] = (val << 1) & 0x7;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_ob[mode][2] |= (val >> 15) & 0x1;
+ ee->ee_db[mode][2] = (val >> 12) & 0x7;
+ ee->ee_ob[mode][1] = (val >> 9) & 0x7;
+ ee->ee_db[mode][1] = (val >> 6) & 0x7;
+ ee->ee_ob[mode][0] = (val >> 3) & 0x7;
+ ee->ee_db[mode][0] = val & 0x7;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ case AR5K_EEPROM_MODE_11B:
+ ee->ee_ob[mode][1] = (val >> 4) & 0x7;
+ ee->ee_db[mode][1] = val & 0x7;
+ break;
+ }
+
AR5K_EEPROM_READ(o++, val);
ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff;
ee->ee_thr_62[mode] = val & 0xff;
@@ -209,8 +299,11 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
AR5K_EEPROM_READ(o++, val);
ee->ee_i_gain[mode] |= (val << 3) & 0x38;
- if (mode == AR5K_EEPROM_MODE_11G)
+ if (mode == AR5K_EEPROM_MODE_11G) {
ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff;
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6)
+ ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
+ }
}
if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 &&
@@ -219,10 +312,77 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
}
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6 &&
- mode == AR5K_EEPROM_MODE_11G)
- ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_0)
+ goto done;
+
+ switch(mode) {
+ case AR5K_EEPROM_MODE_11A:
+ if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1)
+ break;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_margin_tx_rx[mode] = val & 0x3f;
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ AR5K_EEPROM_READ(o++, val);
+
+ ee->ee_pwr_cal_b[0].freq =
+ ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
+ if (ee->ee_pwr_cal_b[0].freq != AR5K_EEPROM_CHANNEL_DIS)
+ ee->ee_n_piers[mode]++;
+
+ ee->ee_pwr_cal_b[1].freq =
+ ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
+ if (ee->ee_pwr_cal_b[1].freq != AR5K_EEPROM_CHANNEL_DIS)
+ ee->ee_n_piers[mode]++;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_pwr_cal_b[2].freq =
+ ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
+ if (ee->ee_pwr_cal_b[2].freq != AR5K_EEPROM_CHANNEL_DIS)
+ ee->ee_n_piers[mode]++;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
+ ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ AR5K_EEPROM_READ(o++, val);
+
+ ee->ee_pwr_cal_g[0].freq =
+ ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
+ if (ee->ee_pwr_cal_g[0].freq != AR5K_EEPROM_CHANNEL_DIS)
+ ee->ee_n_piers[mode]++;
+
+ ee->ee_pwr_cal_g[1].freq =
+ ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
+ if (ee->ee_pwr_cal_g[1].freq != AR5K_EEPROM_CHANNEL_DIS)
+ ee->ee_n_piers[mode]++;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_turbo_max_power[mode] = val & 0x7f;
+ ee->ee_xr_power[mode] = (val >> 7) & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_pwr_cal_g[2].freq =
+ ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
+ if (ee->ee_pwr_cal_g[2].freq != AR5K_EEPROM_CHANNEL_DIS)
+ ee->ee_n_piers[mode]++;
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
+ ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
+
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
+ ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) {
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_cck_ofdm_gain_delta = val & 0xff;
+ }
+ break;
+ }
+
+done:
/* return new offset */
*offset = o;
@@ -230,204 +390,944 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
}
/*
- * Initialize eeprom & capabilities structs
+ * Read turbo mode information on newer EEPROM versions
*/
-int ath5k_eeprom_init(struct ath5k_hw *ah)
+static int
+ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah,
+ u32 *offset, unsigned int mode)
{
struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
- unsigned int mode, i;
- int ret;
- u32 offset;
+ u32 o = *offset;
u16 val;
+ int ret;
- /* Initial TX thermal adjustment values */
- ee->ee_tx_clip = 4;
- ee->ee_pwd_84 = ee->ee_pwd_90 = 1;
- ee->ee_gain_select = 1;
+ if (ee->ee_version < AR5K_EEPROM_VERSION_5_0)
+ return 0;
- /*
- * Read values from EEPROM and store them in the capability structure
- */
- AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic);
- AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect);
- AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain);
- AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version);
- AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header);
+ switch (mode){
+ case AR5K_EEPROM_MODE_11A:
+ ee->ee_switch_settling_turbo[mode] = (val >> 6) & 0x7f;
- /* Return if we have an old EEPROM */
- if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
- return 0;
+ ee->ee_atn_tx_rx_turbo[mode] = (val >> 13) & 0x7;
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x7) << 3;
+ ee->ee_margin_tx_rx_turbo[mode] = (val >> 3) & 0x3f;
+
+ ee->ee_adc_desired_size_turbo[mode] = (val >> 9) & 0x7f;
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_adc_desired_size_turbo[mode] |= (val & 0x1) << 7;
+ ee->ee_pga_desired_size_turbo[mode] = (val >> 1) & 0xff;
+
+ if (AR5K_EEPROM_EEMAP(ee->ee_misc0) >=2)
+ ee->ee_pd_gain_overlap = (val >> 9) & 0xf;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ ee->ee_switch_settling_turbo[mode] = (val >> 8) & 0x7f;
+
+ ee->ee_atn_tx_rx_turbo[mode] = (val >> 15) & 0x7;
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x1f) << 1;
+ ee->ee_margin_tx_rx_turbo[mode] = (val >> 5) & 0x3f;
+
+ ee->ee_adc_desired_size_turbo[mode] = (val >> 11) & 0x7f;
+ AR5K_EEPROM_READ(o++, val);
+ ee->ee_adc_desired_size_turbo[mode] |= (val & 0x7) << 5;
+ ee->ee_pga_desired_size_turbo[mode] = (val >> 3) & 0xff;
+ break;
+ }
+
+ /* return new offset */
+ *offset = o;
+
+ return 0;
+}
+
+
+static int
+ath5k_eeprom_init_modes(struct ath5k_hw *ah)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ u32 mode_offset[3];
+ unsigned int mode;
+ u32 offset;
+ int ret;
-#ifdef notyet
/*
- * Validate the checksum of the EEPROM date. There are some
- * devices with invalid EEPROMs.
+ * Get values for all modes
*/
- for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) {
- AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
- cksum ^= val;
+ mode_offset[AR5K_EEPROM_MODE_11A] = AR5K_EEPROM_MODES_11A(ah->ah_ee_version);
+ mode_offset[AR5K_EEPROM_MODE_11B] = AR5K_EEPROM_MODES_11B(ah->ah_ee_version);
+ mode_offset[AR5K_EEPROM_MODE_11G] = AR5K_EEPROM_MODES_11G(ah->ah_ee_version);
+
+ ee->ee_turbo_max_power[AR5K_EEPROM_MODE_11A] =
+ AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header);
+
+ for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) {
+ offset = mode_offset[mode];
+
+ ret = ath5k_eeprom_read_ants(ah, &offset, mode);
+ if (ret)
+ return ret;
+
+ ret = ath5k_eeprom_read_modes(ah, &offset, mode);
+ if (ret)
+ return ret;
+
+ ret = ath5k_eeprom_read_turbo_modes(ah, &offset, mode);
+ if (ret)
+ return ret;
}
- if (cksum != AR5K_EEPROM_INFO_CKSUM) {
- ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum);
- return -EIO;
+
+ /* override for older eeprom versions for better performance */
+ if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) {
+ ee->ee_thr_62[AR5K_EEPROM_MODE_11A] = 15;
+ ee->ee_thr_62[AR5K_EEPROM_MODE_11B] = 28;
+ ee->ee_thr_62[AR5K_EEPROM_MODE_11G] = 28;
}
-#endif
- AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version),
- ee_ant_gain);
+ return 0;
+}
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
- AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
- AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
- }
+static inline void
+ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
+{
+ const static u16 intercepts3[] =
+ { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 };
+ const static u16 intercepts3_2[] =
+ { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
+ const u16 *ip;
+ int i;
+
+ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_2)
+ ip = intercepts3_2;
+ else
+ ip = intercepts3;
- if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
- AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val);
- ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7;
- ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7;
+ for (i = 0; i < ARRAY_SIZE(intercepts3); i++)
+ *vp++ = (ip[i] * max + (100 - ip[i]) * min) / 100;
+}
- AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val);
- ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7;
- ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
+static inline int
+ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max,
+ struct ath5k_chan_pcal_info *pc, u8 *count)
+{
+ int o = *offset;
+ int i = 0;
+ u8 f1, f2;
+ int ret;
+ u16 val;
+
+ while(i < max) {
+ AR5K_EEPROM_READ(o++, val);
+
+ f1 = (val >> 8) & 0xff;
+ f2 = val & 0xff;
+
+ if (f1)
+ pc[i++].freq = f1;
+
+ if (f2)
+ pc[i++].freq = f2;
+
+ if (!f1 || !f2)
+ break;
}
+ *offset = o;
+ *count = i;
- /*
- * Get conformance test limit values
- */
- offset = AR5K_EEPROM_CTL(ah->ah_ee_version);
- ee->ee_ctls = AR5K_EEPROM_N_CTLS(ah->ah_ee_version);
+ return 0;
+}
+
+static int
+ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info *pcal = ee->ee_pwr_cal_a;
+ int i, ret;
+ u16 val;
+ u8 mask;
+
+ if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) {
+ ath5k_eeprom_read_freq_list(ah, &offset,
+ AR5K_EEPROM_N_5GHZ_CHAN, pcal,
+ &ee->ee_n_piers[AR5K_EEPROM_MODE_11A]);
+ } else {
+ mask = AR5K_EEPROM_FREQ_M(ah->ah_ee_version);
- for (i = 0; i < ee->ee_ctls; i++) {
AR5K_EEPROM_READ(offset++, val);
- ee->ee_ctl[i] = (val >> 8) & 0xff;
- ee->ee_ctl[i + 1] = val & 0xff;
+ pcal[0].freq = (val >> 9) & mask;
+ pcal[1].freq = (val >> 2) & mask;
+ pcal[2].freq = (val << 5) & mask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcal[2].freq |= (val >> 11) & 0x1f;
+ pcal[3].freq = (val >> 4) & mask;
+ pcal[4].freq = (val << 3) & mask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcal[4].freq |= (val >> 13) & 0x7;
+ pcal[5].freq = (val >> 6) & mask;
+ pcal[6].freq = (val << 1) & mask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcal[6].freq |= (val >> 15) & 0x1;
+ pcal[7].freq = (val >> 8) & mask;
+ pcal[8].freq = (val >> 1) & mask;
+ pcal[9].freq = (val << 6) & mask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ pcal[9].freq |= (val >> 10) & 0x3f;
+ ee->ee_n_piers[AR5K_EEPROM_MODE_11A] = 10;
}
- /*
- * Get values for 802.11a (5GHz)
- */
- mode = AR5K_EEPROM_MODE_11A;
+ for(i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i += 1) {
+ pcal[i].freq = ath5k_eeprom_bin2freq(ee,
+ pcal[i].freq, AR5K_EEPROM_MODE_11A);
+ }
- ee->ee_turbo_max_power[mode] =
- AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header);
+ return 0;
+}
- offset = AR5K_EEPROM_MODES_11A(ah->ah_ee_version);
+static inline int
+ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info *pcal;
+ int i;
+
+ switch(mode) {
+ case AR5K_EEPROM_MODE_11B:
+ pcal = ee->ee_pwr_cal_b;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ pcal = ee->ee_pwr_cal_g;
+ break;
+ default:
+ return -EINVAL;
+ }
- ret = ath5k_eeprom_read_ants(ah, &offset, mode);
- if (ret)
- return ret;
+ ath5k_eeprom_read_freq_list(ah, &offset,
+ AR5K_EEPROM_N_2GHZ_CHAN_2413, pcal,
+ &ee->ee_n_piers[mode]);
+ for(i = 0; i < AR5K_EEPROM_N_2GHZ_CHAN_2413; i += 1) {
+ pcal[i].freq = ath5k_eeprom_bin2freq(ee,
+ pcal[i].freq, mode);
+ }
- AR5K_EEPROM_READ(offset++, val);
- ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
- ee->ee_ob[mode][3] = (val >> 5) & 0x7;
- ee->ee_db[mode][3] = (val >> 2) & 0x7;
- ee->ee_ob[mode][2] = (val << 1) & 0x7;
-
- AR5K_EEPROM_READ(offset++, val);
- ee->ee_ob[mode][2] |= (val >> 15) & 0x1;
- ee->ee_db[mode][2] = (val >> 12) & 0x7;
- ee->ee_ob[mode][1] = (val >> 9) & 0x7;
- ee->ee_db[mode][1] = (val >> 6) & 0x7;
- ee->ee_ob[mode][0] = (val >> 3) & 0x7;
- ee->ee_db[mode][0] = val & 0x7;
-
- ret = ath5k_eeprom_read_modes(ah, &offset, mode);
- if (ret)
- return ret;
+ return 0;
+}
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
- AR5K_EEPROM_READ(offset++, val);
- ee->ee_margin_tx_rx[mode] = val & 0x3f;
+
+static int
+ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info *pcal;
+ int offset, ret;
+ int i, j;
+ u16 val;
+
+ offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
+ switch(mode) {
+ case AR5K_EEPROM_MODE_11A:
+ if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
+ return 0;
+
+ ret = ath5k_eeprom_init_11a_pcal_freq(ah,
+ offset + AR5K_EEPROM_GROUP1_OFFSET);
+ if (ret < 0)
+ return ret;
+
+ offset += AR5K_EEPROM_GROUP2_OFFSET;
+ pcal = ee->ee_pwr_cal_a;
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ if (!AR5K_EEPROM_HDR_11B(ee->ee_header) &&
+ !AR5K_EEPROM_HDR_11G(ee->ee_header))
+ return 0;
+
+ pcal = ee->ee_pwr_cal_b;
+ offset += AR5K_EEPROM_GROUP3_OFFSET;
+
+ /* fixed piers */
+ pcal[0].freq = 2412;
+ pcal[1].freq = 2447;
+ pcal[2].freq = 2484;
+ ee->ee_n_piers[mode] = 3;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
+ return 0;
+
+ pcal = ee->ee_pwr_cal_g;
+ offset += AR5K_EEPROM_GROUP4_OFFSET;
+
+ /* fixed piers */
+ pcal[0].freq = 2312;
+ pcal[1].freq = 2412;
+ pcal[2].freq = 2484;
+ ee->ee_n_piers[mode] = 3;
+ break;
+ default:
+ return -EINVAL;
}
- /*
- * Get values for 802.11b (2.4GHz)
- */
- mode = AR5K_EEPROM_MODE_11B;
- offset = AR5K_EEPROM_MODES_11B(ah->ah_ee_version);
+ for (i = 0; i < ee->ee_n_piers[mode]; i++) {
+ struct ath5k_chan_pcal_info_rf5111 *cdata =
+ &pcal[i].rf5111_info;
- ret = ath5k_eeprom_read_ants(ah, &offset, mode);
- if (ret)
- return ret;
+ AR5K_EEPROM_READ(offset++, val);
+ cdata->pcdac_max = ((val >> 10) & AR5K_EEPROM_PCDAC_M);
+ cdata->pcdac_min = ((val >> 4) & AR5K_EEPROM_PCDAC_M);
+ cdata->pwr[0] = ((val << 2) & AR5K_EEPROM_POWER_M);
- AR5K_EEPROM_READ(offset++, val);
- ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
- ee->ee_ob[mode][1] = (val >> 4) & 0x7;
- ee->ee_db[mode][1] = val & 0x7;
+ AR5K_EEPROM_READ(offset++, val);
+ cdata->pwr[0] |= ((val >> 14) & 0x3);
+ cdata->pwr[1] = ((val >> 8) & AR5K_EEPROM_POWER_M);
+ cdata->pwr[2] = ((val >> 2) & AR5K_EEPROM_POWER_M);
+ cdata->pwr[3] = ((val << 4) & AR5K_EEPROM_POWER_M);
- ret = ath5k_eeprom_read_modes(ah, &offset, mode);
- if (ret)
- return ret;
+ AR5K_EEPROM_READ(offset++, val);
+ cdata->pwr[3] |= ((val >> 12) & 0xf);
+ cdata->pwr[4] = ((val >> 6) & AR5K_EEPROM_POWER_M);
+ cdata->pwr[5] = (val & AR5K_EEPROM_POWER_M);
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
AR5K_EEPROM_READ(offset++, val);
- ee->ee_cal_pier[mode][0] =
- ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
- ee->ee_cal_pier[mode][1] =
- ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode);
+ cdata->pwr[6] = ((val >> 10) & AR5K_EEPROM_POWER_M);
+ cdata->pwr[7] = ((val >> 4) & AR5K_EEPROM_POWER_M);
+ cdata->pwr[8] = ((val << 2) & AR5K_EEPROM_POWER_M);
AR5K_EEPROM_READ(offset++, val);
- ee->ee_cal_pier[mode][2] =
- ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
+ cdata->pwr[8] |= ((val >> 14) & 0x3);
+ cdata->pwr[9] = ((val >> 8) & AR5K_EEPROM_POWER_M);
+ cdata->pwr[10] = ((val >> 2) & AR5K_EEPROM_POWER_M);
+
+ ath5k_get_pcdac_intercepts(ah, cdata->pcdac_min,
+ cdata->pcdac_max, cdata->pcdac);
+
+ for (j = 0; j < AR5K_EEPROM_N_PCDAC; j++) {
+ cdata->pwr[j] = (u16)
+ (AR5K_EEPROM_POWER_STEP * cdata->pwr[j]);
+ }
}
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
- ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
+ return 0;
+}
- /*
- * Get values for 802.11g (2.4GHz)
- */
- mode = AR5K_EEPROM_MODE_11G;
- offset = AR5K_EEPROM_MODES_11G(ah->ah_ee_version);
+static int
+ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info_rf5112 *chan_pcal_info;
+ struct ath5k_chan_pcal_info *gen_chan_info;
+ u32 offset;
+ unsigned int i, c;
+ u16 val;
+ int ret;
- ret = ath5k_eeprom_read_ants(ah, &offset, mode);
- if (ret)
- return ret;
+ switch (mode) {
+ case AR5K_EEPROM_MODE_11A:
+ /*
+ * Read 5GHz EEPROM channels
+ */
+ offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
+ ath5k_eeprom_init_11a_pcal_freq(ah, offset);
+
+ offset += AR5K_EEPROM_GROUP2_OFFSET;
+ gen_chan_info = ee->ee_pwr_cal_a;
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
+ if (AR5K_EEPROM_HDR_11A(ee->ee_header))
+ offset += AR5K_EEPROM_GROUP3_OFFSET;
+
+ /* NB: frequency piers parsed during mode init */
+ gen_chan_info = ee->ee_pwr_cal_b;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
+ if (AR5K_EEPROM_HDR_11A(ee->ee_header))
+ offset += AR5K_EEPROM_GROUP4_OFFSET;
+ else if (AR5K_EEPROM_HDR_11B(ee->ee_header))
+ offset += AR5K_EEPROM_GROUP2_OFFSET;
+
+ /* NB: frequency piers parsed during mode init */
+ gen_chan_info = ee->ee_pwr_cal_g;
+ break;
+ default:
+ return -EINVAL;
+ }
- AR5K_EEPROM_READ(offset++, val);
- ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff);
- ee->ee_ob[mode][1] = (val >> 4) & 0x7;
- ee->ee_db[mode][1] = val & 0x7;
+ for (i = 0; i < ee->ee_n_piers[mode]; i++) {
+ chan_pcal_info = &gen_chan_info[i].rf5112_info;
- ret = ath5k_eeprom_read_modes(ah, &offset, mode);
- if (ret)
- return ret;
+ /* Power values in dBm * 4
+ * for the lower xpd gain curve
+ * (0 dBm -> higher output power) */
+ for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) {
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pwr_x0[c] = (val & 0xff);
+ chan_pcal_info->pwr_x0[++c] = ((val >> 8) & 0xff);
+ }
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
+ /* PCDAC steps
+ * corresponding to the above power
+ * measurements */
AR5K_EEPROM_READ(offset++, val);
- ee->ee_cal_pier[mode][0] =
- ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
- ee->ee_cal_pier[mode][1] =
- ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode);
+ chan_pcal_info->pcdac_x0[1] = (val & 0x1f);
+ chan_pcal_info->pcdac_x0[2] = ((val >> 5) & 0x1f);
+ chan_pcal_info->pcdac_x0[3] = ((val >> 10) & 0x1f);
+ /* Power values in dBm * 4
+ * for the higher xpd gain curve
+ * (18 dBm -> lower output power) */
AR5K_EEPROM_READ(offset++, val);
- ee->ee_turbo_max_power[mode] = val & 0x7f;
- ee->ee_xr_power[mode] = (val >> 7) & 0x3f;
+ chan_pcal_info->pwr_x3[0] = (val & 0xff);
+ chan_pcal_info->pwr_x3[1] = ((val >> 8) & 0xff);
AR5K_EEPROM_READ(offset++, val);
- ee->ee_cal_pier[mode][2] =
- ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
+ chan_pcal_info->pwr_x3[2] = (val & 0xff);
+
+ /* PCDAC steps
+ * corresponding to the above power
+ * measurements (static) */
+ chan_pcal_info->pcdac_x3[0] = 20;
+ chan_pcal_info->pcdac_x3[1] = 35;
+ chan_pcal_info->pcdac_x3[2] = 63;
+
+ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) {
+ chan_pcal_info->pcdac_x0[0] = ((val >> 8) & 0xff);
+
+ /* Last xpd0 power level is also channel maximum */
+ gen_chan_info[i].max_pwr = chan_pcal_info->pwr_x0[3];
+ } else {
+ chan_pcal_info->pcdac_x0[0] = 1;
+ gen_chan_info[i].max_pwr = ((val >> 8) & 0xff);
+ }
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
- ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
+ /* Recreate pcdac_x0 table for this channel using pcdac steps */
+ chan_pcal_info->pcdac_x0[1] += chan_pcal_info->pcdac_x0[0];
+ chan_pcal_info->pcdac_x0[2] += chan_pcal_info->pcdac_x0[1];
+ chan_pcal_info->pcdac_x0[3] += chan_pcal_info->pcdac_x0[2];
+ }
+
+ return 0;
+}
+
+static inline unsigned int
+ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode)
+{
+ static const unsigned int pdgains_size[] = { 4, 6, 9, 12 };
+ unsigned int sz;
+
+ sz = pdgains_size[ee->ee_pd_gains[mode] - 1];
+ sz *= ee->ee_n_piers[mode];
+
+ return sz;
+}
+
+static unsigned int
+ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
+{
+ u32 offset = AR5K_EEPROM_CAL_DATA_START(ee->ee_misc4);
+
+ switch(mode) {
+ case AR5K_EEPROM_MODE_11G:
+ if (AR5K_EEPROM_HDR_11B(ee->ee_header))
+ offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11B) + 2;
+ /* fall through */
+ case AR5K_EEPROM_MODE_11B:
+ if (AR5K_EEPROM_HDR_11A(ee->ee_header))
+ offset += ath5k_pdgains_size_2413(ee, AR5K_EEPROM_MODE_11A) + 5;
+ /* fall through */
+ case AR5K_EEPROM_MODE_11A:
+ break;
+ default:
+ break;
+ }
+
+ return offset;
+}
+
+static int
+ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_chan_pcal_info_rf2413 *chan_pcal_info;
+ struct ath5k_chan_pcal_info *gen_chan_info;
+ unsigned int i, c;
+ u32 offset;
+ int ret;
+ u16 val;
+ u8 pd_gains = 0;
+
+ if (ee->ee_x_gain[mode] & 0x1) pd_gains++;
+ if ((ee->ee_x_gain[mode] >> 1) & 0x1) pd_gains++;
+ if ((ee->ee_x_gain[mode] >> 2) & 0x1) pd_gains++;
+ if ((ee->ee_x_gain[mode] >> 3) & 0x1) pd_gains++;
+ ee->ee_pd_gains[mode] = pd_gains;
+
+ offset = ath5k_cal_data_offset_2413(ee, mode);
+ switch (mode) {
+ case AR5K_EEPROM_MODE_11A:
+ if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
+ return 0;
+
+ ath5k_eeprom_init_11a_pcal_freq(ah, offset);
+ offset += AR5K_EEPROM_N_5GHZ_CHAN / 2;
+ gen_chan_info = ee->ee_pwr_cal_a;
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
+ return 0;
+ ath5k_eeprom_init_11bg_2413(ah, mode, offset);
+ offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
+ gen_chan_info = ee->ee_pwr_cal_b;
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
+ return 0;
+
+ ath5k_eeprom_init_11bg_2413(ah, mode, offset);
+ offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
+ gen_chan_info = ee->ee_pwr_cal_g;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (pd_gains == 0)
+ return 0;
+
+ for (i = 0; i < ee->ee_n_piers[mode]; i++) {
+ chan_pcal_info = &gen_chan_info[i].rf2413_info;
+
+ /*
+ * Read pwr_i, pddac_i and the first
+ * 2 pd points (pwr, pddac)
+ */
AR5K_EEPROM_READ(offset++, val);
- ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
- ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
+ chan_pcal_info->pwr_i[0] = val & 0x1f;
+ chan_pcal_info->pddac_i[0] = (val >> 5) & 0x7f;
+ chan_pcal_info->pwr[0][0] =
+ (val >> 12) & 0xf;
- if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) {
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pddac[0][0] = val & 0x3f;
+ chan_pcal_info->pwr[0][1] = (val >> 6) & 0xf;
+ chan_pcal_info->pddac[0][1] =
+ (val >> 10) & 0x3f;
+
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pwr[0][2] = val & 0xf;
+ chan_pcal_info->pddac[0][2] =
+ (val >> 4) & 0x3f;
+
+ chan_pcal_info->pwr[0][3] = 0;
+ chan_pcal_info->pddac[0][3] = 0;
+
+ if (pd_gains > 1) {
+ /*
+ * Pd gain 0 is not the last pd gain
+ * so it only has 2 pd points.
+ * Continue wih pd gain 1.
+ */
+ chan_pcal_info->pwr_i[1] = (val >> 10) & 0x1f;
+
+ chan_pcal_info->pddac_i[1] = (val >> 15) & 0x1;
AR5K_EEPROM_READ(offset++, val);
- ee->ee_cck_ofdm_gain_delta = val & 0xff;
+ chan_pcal_info->pddac_i[1] |= (val & 0x3F) << 1;
+
+ chan_pcal_info->pwr[1][0] = (val >> 6) & 0xf;
+ chan_pcal_info->pddac[1][0] =
+ (val >> 10) & 0x3f;
+
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pwr[1][1] = val & 0xf;
+ chan_pcal_info->pddac[1][1] =
+ (val >> 4) & 0x3f;
+ chan_pcal_info->pwr[1][2] =
+ (val >> 10) & 0xf;
+
+ chan_pcal_info->pddac[1][2] =
+ (val >> 14) & 0x3;
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pddac[1][2] |=
+ (val & 0xF) << 2;
+
+ chan_pcal_info->pwr[1][3] = 0;
+ chan_pcal_info->pddac[1][3] = 0;
+ } else if (pd_gains == 1) {
+ /*
+ * Pd gain 0 is the last one so
+ * read the extra point.
+ */
+ chan_pcal_info->pwr[0][3] =
+ (val >> 10) & 0xf;
+
+ chan_pcal_info->pddac[0][3] =
+ (val >> 14) & 0x3;
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pddac[0][3] |=
+ (val & 0xF) << 2;
+ }
+
+ /*
+ * Proceed with the other pd_gains
+ * as above.
+ */
+ if (pd_gains > 2) {
+ chan_pcal_info->pwr_i[2] = (val >> 4) & 0x1f;
+ chan_pcal_info->pddac_i[2] = (val >> 9) & 0x7f;
+
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pwr[2][0] =
+ (val >> 0) & 0xf;
+ chan_pcal_info->pddac[2][0] =
+ (val >> 4) & 0x3f;
+ chan_pcal_info->pwr[2][1] =
+ (val >> 10) & 0xf;
+
+ chan_pcal_info->pddac[2][1] =
+ (val >> 14) & 0x3;
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pddac[2][1] |=
+ (val & 0xF) << 2;
+
+ chan_pcal_info->pwr[2][2] =
+ (val >> 4) & 0xf;
+ chan_pcal_info->pddac[2][2] =
+ (val >> 8) & 0x3f;
+
+ chan_pcal_info->pwr[2][3] = 0;
+ chan_pcal_info->pddac[2][3] = 0;
+ } else if (pd_gains == 2) {
+ chan_pcal_info->pwr[1][3] =
+ (val >> 4) & 0xf;
+ chan_pcal_info->pddac[1][3] =
+ (val >> 8) & 0x3f;
+ }
+
+ if (pd_gains > 3) {
+ chan_pcal_info->pwr_i[3] = (val >> 14) & 0x3;
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pwr_i[3] |= ((val >> 0) & 0x7) << 2;
+
+ chan_pcal_info->pddac_i[3] = (val >> 3) & 0x7f;
+ chan_pcal_info->pwr[3][0] =
+ (val >> 10) & 0xf;
+ chan_pcal_info->pddac[3][0] =
+ (val >> 14) & 0x3;
+
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pddac[3][0] |=
+ (val & 0xF) << 2;
+ chan_pcal_info->pwr[3][1] =
+ (val >> 4) & 0xf;
+ chan_pcal_info->pddac[3][1] =
+ (val >> 8) & 0x3f;
+
+ chan_pcal_info->pwr[3][2] =
+ (val >> 14) & 0x3;
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pwr[3][2] |=
+ ((val >> 0) & 0x3) << 2;
+
+ chan_pcal_info->pddac[3][2] =
+ (val >> 2) & 0x3f;
+ chan_pcal_info->pwr[3][3] =
+ (val >> 8) & 0xf;
+
+ chan_pcal_info->pddac[3][3] =
+ (val >> 12) & 0xF;
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pddac[3][3] |=
+ ((val >> 0) & 0x3) << 4;
+ } else if (pd_gains == 3) {
+ chan_pcal_info->pwr[2][3] =
+ (val >> 14) & 0x3;
+ AR5K_EEPROM_READ(offset++, val);
+ chan_pcal_info->pwr[2][3] |=
+ ((val >> 0) & 0x3) << 2;
+
+ chan_pcal_info->pddac[2][3] =
+ (val >> 2) & 0x3f;
+ }
+
+ for (c = 0; c < pd_gains; c++) {
+ /* Recreate pwr table for this channel using pwr steps */
+ chan_pcal_info->pwr[c][0] += chan_pcal_info->pwr_i[c] * 2;
+ chan_pcal_info->pwr[c][1] += chan_pcal_info->pwr[c][0];
+ chan_pcal_info->pwr[c][2] += chan_pcal_info->pwr[c][1];
+ chan_pcal_info->pwr[c][3] += chan_pcal_info->pwr[c][2];
+ if (chan_pcal_info->pwr[c][3] == chan_pcal_info->pwr[c][2])
+ chan_pcal_info->pwr[c][3] = 0;
+
+ /* Recreate pddac table for this channel using pddac steps */
+ chan_pcal_info->pddac[c][0] += chan_pcal_info->pddac_i[c];
+ chan_pcal_info->pddac[c][1] += chan_pcal_info->pddac[c][0];
+ chan_pcal_info->pddac[c][2] += chan_pcal_info->pddac[c][1];
+ chan_pcal_info->pddac[c][3] += chan_pcal_info->pddac[c][2];
+ if (chan_pcal_info->pddac[c][3] == chan_pcal_info->pddac[c][2])
+ chan_pcal_info->pddac[c][3] = 0;
}
}
- /*
- * Read 5GHz EEPROM channels
- */
+ return 0;
+}
+
+/*
+ * Read per rate target power (this is the maximum tx power
+ * supported by the card). This info is used when setting
+ * tx power, no matter the channel.
+ *
+ * This also works for v5 EEPROMs.
+ */
+static int ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_rate_pcal_info *rate_pcal_info;
+ u16 *rate_target_pwr_num;
+ u32 offset;
+ u16 val;
+ int ret, i;
+
+ offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1);
+ rate_target_pwr_num = &ee->ee_rate_target_pwr_num[mode];
+ switch (mode) {
+ case AR5K_EEPROM_MODE_11A:
+ offset += AR5K_EEPROM_TARGET_PWR_OFF_11A(ee->ee_version);
+ rate_pcal_info = ee->ee_rate_tpwr_a;
+ ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_CHAN;
+ break;
+ case AR5K_EEPROM_MODE_11B:
+ offset += AR5K_EEPROM_TARGET_PWR_OFF_11B(ee->ee_version);
+ rate_pcal_info = ee->ee_rate_tpwr_b;
+ ee->ee_rate_target_pwr_num[mode] = 2; /* 3rd is g mode's 1st */
+ break;
+ case AR5K_EEPROM_MODE_11G:
+ offset += AR5K_EEPROM_TARGET_PWR_OFF_11G(ee->ee_version);
+ rate_pcal_info = ee->ee_rate_tpwr_g;
+ ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_2GHZ_CHAN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Different freq mask for older eeproms (<= v3.2) */
+ if (ee->ee_version <= AR5K_EEPROM_VERSION_3_2) {
+ for (i = 0; i < (*rate_target_pwr_num); i++) {
+ AR5K_EEPROM_READ(offset++, val);
+ rate_pcal_info[i].freq =
+ ath5k_eeprom_bin2freq(ee, (val >> 9) & 0x7f, mode);
+
+ rate_pcal_info[i].target_power_6to24 = ((val >> 3) & 0x3f);
+ rate_pcal_info[i].target_power_36 = (val << 3) & 0x3f;
+
+ AR5K_EEPROM_READ(offset++, val);
+
+ if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS ||
+ val == 0) {
+ (*rate_target_pwr_num) = i;
+ break;
+ }
+
+ rate_pcal_info[i].target_power_36 |= ((val >> 13) & 0x7);
+ rate_pcal_info[i].target_power_48 = ((val >> 7) & 0x3f);
+ rate_pcal_info[i].target_power_54 = ((val >> 1) & 0x3f);
+ }
+ } else {
+ for (i = 0; i < (*rate_target_pwr_num); i++) {
+ AR5K_EEPROM_READ(offset++, val);
+ rate_pcal_info[i].freq =
+ ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
+
+ rate_pcal_info[i].target_power_6to24 = ((val >> 2) & 0x3f);
+ rate_pcal_info[i].target_power_36 = (val << 4) & 0x3f;
+
+ AR5K_EEPROM_READ(offset++, val);
+
+ if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS ||
+ val == 0) {
+ (*rate_target_pwr_num) = i;
+ break;
+ }
+
+ rate_pcal_info[i].target_power_36 |= (val >> 12) & 0xf;
+ rate_pcal_info[i].target_power_48 = ((val >> 6) & 0x3f);
+ rate_pcal_info[i].target_power_54 = (val & 0x3f);
+ }
+ }
+
+ return 0;
+}
+
+static int
+ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ int (*read_pcal)(struct ath5k_hw *hw, int mode);
+ int mode;
+ int err;
+
+ if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) &&
+ (AR5K_EEPROM_EEMAP(ee->ee_misc0) == 1))
+ read_pcal = ath5k_eeprom_read_pcal_info_5112;
+ else if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0) &&
+ (AR5K_EEPROM_EEMAP(ee->ee_misc0) == 2))
+ read_pcal = ath5k_eeprom_read_pcal_info_2413;
+ else
+ read_pcal = ath5k_eeprom_read_pcal_info_5111;
+
+ for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) {
+ err = read_pcal(ah, mode);
+ if (err)
+ return err;
+
+ err = ath5k_eeprom_read_target_rate_pwr_info(ah, mode);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+/* Read conformance test limits */
+static int
+ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
+{
+ struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
+ struct ath5k_edge_power *rep;
+ unsigned int fmask, pmask;
+ unsigned int ctl_mode;
+ int ret, i, j;
+ u32 offset;
+ u16 val;
+
+ pmask = AR5K_EEPROM_POWER_M;
+ fmask = AR5K_EEPROM_FREQ_M(ee->ee_version);
+ offset = AR5K_EEPROM_CTL(ee->ee_version);
+ ee->ee_ctls = AR5K_EEPROM_N_CTLS(ee->ee_version);
+ for (i = 0; i < ee->ee_ctls; i += 2) {
+ AR5K_EEPROM_READ(offset++, val);
+ ee->ee_ctl[i] = (val >> 8) & 0xff;
+ ee->ee_ctl[i + 1] = val & 0xff;
+ }
+
+ offset = AR5K_EEPROM_GROUP8_OFFSET;
+ if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0)
+ offset += AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) -
+ AR5K_EEPROM_GROUP5_OFFSET;
+ else
+ offset += AR5K_EEPROM_GROUPS_START(ee->ee_version);
+
+ rep = ee->ee_ctl_pwr;
+ for(i = 0; i < ee->ee_ctls; i++) {
+ switch(ee->ee_ctl[i] & AR5K_CTL_MODE_M) {
+ case AR5K_CTL_11A:
+ case AR5K_CTL_TURBO:
+ ctl_mode = AR5K_EEPROM_MODE_11A;
+ break;
+ default:
+ ctl_mode = AR5K_EEPROM_MODE_11G;
+ break;
+ }
+ if (ee->ee_ctl[i] == 0) {
+ if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3)
+ offset += 8;
+ else
+ offset += 7;
+ rep += AR5K_EEPROM_N_EDGES;
+ continue;
+ }
+ if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) {
+ for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) {
+ AR5K_EEPROM_READ(offset++, val);
+ rep[j].freq = (val >> 8) & fmask;
+ rep[j + 1].freq = val & fmask;
+ }
+ for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) {
+ AR5K_EEPROM_READ(offset++, val);
+ rep[j].edge = (val >> 8) & pmask;
+ rep[j].flag = (val >> 14) & 1;
+ rep[j + 1].edge = val & pmask;
+ rep[j + 1].flag = (val >> 6) & 1;
+ }
+ } else {
+ AR5K_EEPROM_READ(offset++, val);
+ rep[0].freq = (val >> 9) & fmask;
+ rep[1].freq = (val >> 2) & fmask;
+ rep[2].freq = (val << 5) & fmask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ rep[2].freq |= (val >> 11) & 0x1f;
+ rep[3].freq = (val >> 4) & fmask;
+ rep[4].freq = (val << 3) & fmask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ rep[4].freq |= (val >> 13) & 0x7;
+ rep[5].freq = (val >> 6) & fmask;
+ rep[6].freq = (val << 1) & fmask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ rep[6].freq |= (val >> 15) & 0x1;
+ rep[7].freq = (val >> 8) & fmask;
+
+ rep[0].edge = (val >> 2) & pmask;
+ rep[1].edge = (val << 4) & pmask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ rep[1].edge |= (val >> 12) & 0xf;
+ rep[2].edge = (val >> 6) & pmask;
+ rep[3].edge = val & pmask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ rep[4].edge = (val >> 10) & pmask;
+ rep[5].edge = (val >> 4) & pmask;
+ rep[6].edge = (val << 2) & pmask;
+
+ AR5K_EEPROM_READ(offset++, val);
+ rep[6].edge |= (val >> 14) & 0x3;
+ rep[7].edge = (val >> 8) & pmask;
+ }
+ for (j = 0; j < AR5K_EEPROM_N_EDGES; j++) {
+ rep[j].freq = ath5k_eeprom_bin2freq(ee,
+ rep[j].freq, ctl_mode);
+ }
+ rep += AR5K_EEPROM_N_EDGES;
+ }
return 0;
}
+
+/*
+ * Initialize eeprom power tables
+ */
+int
+ath5k_eeprom_init(struct ath5k_hw *ah)
+{
+ int err;
+
+ err = ath5k_eeprom_init_header(ah);
+ if (err < 0)
+ return err;
+
+ err = ath5k_eeprom_init_modes(ah);
+ if (err < 0)
+ return err;
+
+ err = ath5k_eeprom_read_pcal_info(ah);
+ if (err < 0)
+ return err;
+
+ err = ath5k_eeprom_read_ctl_info(ah);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
/*
* Read the MAC address from eeprom
*/
diff --git a/drivers/net/wireless/ath5k/eeprom.h b/drivers/net/wireless/ath5k/eeprom.h
index a468ecfbb18a..09eb7d0176a4 100644
--- a/drivers/net/wireless/ath5k/eeprom.h
+++ b/drivers/net/wireless/ath5k/eeprom.h
@@ -25,24 +25,8 @@
#define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */
#define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */
-#define AR5K_EEPROM_PROTECT 0x003f /* EEPROM protect status */
-#define AR5K_EEPROM_PROTECT_RD_0_31 0x0001 /* Read protection bit for offsets 0x0 - 0x1f */
-#define AR5K_EEPROM_PROTECT_WR_0_31 0x0002 /* Write protection bit for offsets 0x0 - 0x1f */
-#define AR5K_EEPROM_PROTECT_RD_32_63 0x0004 /* 0x20 - 0x3f */
-#define AR5K_EEPROM_PROTECT_WR_32_63 0x0008
-#define AR5K_EEPROM_PROTECT_RD_64_127 0x0010 /* 0x40 - 0x7f */
-#define AR5K_EEPROM_PROTECT_WR_64_127 0x0020
-#define AR5K_EEPROM_PROTECT_RD_128_191 0x0040 /* 0x80 - 0xbf (regdom) */
-#define AR5K_EEPROM_PROTECT_WR_128_191 0x0080
-#define AR5K_EEPROM_PROTECT_RD_192_207 0x0100 /* 0xc0 - 0xcf */
-#define AR5K_EEPROM_PROTECT_WR_192_207 0x0200
-#define AR5K_EEPROM_PROTECT_RD_208_223 0x0400 /* 0xd0 - 0xdf */
-#define AR5K_EEPROM_PROTECT_WR_208_223 0x0800
-#define AR5K_EEPROM_PROTECT_RD_224_239 0x1000 /* 0xe0 - 0xef */
-#define AR5K_EEPROM_PROTECT_WR_224_239 0x2000
-#define AR5K_EEPROM_PROTECT_RD_240_255 0x4000 /* 0xf0 - 0xff */
-#define AR5K_EEPROM_PROTECT_WR_240_255 0x8000
#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */
+#define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */
#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */
#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE)
#define AR5K_EEPROM_INFO_CKSUM 0xffff
@@ -53,15 +37,19 @@
#define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2Ghz (ar5211_rfregs) */
#define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */
#define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */
-#define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain ee_cck_ofdm_power_delta (eeprom_read_modes) */
-#define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc*, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */
+#define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain, ee_cck_ofdm_power_delta (eeprom_read_modes) */
+#define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */
#define AR5K_EEPROM_VERSION_4_1 0x4001 /* has ee_margin_tx_rx (eeprom_init) */
#define AR5K_EEPROM_VERSION_4_2 0x4002 /* has ee_cck_ofdm_gain_delta (eeprom_init) */
-#define AR5K_EEPROM_VERSION_4_3 0x4003
+#define AR5K_EEPROM_VERSION_4_3 0x4003 /* power calibration changes */
#define AR5K_EEPROM_VERSION_4_4 0x4004
#define AR5K_EEPROM_VERSION_4_5 0x4005
#define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */
-#define AR5K_EEPROM_VERSION_4_7 0x4007
+#define AR5K_EEPROM_VERSION_4_7 0x3007 /* 4007 ? */
+#define AR5K_EEPROM_VERSION_4_9 0x4009 /* EAR futureproofing */
+#define AR5K_EEPROM_VERSION_5_0 0x5000 /* Has 2413 PDADC calibration etc */
+#define AR5K_EEPROM_VERSION_5_1 0x5001 /* Has capability values */
+#define AR5K_EEPROM_VERSION_5_3 0x5003 /* Has spur mitigation tables */
#define AR5K_EEPROM_MODE_11A 0
#define AR5K_EEPROM_MODE_11B 1
@@ -74,8 +62,8 @@
#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */
#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */
#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7)
-#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz (?) */
#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */
+#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz */
#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c
#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2
@@ -87,27 +75,95 @@
(((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0)
#define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3)
-#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((int8_t)(((_v) >> 8) & 0xff))
-#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((int8_t)((_v) & 0xff))
+#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((s8)(((_v) >> 8) & 0xff))
+#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((s8)((_v) & 0xff))
+
+/* Misc values available since EEPROM 4.0 */
+#define AR5K_EEPROM_MISC0 AR5K_EEPROM_INFO(4)
+#define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff)
+#define AR5K_EEPROM_HDR_XR2_DIS(_v) (((_v) >> 12) & 0x1)
+#define AR5K_EEPROM_HDR_XR5_DIS(_v) (((_v) >> 13) & 0x1)
+#define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3)
+
+#define AR5K_EEPROM_MISC1 AR5K_EEPROM_INFO(5)
+#define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff)
+#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1)
+#define AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(_v) (((_v) >> 15) & 0x1)
+
+#define AR5K_EEPROM_MISC2 AR5K_EEPROM_INFO(6)
+#define AR5K_EEPROM_EEP_FILE_VERSION(_v) (((_v) >> 8) & 0xff)
+#define AR5K_EEPROM_EAR_FILE_VERSION(_v) ((_v) & 0xff)
+
+#define AR5K_EEPROM_MISC3 AR5K_EEPROM_INFO(7)
+#define AR5K_EEPROM_ART_BUILD_NUM(_v) (((_v) >> 10) & 0x3f)
+#define AR5K_EEPROM_EAR_FILE_ID(_v) ((_v) & 0xff)
+
+#define AR5K_EEPROM_MISC4 AR5K_EEPROM_INFO(8)
+#define AR5K_EEPROM_CAL_DATA_START(_v) (((_v) >> 4) & 0xfff)
+#define AR5K_EEPROM_MASK_R0(_v) (((_v) >> 2) & 0x3)
+#define AR5K_EEPROM_MASK_R1(_v) ((_v) & 0x3)
+
+#define AR5K_EEPROM_MISC5 AR5K_EEPROM_INFO(9)
+#define AR5K_EEPROM_COMP_DIS(_v) ((_v) & 0x1)
+#define AR5K_EEPROM_AES_DIS(_v) (((_v) >> 1) & 0x1)
+#define AR5K_EEPROM_FF_DIS(_v) (((_v) >> 2) & 0x1)
+#define AR5K_EEPROM_BURST_DIS(_v) (((_v) >> 3) & 0x1)
+#define AR5K_EEPROM_MAX_QCU(_v) (((_v) >> 4) & 0xf)
+#define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1)
+#define AR5K_EEPROM_KEY_CACHE_SIZE(_v) (((_v) >> 12) & 0xf)
+
+#define AR5K_EEPROM_MISC6 AR5K_EEPROM_INFO(10)
+#define AR5K_EEPROM_TX_CHAIN_DIS ((_v) & 0x8)
+#define AR5K_EEPROM_RX_CHAIN_DIS (((_v) >> 3) & 0x8)
+#define AR5K_EEPROM_FCC_MID_EN (((_v) >> 6) & 0x1)
+#define AR5K_EEPROM_JAP_U1EVEN_EN (((_v) >> 7) & 0x1)
+#define AR5K_EEPROM_JAP_U2_EN (((_v) >> 8) & 0x1)
+#define AR5K_EEPROM_JAP_U1ODD_EN (((_v) >> 9) & 0x1)
+#define AR5K_EEPROM_JAP_11A_NEW_EN (((_v) >> 10) & 0x1)
/* calibration settings */
#define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4)
#define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2)
#define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d)
#define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128) /* Conformance test limits */
+#define AR5K_EEPROM_GROUPS_START(_v) AR5K_EEPROM_OFF(_v, 0x0100, 0x0150) /* Start of Groups */
+#define AR5K_EEPROM_GROUP1_OFFSET 0x0
+#define AR5K_EEPROM_GROUP2_OFFSET 0x5
+#define AR5K_EEPROM_GROUP3_OFFSET 0x37
+#define AR5K_EEPROM_GROUP4_OFFSET 0x46
+#define AR5K_EEPROM_GROUP5_OFFSET 0x55
+#define AR5K_EEPROM_GROUP6_OFFSET 0x65
+#define AR5K_EEPROM_GROUP7_OFFSET 0x69
+#define AR5K_EEPROM_GROUP8_OFFSET 0x6f
+
+#define AR5K_EEPROM_TARGET_PWR_OFF_11A(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
+ AR5K_EEPROM_GROUP5_OFFSET, 0x0000)
+#define AR5K_EEPROM_TARGET_PWR_OFF_11B(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
+ AR5K_EEPROM_GROUP6_OFFSET, 0x0010)
+#define AR5K_EEPROM_TARGET_PWR_OFF_11G(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \
+ AR5K_EEPROM_GROUP7_OFFSET, 0x0014)
/* [3.1 - 3.3] */
#define AR5K_EEPROM_OBDB0_2GHZ 0x00ec
#define AR5K_EEPROM_OBDB1_2GHZ 0x00ed
-/* Misc values available since EEPROM 4.0 */
-#define AR5K_EEPROM_MISC0 0x00c4
-#define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff)
-#define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3)
-#define AR5K_EEPROM_MISC1 0x00c5
-#define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff)
-#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1)
-
+#define AR5K_EEPROM_PROTECT 0x003f /* EEPROM protect status */
+#define AR5K_EEPROM_PROTECT_RD_0_31 0x0001 /* Read protection bit for offsets 0x0 - 0x1f */
+#define AR5K_EEPROM_PROTECT_WR_0_31 0x0002 /* Write protection bit for offsets 0x0 - 0x1f */
+#define AR5K_EEPROM_PROTECT_RD_32_63 0x0004 /* 0x20 - 0x3f */
+#define AR5K_EEPROM_PROTECT_WR_32_63 0x0008
+#define AR5K_EEPROM_PROTECT_RD_64_127 0x0010 /* 0x40 - 0x7f */
+#define AR5K_EEPROM_PROTECT_WR_64_127 0x0020
+#define AR5K_EEPROM_PROTECT_RD_128_191 0x0040 /* 0x80 - 0xbf (regdom) */
+#define AR5K_EEPROM_PROTECT_WR_128_191 0x0080
+#define AR5K_EEPROM_PROTECT_RD_192_207 0x0100 /* 0xc0 - 0xcf */
+#define AR5K_EEPROM_PROTECT_WR_192_207 0x0200
+#define AR5K_EEPROM_PROTECT_RD_208_223 0x0400 /* 0xd0 - 0xdf */
+#define AR5K_EEPROM_PROTECT_WR_208_223 0x0800
+#define AR5K_EEPROM_PROTECT_RD_224_239 0x1000 /* 0xe0 - 0xef */
+#define AR5K_EEPROM_PROTECT_WR_224_239 0x2000
+#define AR5K_EEPROM_PROTECT_RD_240_255 0x4000 /* 0xf0 - 0xff */
+#define AR5K_EEPROM_PROTECT_WR_240_255 0x8000
/* Some EEPROM defines */
#define AR5K_EEPROM_EEP_SCALE 100
@@ -115,8 +171,11 @@
#define AR5K_EEPROM_N_MODES 3
#define AR5K_EEPROM_N_5GHZ_CHAN 10
#define AR5K_EEPROM_N_2GHZ_CHAN 3
+#define AR5K_EEPROM_N_2GHZ_CHAN_2413 4
#define AR5K_EEPROM_MAX_CHAN 10
+#define AR5K_EEPROM_N_PWR_POINTS_5111 11
#define AR5K_EEPROM_N_PCDAC 11
+#define AR5K_EEPROM_N_PHASE_CAL 5
#define AR5K_EEPROM_N_TEST_FREQ 8
#define AR5K_EEPROM_N_EDGES 8
#define AR5K_EEPROM_N_INTERCEPTS 11
@@ -136,6 +195,8 @@
#define AR5K_EEPROM_N_XPD_PER_CHANNEL 4
#define AR5K_EEPROM_N_XPD0_POINTS 4
#define AR5K_EEPROM_N_XPD3_POINTS 3
+#define AR5K_EEPROM_N_PD_GAINS 4
+#define AR5K_EEPROM_N_PD_POINTS 5
#define AR5K_EEPROM_N_INTERCEPT_10_2GHZ 35
#define AR5K_EEPROM_N_INTERCEPT_10_5GHZ 55
#define AR5K_EEPROM_POWER_M 0x3f
@@ -158,8 +219,99 @@
#define AR5K_EEPROM_READ_HDR(_o, _v) \
AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \
-/* Struct to hold EEPROM calibration data */
+enum ath5k_ant_setting {
+ AR5K_ANT_VARIABLE = 0, /* variable by programming */
+ AR5K_ANT_FIXED_A = 1, /* fixed to 11a frequencies */
+ AR5K_ANT_FIXED_B = 2, /* fixed to 11b frequencies */
+ AR5K_ANT_MAX = 3,
+};
+
+enum ath5k_ctl_mode {
+ AR5K_CTL_11A = 0,
+ AR5K_CTL_11B = 1,
+ AR5K_CTL_11G = 2,
+ AR5K_CTL_TURBO = 3,
+ AR5K_CTL_108G = 4,
+ AR5K_CTL_2GHT20 = 5,
+ AR5K_CTL_5GHT20 = 6,
+ AR5K_CTL_2GHT40 = 7,
+ AR5K_CTL_5GHT40 = 8,
+ AR5K_CTL_MODE_M = 15,
+};
+
+/* Per channel calibration data, used for power table setup */
+struct ath5k_chan_pcal_info_rf5111 {
+ /* Power levels in half dbm units
+ * for one power curve. */
+ u8 pwr[AR5K_EEPROM_N_PWR_POINTS_5111];
+ /* PCDAC table steps
+ * for the above values */
+ u8 pcdac[AR5K_EEPROM_N_PWR_POINTS_5111];
+ /* Starting PCDAC step */
+ u8 pcdac_min;
+ /* Final PCDAC step */
+ u8 pcdac_max;
+};
+
+struct ath5k_chan_pcal_info_rf5112 {
+ /* Power levels in quarter dBm units
+ * for lower (0) and higher (3)
+ * level curves */
+ s8 pwr_x0[AR5K_EEPROM_N_XPD0_POINTS];
+ s8 pwr_x3[AR5K_EEPROM_N_XPD3_POINTS];
+ /* PCDAC table steps
+ * for the above values */
+ u8 pcdac_x0[AR5K_EEPROM_N_XPD0_POINTS];
+ u8 pcdac_x3[AR5K_EEPROM_N_XPD3_POINTS];
+};
+
+struct ath5k_chan_pcal_info_rf2413 {
+ /* Starting pwr/pddac values */
+ s8 pwr_i[AR5K_EEPROM_N_PD_GAINS];
+ u8 pddac_i[AR5K_EEPROM_N_PD_GAINS];
+ /* (pwr,pddac) points */
+ s8 pwr[AR5K_EEPROM_N_PD_GAINS]
+ [AR5K_EEPROM_N_PD_POINTS];
+ u8 pddac[AR5K_EEPROM_N_PD_GAINS]
+ [AR5K_EEPROM_N_PD_POINTS];
+};
+
+struct ath5k_chan_pcal_info {
+ /* Frequency */
+ u16 freq;
+ /* Max available power */
+ s8 max_pwr;
+ union {
+ struct ath5k_chan_pcal_info_rf5111 rf5111_info;
+ struct ath5k_chan_pcal_info_rf5112 rf5112_info;
+ struct ath5k_chan_pcal_info_rf2413 rf2413_info;
+ };
+};
+
+/* Per rate calibration data for each mode, used for power table setup */
+struct ath5k_rate_pcal_info {
+ u16 freq; /* Frequency */
+ /* Power level for 6-24Mbit/s rates */
+ u16 target_power_6to24;
+ /* Power level for 36Mbit rate */
+ u16 target_power_36;
+ /* Power level for 48Mbit rate */
+ u16 target_power_48;
+ /* Power level for 54Mbit rate */
+ u16 target_power_54;
+};
+
+/* Power edges for conformance test limits */
+struct ath5k_edge_power {
+ u16 freq;
+ u16 edge; /* in half dBm */
+ bool flag;
+};
+
+/* EEPROM calibration data */
struct ath5k_eeprom_info {
+
+ /* Header information */
u16 ee_magic;
u16 ee_protect;
u16 ee_regdomain;
@@ -168,6 +320,11 @@ struct ath5k_eeprom_info {
u16 ee_ant_gain;
u16 ee_misc0;
u16 ee_misc1;
+ u16 ee_misc2;
+ u16 ee_misc3;
+ u16 ee_misc4;
+ u16 ee_misc5;
+ u16 ee_misc6;
u16 ee_cck_ofdm_gain_delta;
u16 ee_cck_ofdm_power_delta;
u16 ee_scaled_cck_delta;
@@ -185,7 +342,7 @@ struct ath5k_eeprom_info {
u16 ee_turbo_max_power[AR5K_EEPROM_N_MODES];
u16 ee_xr_power[AR5K_EEPROM_N_MODES];
u16 ee_switch_settling[AR5K_EEPROM_N_MODES];
- u16 ee_ant_tx_rx[AR5K_EEPROM_N_MODES];
+ u16 ee_atn_tx_rx[AR5K_EEPROM_N_MODES];
u16 ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC];
u16 ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
u16 ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB];
@@ -198,18 +355,40 @@ struct ath5k_eeprom_info {
u16 ee_x_gain[AR5K_EEPROM_N_MODES];
u16 ee_i_gain[AR5K_EEPROM_N_MODES];
u16 ee_margin_tx_rx[AR5K_EEPROM_N_MODES];
+ u16 ee_switch_settling_turbo[AR5K_EEPROM_N_MODES];
+ u16 ee_margin_tx_rx_turbo[AR5K_EEPROM_N_MODES];
+ u16 ee_atn_tx_rx_turbo[AR5K_EEPROM_N_MODES];
- /* Unused */
+ /* Power calibration data */
u16 ee_false_detect[AR5K_EEPROM_N_MODES];
- u16 ee_cal_pier[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_2GHZ_CHAN];
- u16 ee_channel[AR5K_EEPROM_N_MODES][AR5K_EEPROM_MAX_CHAN]; /*empty*/
+
+ /* Number of pd gain curves per mode (RF2413) */
+ u8 ee_pd_gains[AR5K_EEPROM_N_MODES];
+
+ u8 ee_n_piers[AR5K_EEPROM_N_MODES];
+ struct ath5k_chan_pcal_info ee_pwr_cal_a[AR5K_EEPROM_N_5GHZ_CHAN];
+ struct ath5k_chan_pcal_info ee_pwr_cal_b[AR5K_EEPROM_N_2GHZ_CHAN];
+ struct ath5k_chan_pcal_info ee_pwr_cal_g[AR5K_EEPROM_N_2GHZ_CHAN];
+
+ /* Per rate target power levels */
+ u16 ee_rate_target_pwr_num[AR5K_EEPROM_N_MODES];
+ struct ath5k_rate_pcal_info ee_rate_tpwr_a[AR5K_EEPROM_N_5GHZ_CHAN];
+ struct ath5k_rate_pcal_info ee_rate_tpwr_b[AR5K_EEPROM_N_2GHZ_CHAN];
+ struct ath5k_rate_pcal_info ee_rate_tpwr_g[AR5K_EEPROM_N_2GHZ_CHAN];
/* Conformance test limits (Unused) */
u16 ee_ctls;
u16 ee_ctl[AR5K_EEPROM_MAX_CTLS];
+ struct ath5k_edge_power ee_ctl_pwr[AR5K_EEPROM_N_EDGES * AR5K_EEPROM_MAX_CTLS];
/* Noise Floor Calibration settings */
s16 ee_noise_floor_thr[AR5K_EEPROM_N_MODES];
s8 ee_adc_desired_size[AR5K_EEPROM_N_MODES];
s8 ee_pga_desired_size[AR5K_EEPROM_N_MODES];
+ s8 ee_adc_desired_size_turbo[AR5K_EEPROM_N_MODES];
+ s8 ee_pga_desired_size_turbo[AR5K_EEPROM_N_MODES];
+ s8 ee_pd_gain_overlap;
+
+ u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX];
};
+
diff --git a/drivers/net/wireless/ath5k/initvals.c b/drivers/net/wireless/ath5k/initvals.c
index ceaa6c475c06..450bd6e945ff 100644
--- a/drivers/net/wireless/ath5k/initvals.c
+++ b/drivers/net/wireless/ath5k/initvals.c
@@ -1681,7 +1681,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
*/
/* For AR5212 and combatible */
- if (ah->ah_version == AR5K_AR5212){
+ if (ah->ah_version == AR5K_AR5212) {
/* First set of mode-specific settings */
ath5k_hw_ini_mode_registers(ah,
@@ -1695,7 +1695,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
ar5212_ini, change_channel);
/* Second set of mode-specific settings */
- if (ah->ah_radio == AR5K_RF5111){
+ if (ah->ah_radio == AR5K_RF5111) {
ath5k_hw_ini_mode_registers(ah,
ARRAY_SIZE(ar5212_rf5111_ini_mode_end),
@@ -1706,7 +1706,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
ARRAY_SIZE(rf5111_ini_bbgain),
rf5111_ini_bbgain, change_channel);
- } else if (ah->ah_radio == AR5K_RF5112){
+ } else if (ah->ah_radio == AR5K_RF5112) {
ath5k_hw_ini_mode_registers(ah,
ARRAY_SIZE(ar5212_rf5112_ini_mode_end),
@@ -1716,7 +1716,7 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel)
ARRAY_SIZE(rf5112_ini_bbgain),
rf5112_ini_bbgain, change_channel);
- } else if (ah->ah_radio == AR5K_RF5413){
+ } else if (ah->ah_radio == AR5K_RF5413) {
ath5k_hw_ini_mode_registers(ah,
ARRAY_SIZE(rf5413_ini_mode_end),
diff --git a/drivers/net/wireless/ath5k/pcu.c b/drivers/net/wireless/ath5k/pcu.c
index a47df9a24aa1..0cac05c6a9ce 100644
--- a/drivers/net/wireless/ath5k/pcu.c
+++ b/drivers/net/wireless/ath5k/pcu.c
@@ -46,34 +46,45 @@ int ath5k_hw_set_opmode(struct ath5k_hw *ah)
{
u32 pcu_reg, beacon_reg, low_id, high_id;
- pcu_reg = 0;
+
+ /* Preserve rest settings */
+ pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
+ pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP
+ | AR5K_STA_ID1_KEYSRCH_MODE
+ | (ah->ah_version == AR5K_AR5210 ?
+ (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0));
+
beacon_reg = 0;
ATH5K_TRACE(ah->ah_sc);
switch (ah->ah_op_mode) {
case NL80211_IFTYPE_ADHOC:
- pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_DESC_ANTENNA |
- (ah->ah_version == AR5K_AR5210 ?
- AR5K_STA_ID1_NO_PSPOLL : 0);
+ pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE;
beacon_reg |= AR5K_BCR_ADHOC;
+ if (ah->ah_version == AR5K_AR5210)
+ pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
+ else
+ AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_ADHOC);
break;
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
- pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_RTS_DEF_ANTENNA |
- (ah->ah_version == AR5K_AR5210 ?
- AR5K_STA_ID1_NO_PSPOLL : 0);
+ pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE;
beacon_reg |= AR5K_BCR_AP;
+ if (ah->ah_version == AR5K_AR5210)
+ pcu_reg |= AR5K_STA_ID1_NO_PSPOLL;
+ else
+ AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_ADHOC);
break;
case NL80211_IFTYPE_STATION:
- pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA |
- (ah->ah_version == AR5K_AR5210 ?
+ pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
+ | (ah->ah_version == AR5K_AR5210 ?
AR5K_STA_ID1_PWR_SV : 0);
case NL80211_IFTYPE_MONITOR:
- pcu_reg |= AR5K_STA_ID1_DEFAULT_ANTENNA |
- (ah->ah_version == AR5K_AR5210 ?
+ pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
+ | (ah->ah_version == AR5K_AR5210 ?
AR5K_STA_ID1_NO_PSPOLL : 0);
break;
@@ -130,6 +141,8 @@ void ath5k_hw_update_mib_counters(struct ath5k_hw *ah,
ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR);
ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE);
}
+
+ /* TODO: Handle ANI stats */
}
/**
@@ -258,16 +271,19 @@ void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac)
int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac)
{
u32 low_id, high_id;
+ u32 pcu_reg;
ATH5K_TRACE(ah->ah_sc);
/* Set new station ID */
memcpy(ah->ah_sta_id, mac, ETH_ALEN);
+ pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000;
+
low_id = AR5K_LOW_ID(mac);
high_id = AR5K_HIGH_ID(mac);
ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0);
- ath5k_hw_reg_write(ah, high_id, AR5K_STA_ID1);
+ ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1);
return 0;
}
@@ -290,8 +306,10 @@ void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id)
* Set simple BSSID mask on 5212
*/
if (ah->ah_version == AR5K_AR5212) {
- ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM0);
- ath5k_hw_reg_write(ah, 0xffffffff, AR5K_BSS_IDM1);
+ ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask),
+ AR5K_BSS_IDM0);
+ ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask),
+ AR5K_BSS_IDM1);
}
/*
@@ -415,6 +433,9 @@ int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask)
u32 low_id, high_id;
ATH5K_TRACE(ah->ah_sc);
+ /* Cache bssid mask so that we can restore it
+ * on reset */
+ memcpy(ah->ah_bssid_mask, mask, ETH_ALEN);
if (ah->ah_version == AR5K_AR5212) {
low_id = AR5K_LOW_ID(mask);
high_id = AR5K_HIGH_ID(mask);
@@ -576,7 +597,7 @@ void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter)
filter |= AR5K_RX_FILTER_PROM;
}
- /*Zero length DMA*/
+ /*Zero length DMA (phy error reporting) */
if (data)
AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA);
else
@@ -661,7 +682,12 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
* Set the additional timers by mode
*/
switch (ah->ah_op_mode) {
+ case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_STATION:
+ /* In STA mode timer1 is used as next wakeup
+ * timer and timer2 as next CFP duration start
+ * timer. Both in 1/8TUs. */
+ /* TODO: PCF handling */
if (ah->ah_version == AR5K_AR5210) {
timer1 = 0xffffffff;
timer2 = 0xffffffff;
@@ -669,27 +695,60 @@ void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
timer1 = 0x0000ffff;
timer2 = 0x0007ffff;
}
+ /* Mark associated AP as PCF incapable for now */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PCF);
break;
-
+ case NL80211_IFTYPE_ADHOC:
+ AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_ADHOC_BCN_ATIM);
default:
+ /* On non-STA modes timer1 is used as next DMA
+ * beacon alert (DBA) timer and timer2 as next
+ * software beacon alert. Both in 1/8TUs. */
timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3;
timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3;
+ break;
}
+ /* Timer3 marks the end of our ATIM window
+ * a zero length window is not allowed because
+ * we 'll get no beacons */
timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1);
/*
* Set the beacon register and enable all timers.
- * (next beacon, DMA beacon, software beacon, ATIM window time)
*/
- ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
+ /* When in AP mode zero timer0 to start TSF */
+ if (ah->ah_op_mode == NL80211_IFTYPE_AP)
+ ath5k_hw_reg_write(ah, 0, AR5K_TIMER0);
+ else
+ ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0);
ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1);
ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2);
ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3);
+ /* Force a TSF reset if requested and enable beacons */
+ if (interval & AR5K_BEACON_RESET_TSF)
+ ath5k_hw_reset_tsf(ah);
+
ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD |
- AR5K_BEACON_RESET_TSF | AR5K_BEACON_ENABLE),
- AR5K_BEACON);
+ AR5K_BEACON_ENABLE),
+ AR5K_BEACON);
+
+ /* Flush any pending BMISS interrupts on ISR by
+ * performing a clear-on-write operation on PISR
+ * register for the BMISS bit (writing a bit on
+ * ISR togles a reset for that bit and leaves
+ * the rest bits intact) */
+ if (ah->ah_version == AR5K_AR5210)
+ ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_ISR);
+ else
+ ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_PISR);
+
+ /* TODO: Set enchanced sleep registers on AR5212
+ * based on vif->bss_conf params, until then
+ * disable power save reporting.*/
+ AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PWR_SV);
+
}
#if 0
@@ -899,14 +958,26 @@ int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr)
*/
int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
{
- unsigned int i;
+ unsigned int i, type;
+ u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
ATH5K_TRACE(ah->ah_sc);
AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE);
+ type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry));
+
for (i = 0; i < AR5K_KEYCACHE_SIZE; i++)
ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i));
+ /* Reset associated MIC entry if TKIP
+ * is enabled located at offset (entry + 64) */
+ if (type == AR5K_KEYTABLE_TYPE_TKIP) {
+ AR5K_ASSERT_ENTRY(micentry, AR5K_KEYTABLE_SIZE);
+ for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++)
+ ath5k_hw_reg_write(ah, 0,
+ AR5K_KEYTABLE_OFF(micentry, i));
+ }
+
/*
* Set NULL encryption on AR5212+
*
@@ -916,10 +987,16 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry)
* Note2: Windows driver (ndiswrapper) sets this to
* 0x00000714 instead of 0x00000007
*/
- if (ah->ah_version > AR5K_AR5211)
+ if (ah->ah_version > AR5K_AR5211) {
ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
AR5K_KEYTABLE_TYPE(entry));
+ if (type == AR5K_KEYTABLE_TYPE_TKIP) {
+ ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
+ AR5K_KEYTABLE_TYPE(micentry));
+ }
+ }
+
return 0;
}
@@ -936,6 +1013,23 @@ int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry)
AR5K_KEYTABLE_VALID;
}
+static
+int ath5k_keycache_type(const struct ieee80211_key_conf *key)
+{
+ switch (key->alg) {
+ case ALG_TKIP:
+ return AR5K_KEYTABLE_TYPE_TKIP;
+ case ALG_CCMP:
+ return AR5K_KEYTABLE_TYPE_CCM;
+ case ALG_WEP:
+ if (key->keylen == LEN_WEP40)
+ return AR5K_KEYTABLE_TYPE_40;
+ else if (key->keylen == LEN_WEP104)
+ return AR5K_KEYTABLE_TYPE_104;
+ }
+ return -EINVAL;
+}
+
/*
* Set a key entry on the table
*/
@@ -943,40 +1037,53 @@ int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
const struct ieee80211_key_conf *key, const u8 *mac)
{
unsigned int i;
+ int keylen;
__le32 key_v[5] = {};
+ __le32 key0 = 0, key1 = 0;
+ __le32 *rxmic, *txmic;
u32 keytype;
+ u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET;
+ bool is_tkip;
+ const u8 *key_ptr;
ATH5K_TRACE(ah->ah_sc);
- /* key->keylen comes in from mac80211 in bytes */
+ is_tkip = (key->alg == ALG_TKIP);
- if (key->keylen > AR5K_KEYTABLE_SIZE / 8)
+ /*
+ * key->keylen comes in from mac80211 in bytes.
+ * TKIP is 128 bit + 128 bit mic
+ */
+ keylen = (is_tkip) ? (128 / 8) : key->keylen;
+
+ if (entry > AR5K_KEYTABLE_SIZE ||
+ (is_tkip && micentry > AR5K_KEYTABLE_SIZE))
return -EOPNOTSUPP;
- switch (key->keylen) {
- /* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit */
- case 40 / 8:
- memcpy(&key_v[0], key->key, 5);
- keytype = AR5K_KEYTABLE_TYPE_40;
- break;
+ if (unlikely(keylen > 16))
+ return -EOPNOTSUPP;
- /* WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit */
- case 104 / 8:
- memcpy(&key_v[0], &key->key[0], 6);
- memcpy(&key_v[2], &key->key[6], 6);
- memcpy(&key_v[4], &key->key[12], 1);
- keytype = AR5K_KEYTABLE_TYPE_104;
- break;
- /* WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit */
- case 128 / 8:
- memcpy(&key_v[0], &key->key[0], 6);
- memcpy(&key_v[2], &key->key[6], 6);
- memcpy(&key_v[4], &key->key[12], 4);
- keytype = AR5K_KEYTABLE_TYPE_128;
- break;
+ keytype = ath5k_keycache_type(key);
+ if (keytype < 0)
+ return keytype;
- default:
- return -EINVAL; /* shouldn't happen */
+ /*
+ * each key block is 6 bytes wide, written as pairs of
+ * alternating 32 and 16 bit le values.
+ */
+ key_ptr = key->key;
+ for (i = 0; keylen >= 6; keylen -= 6) {
+ memcpy(&key_v[i], key_ptr, 6);
+ i += 2;
+ key_ptr += 6;
+ }
+ if (keylen)
+ memcpy(&key_v[i], key_ptr, keylen);
+
+ /* intentionally corrupt key until mic is installed */
+ if (is_tkip) {
+ key0 = key_v[0] = ~key_v[0];
+ key1 = key_v[1] = ~key_v[1];
}
for (i = 0; i < ARRAY_SIZE(key_v); i++)
@@ -985,6 +1092,40 @@ int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry,
ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry));
+ if (is_tkip) {
+ /* Install rx/tx MIC */
+ rxmic = (__le32 *) &key->key[16];
+ txmic = (__le32 *) &key->key[24];
+
+ if (ah->ah_combined_mic) {
+ key_v[0] = rxmic[0];
+ key_v[1] = cpu_to_le32(le32_to_cpu(txmic[0]) >> 16);
+ key_v[2] = rxmic[1];
+ key_v[3] = cpu_to_le32(le32_to_cpu(txmic[0]) & 0xffff);
+ key_v[4] = txmic[1];
+ } else {
+ key_v[0] = rxmic[0];
+ key_v[1] = 0;
+ key_v[2] = rxmic[1];
+ key_v[3] = 0;
+ key_v[4] = 0;
+ }
+ for (i = 0; i < ARRAY_SIZE(key_v); i++)
+ ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]),
+ AR5K_KEYTABLE_OFF(micentry, i));
+
+ ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL,
+ AR5K_KEYTABLE_TYPE(micentry));
+ ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC0(micentry));
+ ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC1(micentry));
+
+ /* restore first 2 words of key */
+ ath5k_hw_reg_write(ah, le32_to_cpu(~key0),
+ AR5K_KEYTABLE_OFF(entry, 0));
+ ath5k_hw_reg_write(ah, le32_to_cpu(~key1),
+ AR5K_KEYTABLE_OFF(entry, 1));
+ }
+
return ath5k_hw_set_key_lladdr(ah, entry, mac);
}
diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c
index e43f6563e61a..7ba18e09463b 100644
--- a/drivers/net/wireless/ath5k/phy.c
+++ b/drivers/net/wireless/ath5k/phy.c
@@ -1412,7 +1412,8 @@ static int ath5k_hw_rf5112_rfregs(struct ath5k_hw *ah,
rf_ini = rfregs_2112a;
rf_size = ARRAY_SIZE(rfregs_5112a);
if (mode < 2) {
- ATH5K_ERR(ah->ah_sc,"invalid channel mode: %i\n",mode);
+ ATH5K_ERR(ah->ah_sc, "invalid channel mode: %i\n",
+ mode);
return -EINVAL;
}
mode = mode - 2; /*no a/turboa modes for 2112*/
@@ -1708,7 +1709,7 @@ enum ath5k_rfgain ath5k_hw_get_rf_gain(struct ath5k_hw *ah)
if (ah->ah_radio >= AR5K_RF5112) {
ath5k_hw_rfregs_gainf_corr(ah);
ah->ah_gain.g_current =
- ah->ah_gain.g_current>=ah->ah_gain.g_f_corr ?
+ ah->ah_gain.g_current >= ah->ah_gain.g_f_corr ?
(ah->ah_gain.g_current-ah->ah_gain.g_f_corr) :
0;
}
@@ -2195,9 +2196,7 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
return ret;
}
- ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
- if (ret)
- return ret;
+ ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
/*
* Re-enable RX/TX and beacons
diff --git a/drivers/net/wireless/ath5k/qcu.c b/drivers/net/wireless/ath5k/qcu.c
index 01bf09176d23..1b7bc50ea8eb 100644
--- a/drivers/net/wireless/ath5k/qcu.c
+++ b/drivers/net/wireless/ath5k/qcu.c
@@ -432,13 +432,30 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE)
AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue);
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue);
+
+ if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE)
+ AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue);
/* Update secondary interrupt mask registers */
+
+ /* Filter out inactive queues */
ah->ah_txq_imr_txok &= ah->ah_txq_status;
ah->ah_txq_imr_txerr &= ah->ah_txq_status;
ah->ah_txq_imr_txurn &= ah->ah_txq_status;
ah->ah_txq_imr_txdesc &= ah->ah_txq_status;
ah->ah_txq_imr_txeol &= ah->ah_txq_status;
+ ah->ah_txq_imr_cbrorn &= ah->ah_txq_status;
+ ah->ah_txq_imr_cbrurn &= ah->ah_txq_status;
+ ah->ah_txq_imr_qtrig &= ah->ah_txq_status;
+ ah->ah_txq_imr_nofrm &= ah->ah_txq_status;
ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok,
AR5K_SIMR0_QCU_TXOK) |
@@ -448,8 +465,24 @@ int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue)
AR5K_SIMR1_QCU_TXERR) |
AR5K_REG_SM(ah->ah_txq_imr_txeol,
AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1);
- ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txurn,
- AR5K_SIMR2_QCU_TXURN), AR5K_SIMR2);
+ /* Update simr2 but don't overwrite rest simr2 settings */
+ AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN);
+ AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2,
+ AR5K_REG_SM(ah->ah_txq_imr_txurn,
+ AR5K_SIMR2_QCU_TXURN));
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn,
+ AR5K_SIMR3_QCBRORN) |
+ AR5K_REG_SM(ah->ah_txq_imr_cbrurn,
+ AR5K_SIMR3_QCBRURN), AR5K_SIMR3);
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig,
+ AR5K_SIMR4_QTRIG), AR5K_SIMR4);
+ /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */
+ ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm,
+ AR5K_TXNOFRM_QCU), AR5K_TXNOFRM);
+ /* No queue has TXNOFRM enabled, disable the interrupt
+ * by setting AR5K_TXNOFRM to zero */
+ if (ah->ah_txq_imr_nofrm == 0)
+ ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM);
}
return 0;
diff --git a/drivers/net/wireless/ath5k/reg.h b/drivers/net/wireless/ath5k/reg.h
index e557fe178bbf..91aaeaf88199 100644
--- a/drivers/net/wireless/ath5k/reg.h
+++ b/drivers/net/wireless/ath5k/reg.h
@@ -234,6 +234,7 @@
#define AR5K_TXNOFRM 0x004c
#define AR5K_TXNOFRM_M 0x000003ff
#define AR5K_TXNOFRM_QCU 0x000ffc00
+#define AR5K_TXNOFRM_QCU_S 10
/*
* Receive frame gap timeout register
@@ -350,7 +351,7 @@
#define AR5K_SISR3 0x0090 /* Register Address [5211+] */
#define AR5K_SISR3_QCBRORN 0x000003ff /* Mask for QCBRORN */
-#define AR5K_SISR3_QCBORN_S 0
+#define AR5K_SISR3_QCBRORN_S 0
#define AR5K_SISR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */
#define AR5K_SISR3_QCBRURN_S 16
@@ -1113,14 +1114,16 @@
#define AR5K_PCU_MAX 0x8fff
/*
- * First station id register (MAC address in lower 32 bits)
+ * First station id register (Lower 32 bits of MAC address)
*/
-#define AR5K_STA_ID0 0x8000
+#define AR5K_STA_ID0 0x8000
+#define AR5K_STA_ID0_ARRD_L32 0xffffffff
/*
- * Second station id register (MAC address in upper 16 bits)
+ * Second station id register (Upper 16 bits of MAC address + PCU settings)
*/
#define AR5K_STA_ID1 0x8004 /* Register Address */
+#define AR5K_STA_ID1_ADDR_U16 0x0000ffff /* Upper 16 bits of MAC addres */
#define AR5K_STA_ID1_AP 0x00010000 /* Set AP mode */
#define AR5K_STA_ID1_ADHOC 0x00020000 /* Set Ad-Hoc mode */
#define AR5K_STA_ID1_PWR_SV 0x00040000 /* Power save reporting */
@@ -1726,6 +1729,7 @@
#define AR5K_MISC_MODE 0x8120 /* Register Address */
#define AR5K_MISC_MODE_FBSSID_MATCH 0x00000001 /* Force BSSID match */
#define AR5K_MISC_MODE_ACKSIFS_MEM 0x00000002 /* ACK SIFS memory (?) */
+#define AR5K_MISC_MODE_COMBINED_MIC 0x00000004 /* use rx/tx MIC key */
/* more bits */
/*
@@ -1810,6 +1814,10 @@
#define AR5K_KEYTABLE_MAC1(_n) AR5K_KEYTABLE_OFF(_n, 7)
#define AR5K_KEYTABLE_VALID 0x00008000
+/* If key type is TKIP and MIC is enabled
+ * MIC key goes in offset entry + 64 */
+#define AR5K_KEYTABLE_MIC_OFFSET 64
+
/* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit
* WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit
* WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit
diff --git a/drivers/net/wireless/ath5k/reset.c b/drivers/net/wireless/ath5k/reset.c
index 1b6d45b6772d..dc2d7d8bdb7a 100644
--- a/drivers/net/wireless/ath5k/reset.c
+++ b/drivers/net/wireless/ath5k/reset.c
@@ -674,7 +674,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
(ee->ee_switch_settling[ee_mode] << 7) & 0x3f80,
0xffffc07f);
AR5K_REG_MASKED_BITS(ah, AR5K_PHY_GAIN,
- (ee->ee_ant_tx_rx[ee_mode] << 12) & 0x3f000,
+ (ee->ee_atn_tx_rx[ee_mode] << 12) & 0x3f000,
0xfffc0fff);
AR5K_REG_MASKED_BITS(ah, AR5K_PHY_DESIRED_SIZE,
(ee->ee_adc_desired_size[ee_mode] & 0x00ff) |
@@ -842,9 +842,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
*
* XXX: Find an interval that's OK for all cards...
*/
- ret = ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
- if (ret)
- return ret;
+ ath5k_hw_noise_floor_calibration(ah, channel->center_freq);
/*
* Reset queues and start beacon timers at the end of the reset routine
@@ -864,8 +862,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
/* Pre-enable interrupts on 5211/5212*/
if (ah->ah_version != AR5K_AR5210)
- ath5k_hw_set_imr(ah, AR5K_INT_RX | AR5K_INT_TX |
- AR5K_INT_FATAL);
+ ath5k_hw_set_imr(ah, ah->ah_imr);
/*
* Set RF kill flags if supported by the device (read from the EEPROM)
diff --git a/drivers/net/wireless/ath9k/Kconfig b/drivers/net/wireless/ath9k/Kconfig
index 80a692430413..c43bd321f97f 100644
--- a/drivers/net/wireless/ath9k/Kconfig
+++ b/drivers/net/wireless/ath9k/Kconfig
@@ -9,3 +9,14 @@ config ATH9K
Atheros IEEE 802.11n AR5008 and AR9001 family of chipsets.
If you choose to build a module, it'll be called ath9k.
+
+config ATH9K_DEBUG
+ bool "Atheros ath9k debugging"
+ depends on ATH9K
+ ---help---
+ Say Y, if you need ath9k to display debug messages.
+ Pass the debug mask as a module parameter:
+
+ modprobe ath9k debug=0x00002000
+
+ Look in ath9k/core.h for possible debug masks
diff --git a/drivers/net/wireless/ath9k/Makefile b/drivers/net/wireless/ath9k/Makefile
index a6411517e5f8..1209d14613ac 100644
--- a/drivers/net/wireless/ath9k/Makefile
+++ b/drivers/net/wireless/ath9k/Makefile
@@ -1,11 +1,16 @@
ath9k-y += hw.o \
+ eeprom.o \
+ mac.o \
+ calib.o \
+ ani.o \
phy.o \
regd.o \
beacon.o \
main.o \
recv.o \
xmit.o \
- rc.o \
- core.o
+ rc.o
+
+ath9k-$(CONFIG_ATH9K_DEBUG) += debug.o
obj-$(CONFIG_ATH9K) += ath9k.o
diff --git a/drivers/net/wireless/ath9k/ani.c b/drivers/net/wireless/ath9k/ani.c
new file mode 100644
index 000000000000..251e2d9a7a4a
--- /dev/null
+++ b/drivers/net/wireless/ath9k/ani.c
@@ -0,0 +1,852 @@
+/*
+ * Copyright (c) 2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "core.h"
+#include "hw.h"
+#include "reg.h"
+#include "phy.h"
+
+static int ath9k_hw_get_ani_channel_idx(struct ath_hal *ah,
+ struct ath9k_channel *chan)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(ahp->ah_ani); i++) {
+ if (ahp->ah_ani[i].c.channel == chan->channel)
+ return i;
+ if (ahp->ah_ani[i].c.channel == 0) {
+ ahp->ah_ani[i].c.channel = chan->channel;
+ ahp->ah_ani[i].c.channelFlags = chan->channelFlags;
+ return i;
+ }
+ }
+
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "No more channel states left. Using channel 0\n");
+
+ return 0;
+}
+
+static bool ath9k_hw_ani_control(struct ath_hal *ah,
+ enum ath9k_ani_cmd cmd, int param)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416AniState *aniState = ahp->ah_curani;
+
+ switch (cmd & ahp->ah_ani_function) {
+ case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
+ u32 level = param;
+
+ if (level >= ARRAY_SIZE(ahp->ah_totalSizeDesired)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "level out of range (%u > %u)\n",
+ level,
+ (unsigned)ARRAY_SIZE(ahp->ah_totalSizeDesired));
+ return false;
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+ AR_PHY_DESIRED_SZ_TOT_DES,
+ ahp->ah_totalSizeDesired[level]);
+ REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
+ AR_PHY_AGC_CTL1_COARSE_LOW,
+ ahp->ah_coarseLow[level]);
+ REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
+ AR_PHY_AGC_CTL1_COARSE_HIGH,
+ ahp->ah_coarseHigh[level]);
+ REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+ AR_PHY_FIND_SIG_FIRPWR,
+ ahp->ah_firpwr[level]);
+
+ if (level > aniState->noiseImmunityLevel)
+ ahp->ah_stats.ast_ani_niup++;
+ else if (level < aniState->noiseImmunityLevel)
+ ahp->ah_stats.ast_ani_nidown++;
+ aniState->noiseImmunityLevel = level;
+ break;
+ }
+ case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
+ const int m1ThreshLow[] = { 127, 50 };
+ const int m2ThreshLow[] = { 127, 40 };
+ const int m1Thresh[] = { 127, 0x4d };
+ const int m2Thresh[] = { 127, 0x40 };
+ const int m2CountThr[] = { 31, 16 };
+ const int m2CountThrLow[] = { 63, 48 };
+ u32 on = param ? 1 : 0;
+
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
+ m1ThreshLow[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
+ m2ThreshLow[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+ AR_PHY_SFCORR_M1_THRESH,
+ m1Thresh[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+ AR_PHY_SFCORR_M2_THRESH,
+ m2Thresh[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR,
+ AR_PHY_SFCORR_M2COUNT_THR,
+ m2CountThr[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
+ m2CountThrLow[on]);
+
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
+ m1ThreshLow[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
+ m2ThreshLow[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M1_THRESH,
+ m1Thresh[on]);
+ REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
+ AR_PHY_SFCORR_EXT_M2_THRESH,
+ m2Thresh[on]);
+
+ if (on)
+ REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+ else
+ REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
+ AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+
+ if (!on != aniState->ofdmWeakSigDetectOff) {
+ if (on)
+ ahp->ah_stats.ast_ani_ofdmon++;
+ else
+ ahp->ah_stats.ast_ani_ofdmoff++;
+ aniState->ofdmWeakSigDetectOff = !on;
+ }
+ break;
+ }
+ case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
+ const int weakSigThrCck[] = { 8, 6 };
+ u32 high = param ? 1 : 0;
+
+ REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
+ AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
+ weakSigThrCck[high]);
+ if (high != aniState->cckWeakSigThreshold) {
+ if (high)
+ ahp->ah_stats.ast_ani_cckhigh++;
+ else
+ ahp->ah_stats.ast_ani_ccklow++;
+ aniState->cckWeakSigThreshold = high;
+ }
+ break;
+ }
+ case ATH9K_ANI_FIRSTEP_LEVEL:{
+ const int firstep[] = { 0, 4, 8 };
+ u32 level = param;
+
+ if (level >= ARRAY_SIZE(firstep)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "level out of range (%u > %u)\n",
+ level,
+ (unsigned) ARRAY_SIZE(firstep));
+ return false;
+ }
+ REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
+ AR_PHY_FIND_SIG_FIRSTEP,
+ firstep[level]);
+ if (level > aniState->firstepLevel)
+ ahp->ah_stats.ast_ani_stepup++;
+ else if (level < aniState->firstepLevel)
+ ahp->ah_stats.ast_ani_stepdown++;
+ aniState->firstepLevel = level;
+ break;
+ }
+ case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
+ const int cycpwrThr1[] =
+ { 2, 4, 6, 8, 10, 12, 14, 16 };
+ u32 level = param;
+
+ if (level >= ARRAY_SIZE(cycpwrThr1)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "level out of range (%u > %u)\n",
+ level,
+ (unsigned)
+ ARRAY_SIZE(cycpwrThr1));
+ return false;
+ }
+ REG_RMW_FIELD(ah, AR_PHY_TIMING5,
+ AR_PHY_TIMING5_CYCPWR_THR1,
+ cycpwrThr1[level]);
+ if (level > aniState->spurImmunityLevel)
+ ahp->ah_stats.ast_ani_spurup++;
+ else if (level < aniState->spurImmunityLevel)
+ ahp->ah_stats.ast_ani_spurdown++;
+ aniState->spurImmunityLevel = level;
+ break;
+ }
+ case ATH9K_ANI_PRESENT:
+ break;
+ default:
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "invalid cmd %u\n", cmd);
+ return false;
+ }
+
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI, "ANI parameters:\n");
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "noiseImmunityLevel=%d, spurImmunityLevel=%d, "
+ "ofdmWeakSigDetectOff=%d\n",
+ aniState->noiseImmunityLevel, aniState->spurImmunityLevel,
+ !aniState->ofdmWeakSigDetectOff);
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "cckWeakSigThreshold=%d, "
+ "firstepLevel=%d, listenTime=%d\n",
+ aniState->cckWeakSigThreshold, aniState->firstepLevel,
+ aniState->listenTime);
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
+ aniState->cycleCount, aniState->ofdmPhyErrCount,
+ aniState->cckPhyErrCount);
+
+ return true;
+}
+
+static void ath9k_hw_update_mibstats(struct ath_hal *ah,
+ struct ath9k_mib_stats *stats)
+{
+ stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
+ stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
+ stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
+ stats->rts_good += REG_READ(ah, AR_RTS_OK);
+ stats->beacons += REG_READ(ah, AR_BEACON_CNT);
+}
+
+static void ath9k_ani_restart(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416AniState *aniState;
+
+ if (!DO_ANI(ah))
+ return;
+
+ aniState = ahp->ah_curani;
+
+ aniState->listenTime = 0;
+ if (ahp->ah_hasHwPhyCounters) {
+ if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
+ aniState->ofdmPhyErrBase = 0;
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "OFDM Trigger is too high for hw counters\n");
+ } else {
+ aniState->ofdmPhyErrBase =
+ AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
+ }
+ if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
+ aniState->cckPhyErrBase = 0;
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "CCK Trigger is too high for hw counters\n");
+ } else {
+ aniState->cckPhyErrBase =
+ AR_PHY_COUNTMAX - aniState->cckTrigHigh;
+ }
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "Writing ofdmbase=%u cckbase=%u\n",
+ aniState->ofdmPhyErrBase,
+ aniState->cckPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+ ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
+ }
+ aniState->ofdmPhyErrCount = 0;
+ aniState->cckPhyErrCount = 0;
+}
+
+static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_channel *chan = ah->ah_curchan;
+ struct ar5416AniState *aniState;
+ enum wireless_mode mode;
+ int32_t rssi;
+
+ if (!DO_ANI(ah))
+ return;
+
+ aniState = ahp->ah_curani;
+
+ if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
+ if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
+ aniState->noiseImmunityLevel + 1)) {
+ return;
+ }
+ }
+
+ if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
+ if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
+ aniState->spurImmunityLevel + 1)) {
+ return;
+ }
+ }
+
+ if (ah->ah_opmode == NL80211_IFTYPE_AP) {
+ if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
+ ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel + 1);
+ }
+ return;
+ }
+ rssi = BEACON_RSSI(ahp);
+ if (rssi > aniState->rssiThrHigh) {
+ if (!aniState->ofdmWeakSigDetectOff) {
+ if (ath9k_hw_ani_control(ah,
+ ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ false)) {
+ ath9k_hw_ani_control(ah,
+ ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
+ return;
+ }
+ }
+ if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
+ ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel + 1);
+ return;
+ }
+ } else if (rssi > aniState->rssiThrLow) {
+ if (aniState->ofdmWeakSigDetectOff)
+ ath9k_hw_ani_control(ah,
+ ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ true);
+ if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
+ ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel + 1);
+ return;
+ } else {
+ mode = ath9k_hw_chan2wmode(ah, chan);
+ if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
+ if (!aniState->ofdmWeakSigDetectOff)
+ ath9k_hw_ani_control(ah,
+ ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ false);
+ if (aniState->firstepLevel > 0)
+ ath9k_hw_ani_control(ah,
+ ATH9K_ANI_FIRSTEP_LEVEL, 0);
+ return;
+ }
+ }
+}
+
+static void ath9k_hw_ani_cck_err_trigger(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_channel *chan = ah->ah_curchan;
+ struct ar5416AniState *aniState;
+ enum wireless_mode mode;
+ int32_t rssi;
+
+ if (!DO_ANI(ah))
+ return;
+
+ aniState = ahp->ah_curani;
+ if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
+ if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
+ aniState->noiseImmunityLevel + 1)) {
+ return;
+ }
+ }
+ if (ah->ah_opmode == NL80211_IFTYPE_AP) {
+ if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
+ ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel + 1);
+ }
+ return;
+ }
+ rssi = BEACON_RSSI(ahp);
+ if (rssi > aniState->rssiThrLow) {
+ if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
+ ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel + 1);
+ } else {
+ mode = ath9k_hw_chan2wmode(ah, chan);
+ if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
+ if (aniState->firstepLevel > 0)
+ ath9k_hw_ani_control(ah,
+ ATH9K_ANI_FIRSTEP_LEVEL, 0);
+ }
+ }
+}
+
+static void ath9k_hw_ani_lower_immunity(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416AniState *aniState;
+ int32_t rssi;
+
+ aniState = ahp->ah_curani;
+
+ if (ah->ah_opmode == NL80211_IFTYPE_AP) {
+ if (aniState->firstepLevel > 0) {
+ if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel - 1))
+ return;
+ }
+ } else {
+ rssi = BEACON_RSSI(ahp);
+ if (rssi > aniState->rssiThrHigh) {
+ /* XXX: Handle me */
+ } else if (rssi > aniState->rssiThrLow) {
+ if (aniState->ofdmWeakSigDetectOff) {
+ if (ath9k_hw_ani_control(ah,
+ ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ true) == true)
+ return;
+ }
+ if (aniState->firstepLevel > 0) {
+ if (ath9k_hw_ani_control(ah,
+ ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel - 1) == true)
+ return;
+ }
+ } else {
+ if (aniState->firstepLevel > 0) {
+ if (ath9k_hw_ani_control(ah,
+ ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel - 1) == true)
+ return;
+ }
+ }
+ }
+
+ if (aniState->spurImmunityLevel > 0) {
+ if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
+ aniState->spurImmunityLevel - 1))
+ return;
+ }
+
+ if (aniState->noiseImmunityLevel > 0) {
+ ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
+ aniState->noiseImmunityLevel - 1);
+ return;
+ }
+}
+
+static int32_t ath9k_hw_ani_get_listen_time(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416AniState *aniState;
+ u32 txFrameCount, rxFrameCount, cycleCount;
+ int32_t listenTime;
+
+ txFrameCount = REG_READ(ah, AR_TFCNT);
+ rxFrameCount = REG_READ(ah, AR_RFCNT);
+ cycleCount = REG_READ(ah, AR_CCCNT);
+
+ aniState = ahp->ah_curani;
+ if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
+
+ listenTime = 0;
+ ahp->ah_stats.ast_ani_lzero++;
+ } else {
+ int32_t ccdelta = cycleCount - aniState->cycleCount;
+ int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
+ int32_t tfdelta = txFrameCount - aniState->txFrameCount;
+ listenTime = (ccdelta - rfdelta - tfdelta) / 44000;
+ }
+ aniState->cycleCount = cycleCount;
+ aniState->txFrameCount = txFrameCount;
+ aniState->rxFrameCount = rxFrameCount;
+
+ return listenTime;
+}
+
+void ath9k_ani_reset(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416AniState *aniState;
+ struct ath9k_channel *chan = ah->ah_curchan;
+ int index;
+
+ if (!DO_ANI(ah))
+ return;
+
+ index = ath9k_hw_get_ani_channel_idx(ah, chan);
+ aniState = &ahp->ah_ani[index];
+ ahp->ah_curani = aniState;
+
+ if (DO_ANI(ah) && ah->ah_opmode != NL80211_IFTYPE_STATION
+ && ah->ah_opmode != NL80211_IFTYPE_ADHOC) {
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "Reset ANI state opmode %u\n", ah->ah_opmode);
+ ahp->ah_stats.ast_ani_reset++;
+
+ ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
+ ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
+ ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
+ ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ !ATH9K_ANI_USE_OFDM_WEAK_SIG);
+ ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
+ ATH9K_ANI_CCK_WEAK_SIG_THR);
+
+ ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
+ ATH9K_RX_FILTER_PHYERR);
+
+ if (ah->ah_opmode == NL80211_IFTYPE_AP) {
+ ahp->ah_curani->ofdmTrigHigh =
+ ah->ah_config.ofdm_trig_high;
+ ahp->ah_curani->ofdmTrigLow =
+ ah->ah_config.ofdm_trig_low;
+ ahp->ah_curani->cckTrigHigh =
+ ah->ah_config.cck_trig_high;
+ ahp->ah_curani->cckTrigLow =
+ ah->ah_config.cck_trig_low;
+ }
+ ath9k_ani_restart(ah);
+ return;
+ }
+
+ if (aniState->noiseImmunityLevel != 0)
+ ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
+ aniState->noiseImmunityLevel);
+ if (aniState->spurImmunityLevel != 0)
+ ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
+ aniState->spurImmunityLevel);
+ if (aniState->ofdmWeakSigDetectOff)
+ ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
+ !aniState->ofdmWeakSigDetectOff);
+ if (aniState->cckWeakSigThreshold)
+ ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
+ aniState->cckWeakSigThreshold);
+ if (aniState->firstepLevel != 0)
+ ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
+ aniState->firstepLevel);
+ if (ahp->ah_hasHwPhyCounters) {
+ ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) &
+ ~ATH9K_RX_FILTER_PHYERR);
+ ath9k_ani_restart(ah);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+
+ } else {
+ ath9k_ani_restart(ah);
+ ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) |
+ ATH9K_RX_FILTER_PHYERR);
+ }
+}
+
+void ath9k_hw_ani_monitor(struct ath_hal *ah,
+ const struct ath9k_node_stats *stats,
+ struct ath9k_channel *chan)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416AniState *aniState;
+ int32_t listenTime;
+
+ aniState = ahp->ah_curani;
+ ahp->ah_stats.ast_nodestats = *stats;
+
+ listenTime = ath9k_hw_ani_get_listen_time(ah);
+ if (listenTime < 0) {
+ ahp->ah_stats.ast_ani_lneg++;
+ ath9k_ani_restart(ah);
+ return;
+ }
+
+ aniState->listenTime += listenTime;
+
+ if (ahp->ah_hasHwPhyCounters) {
+ u32 phyCnt1, phyCnt2;
+ u32 ofdmPhyErrCnt, cckPhyErrCnt;
+
+ ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
+
+ phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
+ phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
+
+ if (phyCnt1 < aniState->ofdmPhyErrBase ||
+ phyCnt2 < aniState->cckPhyErrBase) {
+ if (phyCnt1 < aniState->ofdmPhyErrBase) {
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "phyCnt1 0x%x, resetting "
+ "counter value to 0x%x\n",
+ phyCnt1,
+ aniState->ofdmPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_1,
+ aniState->ofdmPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_1,
+ AR_PHY_ERR_OFDM_TIMING);
+ }
+ if (phyCnt2 < aniState->cckPhyErrBase) {
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "phyCnt2 0x%x, resetting "
+ "counter value to 0x%x\n",
+ phyCnt2,
+ aniState->cckPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_2,
+ aniState->cckPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_2,
+ AR_PHY_ERR_CCK_TIMING);
+ }
+ return;
+ }
+
+ ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
+ ahp->ah_stats.ast_ani_ofdmerrs +=
+ ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
+ aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
+
+ cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
+ ahp->ah_stats.ast_ani_cckerrs +=
+ cckPhyErrCnt - aniState->cckPhyErrCount;
+ aniState->cckPhyErrCount = cckPhyErrCnt;
+ }
+
+ if (!DO_ANI(ah))
+ return;
+
+ if (aniState->listenTime > 5 * ahp->ah_aniPeriod) {
+ if (aniState->ofdmPhyErrCount <= aniState->listenTime *
+ aniState->ofdmTrigLow / 1000 &&
+ aniState->cckPhyErrCount <= aniState->listenTime *
+ aniState->cckTrigLow / 1000)
+ ath9k_hw_ani_lower_immunity(ah);
+ ath9k_ani_restart(ah);
+ } else if (aniState->listenTime > ahp->ah_aniPeriod) {
+ if (aniState->ofdmPhyErrCount > aniState->listenTime *
+ aniState->ofdmTrigHigh / 1000) {
+ ath9k_hw_ani_ofdm_err_trigger(ah);
+ ath9k_ani_restart(ah);
+ } else if (aniState->cckPhyErrCount >
+ aniState->listenTime * aniState->cckTrigHigh /
+ 1000) {
+ ath9k_hw_ani_cck_err_trigger(ah);
+ ath9k_ani_restart(ah);
+ }
+ }
+}
+
+bool ath9k_hw_phycounters(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ return ahp->ah_hasHwPhyCounters ? true : false;
+}
+
+void ath9k_enable_mib_counters(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable MIB counters\n");
+
+ ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
+
+ REG_WRITE(ah, AR_FILT_OFDM, 0);
+ REG_WRITE(ah, AR_FILT_CCK, 0);
+ REG_WRITE(ah, AR_MIBC,
+ ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS)
+ & 0x0f);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
+ REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
+}
+
+void ath9k_hw_disable_mib_counters(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disable MIB counters\n");
+
+ REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC | AR_MIBC_CMC);
+
+ ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
+
+ REG_WRITE(ah, AR_FILT_OFDM, 0);
+ REG_WRITE(ah, AR_FILT_CCK, 0);
+}
+
+u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah,
+ u32 *rxc_pcnt,
+ u32 *rxf_pcnt,
+ u32 *txf_pcnt)
+{
+ static u32 cycles, rx_clear, rx_frame, tx_frame;
+ u32 good = 1;
+
+ u32 rc = REG_READ(ah, AR_RCCNT);
+ u32 rf = REG_READ(ah, AR_RFCNT);
+ u32 tf = REG_READ(ah, AR_TFCNT);
+ u32 cc = REG_READ(ah, AR_CCCNT);
+
+ if (cycles == 0 || cycles > cc) {
+ DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
+ "cycle counter wrap. ExtBusy = 0\n");
+ good = 0;
+ } else {
+ u32 cc_d = cc - cycles;
+ u32 rc_d = rc - rx_clear;
+ u32 rf_d = rf - rx_frame;
+ u32 tf_d = tf - tx_frame;
+
+ if (cc_d != 0) {
+ *rxc_pcnt = rc_d * 100 / cc_d;
+ *rxf_pcnt = rf_d * 100 / cc_d;
+ *txf_pcnt = tf_d * 100 / cc_d;
+ } else {
+ good = 0;
+ }
+ }
+
+ cycles = cc;
+ rx_frame = rf;
+ rx_clear = rc;
+ tx_frame = tf;
+
+ return good;
+}
+
+/*
+ * Process a MIB interrupt. We may potentially be invoked because
+ * any of the MIB counters overflow/trigger so don't assume we're
+ * here because a PHY error counter triggered.
+ */
+void ath9k_hw_procmibevent(struct ath_hal *ah,
+ const struct ath9k_node_stats *stats)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ u32 phyCnt1, phyCnt2;
+
+ /* Reset these counters regardless */
+ REG_WRITE(ah, AR_FILT_OFDM, 0);
+ REG_WRITE(ah, AR_FILT_CCK, 0);
+ if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
+ REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
+
+ /* Clear the mib counters and save them in the stats */
+ ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
+ ahp->ah_stats.ast_nodestats = *stats;
+
+ if (!DO_ANI(ah))
+ return;
+
+ /* NB: these are not reset-on-read */
+ phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
+ phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
+ if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
+ ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
+ struct ar5416AniState *aniState = ahp->ah_curani;
+ u32 ofdmPhyErrCnt, cckPhyErrCnt;
+
+ /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
+ ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
+ ahp->ah_stats.ast_ani_ofdmerrs +=
+ ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
+ aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
+
+ cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
+ ahp->ah_stats.ast_ani_cckerrs +=
+ cckPhyErrCnt - aniState->cckPhyErrCount;
+ aniState->cckPhyErrCount = cckPhyErrCnt;
+
+ /*
+ * NB: figure out which counter triggered. If both
+ * trigger we'll only deal with one as the processing
+ * clobbers the error counter so the trigger threshold
+ * check will never be true.
+ */
+ if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
+ ath9k_hw_ani_ofdm_err_trigger(ah);
+ if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
+ ath9k_hw_ani_cck_err_trigger(ah);
+ /* NB: always restart to insure the h/w counters are reset */
+ ath9k_ani_restart(ah);
+ }
+}
+
+void ath9k_hw_ani_setup(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ int i;
+
+ const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
+ const int coarseHigh[] = { -14, -14, -14, -14, -12 };
+ const int coarseLow[] = { -64, -64, -64, -64, -70 };
+ const int firpwr[] = { -78, -78, -78, -78, -80 };
+
+ for (i = 0; i < 5; i++) {
+ ahp->ah_totalSizeDesired[i] = totalSizeDesired[i];
+ ahp->ah_coarseHigh[i] = coarseHigh[i];
+ ahp->ah_coarseLow[i] = coarseLow[i];
+ ahp->ah_firpwr[i] = firpwr[i];
+ }
+}
+
+void ath9k_hw_ani_attach(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ int i;
+
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Attach ANI\n");
+
+ ahp->ah_hasHwPhyCounters = 1;
+
+ memset(ahp->ah_ani, 0, sizeof(ahp->ah_ani));
+ for (i = 0; i < ARRAY_SIZE(ahp->ah_ani); i++) {
+ ahp->ah_ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH;
+ ahp->ah_ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW;
+ ahp->ah_ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH;
+ ahp->ah_ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW;
+ ahp->ah_ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
+ ahp->ah_ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
+ ahp->ah_ani[i].ofdmWeakSigDetectOff =
+ !ATH9K_ANI_USE_OFDM_WEAK_SIG;
+ ahp->ah_ani[i].cckWeakSigThreshold =
+ ATH9K_ANI_CCK_WEAK_SIG_THR;
+ ahp->ah_ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
+ ahp->ah_ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
+ if (ahp->ah_hasHwPhyCounters) {
+ ahp->ah_ani[i].ofdmPhyErrBase =
+ AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH;
+ ahp->ah_ani[i].cckPhyErrBase =
+ AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH;
+ }
+ }
+ if (ahp->ah_hasHwPhyCounters) {
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "Setting OfdmErrBase = 0x%08x\n",
+ ahp->ah_ani[0].ofdmPhyErrBase);
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
+ ahp->ah_ani[0].cckPhyErrBase);
+
+ REG_WRITE(ah, AR_PHY_ERR_1, ahp->ah_ani[0].ofdmPhyErrBase);
+ REG_WRITE(ah, AR_PHY_ERR_2, ahp->ah_ani[0].cckPhyErrBase);
+ ath9k_enable_mib_counters(ah);
+ }
+ ahp->ah_aniPeriod = ATH9K_ANI_PERIOD;
+ if (ah->ah_config.enable_ani)
+ ahp->ah_procPhyErr |= HAL_PROCESS_ANI;
+}
+
+void ath9k_hw_ani_detach(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Detach ANI\n");
+
+ if (ahp->ah_hasHwPhyCounters) {
+ ath9k_hw_disable_mib_counters(ah);
+ REG_WRITE(ah, AR_PHY_ERR_1, 0);
+ REG_WRITE(ah, AR_PHY_ERR_2, 0);
+ }
+}
diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h
index accace5f7efb..d27813502953 100644
--- a/drivers/net/wireless/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath9k/ath9k.h
@@ -26,6 +26,7 @@
#define AR9160_DEVID_PCI 0x0027
#define AR9280_DEVID_PCI 0x0029
#define AR9280_DEVID_PCIE 0x002a
+#define AR9285_DEVID_PCIE 0x002b
#define AR5416_AR9100_DEVID 0x000b
@@ -138,6 +139,19 @@ struct ath_desc {
#define ATH9K_TXDESC_NOACK 0x0002
#define ATH9K_TXDESC_RTSENA 0x0004
#define ATH9K_TXDESC_CTSENA 0x0008
+/* ATH9K_TXDESC_INTREQ forces a tx interrupt to be generated for
+ * the descriptor its marked on. We take a tx interrupt to reap
+ * descriptors when the h/w hits an EOL condition or
+ * when the descriptor is specifically marked to generate
+ * an interrupt with this flag. Descriptors should be
+ * marked periodically to insure timely replenishing of the
+ * supply needed for sending frames. Defering interrupts
+ * reduces system load and potentially allows more concurrent
+ * work to be done but if done to aggressively can cause
+ * senders to backup. When the hardware queue is left too
+ * large rate control information may also be too out of
+ * date. An Alternative for this is TX interrupt mitigation
+ * but this needs more testing. */
#define ATH9K_TXDESC_INTREQ 0x0010
#define ATH9K_TXDESC_VEOL 0x0020
#define ATH9K_TXDESC_EXT_ONLY 0x0040
@@ -388,22 +402,6 @@ enum ath9k_int {
ATH9K_INT_NOCARD = 0xffffffff
};
-struct ath9k_rate_table {
- int rateCount;
- u8 rateCodeToIndex[256];
- struct {
- u8 valid;
- u8 phy;
- u32 rateKbps;
- u8 rateCode;
- u8 shortPreamble;
- u8 dot11Rate;
- u8 controlRate;
- u16 lpAckDuration;
- u16 spAckDuration;
- } info[32];
-};
-
#define ATH9K_RATESERIES_RTS_CTS 0x0001
#define ATH9K_RATESERIES_2040 0x0002
#define ATH9K_RATESERIES_HALFGI 0x0004
@@ -479,12 +477,10 @@ struct ath9k_channel {
(((_c)->channelFlags & CHANNEL_A_HT20) == CHANNEL_A_HT20) || \
(((_c)->channelFlags & CHANNEL_A_HT40PLUS) == CHANNEL_A_HT40PLUS) || \
(((_c)->channelFlags & CHANNEL_A_HT40MINUS) == CHANNEL_A_HT40MINUS))
-#define IS_CHAN_B(_c) (((_c)->channelFlags & CHANNEL_B) == CHANNEL_B)
#define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \
(((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \
(((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \
(((_c)->channelFlags & CHANNEL_G_HT40MINUS) == CHANNEL_G_HT40MINUS))
-#define IS_CHAN_CCK(_c) (((_c)->channelFlags & CHANNEL_CCK) != 0)
#define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0)
#define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0)
#define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0)
@@ -493,6 +489,7 @@ struct ath9k_channel {
#define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0)
/* These macros check chanmode and not channelFlags */
+#define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B)
#define IS_CHAN_HT20(_c) (((_c)->chanmode == CHANNEL_A_HT20) || \
((_c)->chanmode == CHANNEL_G_HT20))
#define IS_CHAN_HT40(_c) (((_c)->chanmode == CHANNEL_A_HT40PLUS) || \
@@ -651,13 +648,6 @@ enum ath9k_ant_setting {
ATH9K_ANT_FIXED_B
};
-enum ath9k_opmode {
- ATH9K_M_STA = 1,
- ATH9K_M_IBSS = 0,
- ATH9K_M_HOSTAP = 6,
- ATH9K_M_MONITOR = 8
-};
-
#define ATH9K_SLOT_TIME_6 6
#define ATH9K_SLOT_TIME_9 9
#define ATH9K_SLOT_TIME_20 20
@@ -689,13 +679,19 @@ enum ath9k_ani_cmd {
ATH9K_ANI_ALL = 0xff
};
-enum phytype {
- PHY_DS,
- PHY_FH,
- PHY_OFDM,
- PHY_HT,
+enum {
+ WLAN_RC_PHY_OFDM,
+ WLAN_RC_PHY_CCK,
+ WLAN_RC_PHY_HT_20_SS,
+ WLAN_RC_PHY_HT_20_DS,
+ WLAN_RC_PHY_HT_40_SS,
+ WLAN_RC_PHY_HT_40_DS,
+ WLAN_RC_PHY_HT_20_SS_HGI,
+ WLAN_RC_PHY_HT_20_DS_HGI,
+ WLAN_RC_PHY_HT_40_SS_HGI,
+ WLAN_RC_PHY_HT_40_DS_HGI,
+ WLAN_RC_PHY_MAX
};
-#define PHY_CCK PHY_DS
enum ath9k_tp_scale {
ATH9K_TP_SCALE_MAX = 0,
@@ -778,7 +774,8 @@ struct ath_hal {
void __iomem *ah_sh;
struct ath_softc *ah_sc;
- enum ath9k_opmode ah_opmode;
+
+ enum nl80211_iftype ah_opmode;
struct ath9k_ops_config ah_config;
struct ath9k_hw_capabilities ah_caps;
@@ -815,195 +812,246 @@ struct chan_centers {
u16 ext_center;
};
-int ath_hal_getcapability(struct ath_hal *ah,
- enum ath9k_capability_type type,
- u32 capability,
- u32 *result);
-const struct ath9k_rate_table *ath9k_hw_getratetable(struct ath_hal *ah,
- u32 mode);
-void ath9k_hw_detach(struct ath_hal *ah);
-struct ath_hal *ath9k_hw_attach(u16 devid,
- struct ath_softc *sc,
- void __iomem *mem,
- int *error);
-bool ath9k_regd_init_channels(struct ath_hal *ah,
- u32 maxchans, u32 *nchans,
- u8 *regclassids,
- u32 maxregids, u32 *nregids,
- u16 cc,
- bool enableOutdoor,
- bool enableExtendedChannels);
+struct ath_rate_table;
+
+/* Helpers */
+
+enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah,
+ const struct ath9k_channel *chan);
+bool ath9k_hw_wait(struct ath_hal *ah, u32 reg, u32 mask, u32 val);
+u32 ath9k_hw_reverse_bits(u32 val, u32 n);
+bool ath9k_get_channel_edges(struct ath_hal *ah,
+ u16 flags, u16 *low,
+ u16 *high);
+u16 ath9k_hw_computetxtime(struct ath_hal *ah,
+ struct ath_rate_table *rates,
+ u32 frameLen, u16 rateix,
+ bool shortPreamble);
u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags);
-enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah,
- enum ath9k_int ints);
-bool ath9k_hw_reset(struct ath_hal *ah,
- struct ath9k_channel *chan,
+void ath9k_hw_get_channel_centers(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ struct chan_centers *centers);
+
+/* Attach, Detach */
+
+const char *ath9k_hw_probe(u16 vendorid, u16 devid);
+void ath9k_hw_detach(struct ath_hal *ah);
+struct ath_hal *ath9k_hw_attach(u16 devid, struct ath_softc *sc,
+ void __iomem *mem, int *error);
+void ath9k_hw_rfdetach(struct ath_hal *ah);
+
+
+/* HW Reset */
+
+bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
enum ath9k_ht_macmode macmode,
u8 txchainmask, u8 rxchainmask,
enum ath9k_ht_extprotspacing extprotspacing,
- bool bChannelChange,
- int *status);
-bool ath9k_hw_phy_disable(struct ath_hal *ah);
-void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
- bool *isCalDone);
-void ath9k_hw_ani_monitor(struct ath_hal *ah,
- const struct ath9k_node_stats *stats,
- struct ath9k_channel *chan);
-bool ath9k_hw_calibrate(struct ath_hal *ah,
- struct ath9k_channel *chan,
- u8 rxchainmask,
- bool longcal,
- bool *isCalDone);
-s16 ath9k_hw_getchan_noise(struct ath_hal *ah,
- struct ath9k_channel *chan);
-void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid,
- u16 assocId);
-void ath9k_hw_setrxfilter(struct ath_hal *ah, u32 bits);
-void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid,
- u16 assocId);
-bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q);
-void ath9k_hw_reset_tsf(struct ath_hal *ah);
-bool ath9k_hw_keyisvalid(struct ath_hal *ah, u16 entry);
-bool ath9k_hw_keysetmac(struct ath_hal *ah, u16 entry,
- const u8 *mac);
-bool ath9k_hw_set_keycache_entry(struct ath_hal *ah,
- u16 entry,
- const struct ath9k_keyval *k,
- const u8 *mac,
- int xorKey);
-bool ath9k_hw_set_tsfadjust(struct ath_hal *ah,
- u32 setting);
-void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore);
-bool ath9k_hw_intrpend(struct ath_hal *ah);
-bool ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked);
-bool ath9k_hw_updatetxtriglevel(struct ath_hal *ah,
- bool bIncTrigLevel);
-void ath9k_hw_procmibevent(struct ath_hal *ah,
- const struct ath9k_node_stats *stats);
-bool ath9k_hw_setrxabort(struct ath_hal *ah, bool set);
-void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode);
-bool ath9k_hw_phycounters(struct ath_hal *ah);
+ bool bChannelChange, int *status);
+
+/* Key Cache Management */
+
bool ath9k_hw_keyreset(struct ath_hal *ah, u16 entry);
-bool ath9k_hw_getcapability(struct ath_hal *ah,
- enum ath9k_capability_type type,
- u32 capability,
- u32 *result);
-bool ath9k_hw_setcapability(struct ath_hal *ah,
- enum ath9k_capability_type type,
- u32 capability,
- u32 setting,
- int *status);
-u32 ath9k_hw_getdefantenna(struct ath_hal *ah);
-void ath9k_hw_getmac(struct ath_hal *ah, u8 *mac);
-void ath9k_hw_getbssidmask(struct ath_hal *ah, u8 *mask);
-bool ath9k_hw_setbssidmask(struct ath_hal *ah,
- const u8 *mask);
+bool ath9k_hw_keysetmac(struct ath_hal *ah, u16 entry, const u8 *mac);
+bool ath9k_hw_set_keycache_entry(struct ath_hal *ah, u16 entry,
+ const struct ath9k_keyval *k,
+ const u8 *mac, int xorKey);
+bool ath9k_hw_keyisvalid(struct ath_hal *ah, u16 entry);
+
+/* Power Management */
+
bool ath9k_hw_setpower(struct ath_hal *ah,
enum ath9k_power_mode mode);
-enum ath9k_int ath9k_hw_intrget(struct ath_hal *ah);
-u64 ath9k_hw_gettsf64(struct ath_hal *ah);
+void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore);
+
+/* Beacon timers */
+
+void ath9k_hw_beaconinit(struct ath_hal *ah, u32 next_beacon, u32 beacon_period);
+void ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah,
+ const struct ath9k_beacon_state *bs);
+/* HW Capabilities */
+
+bool ath9k_hw_fill_cap_info(struct ath_hal *ah);
+bool ath9k_hw_getcapability(struct ath_hal *ah, enum ath9k_capability_type type,
+ u32 capability, u32 *result);
+bool ath9k_hw_setcapability(struct ath_hal *ah, enum ath9k_capability_type type,
+ u32 capability, u32 setting, int *status);
+
+/* GPIO / RFKILL / Antennae */
+
+void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio);
+u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio);
+void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
+ u32 ah_signal_type);
+void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val);
+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
+void ath9k_enable_rfkill(struct ath_hal *ah);
+#endif
+int ath9k_hw_select_antconfig(struct ath_hal *ah, u32 cfg);
u32 ath9k_hw_getdefantenna(struct ath_hal *ah);
-bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us);
+void ath9k_hw_setantenna(struct ath_hal *ah, u32 antenna);
bool ath9k_hw_setantennaswitch(struct ath_hal *ah,
enum ath9k_ant_setting settings,
struct ath9k_channel *chan,
u8 *tx_chainmask,
u8 *rx_chainmask,
u8 *antenna_cfgd);
-void ath9k_hw_setantenna(struct ath_hal *ah, u32 antenna);
-int ath9k_hw_select_antconfig(struct ath_hal *ah,
- u32 cfg);
-bool ath9k_hw_puttxbuf(struct ath_hal *ah, u32 q,
- u32 txdp);
+
+/* General Operation */
+
+u32 ath9k_hw_getrxfilter(struct ath_hal *ah);
+void ath9k_hw_setrxfilter(struct ath_hal *ah, u32 bits);
+bool ath9k_hw_phy_disable(struct ath_hal *ah);
+bool ath9k_hw_disable(struct ath_hal *ah);
+bool ath9k_hw_set_txpowerlimit(struct ath_hal *ah, u32 limit);
+void ath9k_hw_getmac(struct ath_hal *ah, u8 *mac);
+bool ath9k_hw_setmac(struct ath_hal *ah, const u8 *mac);
+void ath9k_hw_setopmode(struct ath_hal *ah);
+void ath9k_hw_setmcastfilter(struct ath_hal *ah, u32 filter0, u32 filter1);
+void ath9k_hw_getbssidmask(struct ath_hal *ah, u8 *mask);
+bool ath9k_hw_setbssidmask(struct ath_hal *ah, const u8 *mask);
+void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid, u16 assocId);
+u64 ath9k_hw_gettsf64(struct ath_hal *ah);
+void ath9k_hw_reset_tsf(struct ath_hal *ah);
+bool ath9k_hw_set_tsfadjust(struct ath_hal *ah, u32 setting);
+bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us);
+void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode);
+
+/* Regulatory */
+
+bool ath9k_regd_is_public_safety_sku(struct ath_hal *ah);
+struct ath9k_channel* ath9k_regd_check_channel(struct ath_hal *ah,
+ const struct ath9k_channel *c);
+u32 ath9k_regd_get_ctl(struct ath_hal *ah, struct ath9k_channel *chan);
+u32 ath9k_regd_get_antenna_allowed(struct ath_hal *ah,
+ struct ath9k_channel *chan);
+bool ath9k_regd_init_channels(struct ath_hal *ah,
+ u32 maxchans, u32 *nchans, u8 *regclassids,
+ u32 maxregids, u32 *nregids, u16 cc,
+ bool enableOutdoor, bool enableExtendedChannels);
+
+/* ANI */
+
+void ath9k_ani_reset(struct ath_hal *ah);
+void ath9k_hw_ani_monitor(struct ath_hal *ah,
+ const struct ath9k_node_stats *stats,
+ struct ath9k_channel *chan);
+bool ath9k_hw_phycounters(struct ath_hal *ah);
+void ath9k_enable_mib_counters(struct ath_hal *ah);
+void ath9k_hw_disable_mib_counters(struct ath_hal *ah);
+u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah,
+ u32 *rxc_pcnt,
+ u32 *rxf_pcnt,
+ u32 *txf_pcnt);
+void ath9k_hw_procmibevent(struct ath_hal *ah,
+ const struct ath9k_node_stats *stats);
+void ath9k_hw_ani_setup(struct ath_hal *ah);
+void ath9k_hw_ani_attach(struct ath_hal *ah);
+void ath9k_hw_ani_detach(struct ath_hal *ah);
+
+/* Calibration */
+
+void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
+ bool *isCalDone);
+void ath9k_hw_start_nfcal(struct ath_hal *ah);
+void ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan);
+int16_t ath9k_hw_getnf(struct ath_hal *ah,
+ struct ath9k_channel *chan);
+void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah);
+s16 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan);
+bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
+ u8 rxchainmask, bool longcal,
+ bool *isCalDone);
+bool ath9k_hw_init_cal(struct ath_hal *ah,
+ struct ath9k_channel *chan);
+
+
+/* EEPROM */
+
+int ath9k_hw_set_txpower(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ u16 cfgCtl,
+ u8 twiceAntennaReduction,
+ u8 twiceMaxRegulatoryPower,
+ u8 powerLimit);
+void ath9k_hw_set_addac(struct ath_hal *ah, struct ath9k_channel *chan);
+bool ath9k_hw_set_power_per_rate_table(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ int16_t *ratesArray,
+ u16 cfgCtl,
+ u8 AntennaReduction,
+ u8 twiceMaxRegulatoryPower,
+ u8 powerLimit);
+bool ath9k_hw_set_power_cal_table(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ int16_t *pTxPowerIndexOffset);
+bool ath9k_hw_eeprom_set_board_values(struct ath_hal *ah,
+ struct ath9k_channel *chan);
+int ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ u8 index, u16 *config);
+u8 ath9k_hw_get_num_ant_config(struct ath_hal *ah,
+ enum ieee80211_band freq_band);
+u16 ath9k_hw_eeprom_get_spur_chan(struct ath_hal *ah, u16 i, bool is2GHz);
+int ath9k_hw_eeprom_attach(struct ath_hal *ah);
+
+/* Interrupt Handling */
+
+bool ath9k_hw_intrpend(struct ath_hal *ah);
+bool ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked);
+enum ath9k_int ath9k_hw_intrget(struct ath_hal *ah);
+enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah, enum ath9k_int ints);
+
+/* MAC (PCU/QCU) */
+
+u32 ath9k_hw_gettxbuf(struct ath_hal *ah, u32 q);
+bool ath9k_hw_puttxbuf(struct ath_hal *ah, u32 q, u32 txdp);
bool ath9k_hw_txstart(struct ath_hal *ah, u32 q);
-u16 ath9k_hw_computetxtime(struct ath_hal *ah,
- const struct ath9k_rate_table *rates,
- u32 frameLen, u16 rateix,
- bool shortPreamble);
+u32 ath9k_hw_numtxpending(struct ath_hal *ah, u32 q);
+bool ath9k_hw_updatetxtriglevel(struct ath_hal *ah, bool bIncTrigLevel);
+bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q);
+bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,
+ u32 segLen, bool firstSeg,
+ bool lastSeg, const struct ath_desc *ds0);
+void ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds);
+int ath9k_hw_txprocdesc(struct ath_hal *ah, struct ath_desc *ds);
+void ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds,
+ u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
+ u32 keyIx, enum ath9k_key_type keyType, u32 flags);
void ath9k_hw_set11n_ratescenario(struct ath_hal *ah, struct ath_desc *ds,
struct ath_desc *lastds,
u32 durUpdateEn, u32 rtsctsRate,
u32 rtsctsDuration,
struct ath9k_11n_rate_series series[],
u32 nseries, u32 flags);
-void ath9k_hw_set11n_burstduration(struct ath_hal *ah,
- struct ath_desc *ds,
+void ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds,
+ u32 aggrLen);
+void ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds,
+ u32 numDelims);
+void ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds);
+void ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds);
+void ath9k_hw_set11n_burstduration(struct ath_hal *ah, struct ath_desc *ds,
u32 burstDuration);
-void ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds);
-u32 ath9k_hw_reverse_bits(u32 val, u32 n);
-bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q);
-u32 ath9k_regd_get_ctl(struct ath_hal *ah, struct ath9k_channel *chan);
-u32 ath9k_regd_get_antenna_allowed(struct ath_hal *ah,
- struct ath9k_channel *chan);
-u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags);
-bool ath9k_hw_get_txq_props(struct ath_hal *ah, int q,
- struct ath9k_tx_queue_info *qinfo);
+void ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah, struct ath_desc *ds,
+ u32 vmf);
+void ath9k_hw_gettxintrtxqs(struct ath_hal *ah, u32 *txqs);
bool ath9k_hw_set_txq_props(struct ath_hal *ah, int q,
const struct ath9k_tx_queue_info *qinfo);
-struct ath9k_channel *ath9k_regd_check_channel(struct ath_hal *ah,
- const struct ath9k_channel *c);
-void ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds,
- u32 pktLen, enum ath9k_pkt_type type,
- u32 txPower, u32 keyIx,
- enum ath9k_key_type keyType, u32 flags);
-bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,
- u32 segLen, bool firstSeg,
- bool lastSeg,
- const struct ath_desc *ds0);
-u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah,
- u32 *rxc_pcnt,
- u32 *rxf_pcnt,
- u32 *txf_pcnt);
-void ath9k_hw_dmaRegDump(struct ath_hal *ah);
-void ath9k_hw_beaconinit(struct ath_hal *ah,
- u32 next_beacon, u32 beacon_period);
-void ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah,
- const struct ath9k_beacon_state *bs);
+bool ath9k_hw_get_txq_props(struct ath_hal *ah, int q,
+ struct ath9k_tx_queue_info *qinfo);
+int ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type,
+ const struct ath9k_tx_queue_info *qinfo);
+bool ath9k_hw_releasetxqueue(struct ath_hal *ah, u32 q);
+bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q);
+int ath9k_hw_rxprocdesc(struct ath_hal *ah, struct ath_desc *ds,
+ u32 pa, struct ath_desc *nds, u64 tsf);
bool ath9k_hw_setuprxdesc(struct ath_hal *ah, struct ath_desc *ds,
u32 size, u32 flags);
+bool ath9k_hw_setrxabort(struct ath_hal *ah, bool set);
void ath9k_hw_putrxbuf(struct ath_hal *ah, u32 rxdp);
void ath9k_hw_rxena(struct ath_hal *ah);
-void ath9k_hw_setopmode(struct ath_hal *ah);
-bool ath9k_hw_setmac(struct ath_hal *ah, const u8 *mac);
-void ath9k_hw_setmcastfilter(struct ath_hal *ah, u32 filter0,
- u32 filter1);
-u32 ath9k_hw_getrxfilter(struct ath_hal *ah);
void ath9k_hw_startpcureceive(struct ath_hal *ah);
void ath9k_hw_stoppcurecv(struct ath_hal *ah);
bool ath9k_hw_stopdmarecv(struct ath_hal *ah);
-int ath9k_hw_rxprocdesc(struct ath_hal *ah,
- struct ath_desc *ds, u32 pa,
- struct ath_desc *nds, u64 tsf);
-u32 ath9k_hw_gettxbuf(struct ath_hal *ah, u32 q);
-int ath9k_hw_txprocdesc(struct ath_hal *ah,
- struct ath_desc *ds);
-void ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds,
- u32 numDelims);
-void ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds,
- u32 aggrLen);
-void ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds);
-bool ath9k_hw_releasetxqueue(struct ath_hal *ah, u32 q);
-void ath9k_hw_gettxintrtxqs(struct ath_hal *ah, u32 *txqs);
-void ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds);
-void ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah,
- struct ath_desc *ds, u32 vmf);
-bool ath9k_hw_set_txpowerlimit(struct ath_hal *ah, u32 limit);
-bool ath9k_regd_is_public_safety_sku(struct ath_hal *ah);
-int ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type,
- const struct ath9k_tx_queue_info *qinfo);
-u32 ath9k_hw_numtxpending(struct ath_hal *ah, u32 q);
-const char *ath9k_hw_probe(u16 vendorid, u16 devid);
-bool ath9k_hw_disable(struct ath_hal *ah);
-void ath9k_hw_rfdetach(struct ath_hal *ah);
-void ath9k_hw_get_channel_centers(struct ath_hal *ah,
- struct ath9k_channel *chan,
- struct chan_centers *centers);
-bool ath9k_get_channel_edges(struct ath_hal *ah,
- u16 flags, u16 *low,
- u16 *high);
-void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
- u32 ah_signal_type);
-void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 value);
-u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio);
-void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio);
+
#endif
diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c
index 4dd1c1bda0fb..3ab0b43aaf93 100644
--- a/drivers/net/wireless/ath9k/beacon.c
+++ b/drivers/net/wireless/ath9k/beacon.c
@@ -14,13 +14,9 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
- /* Implementation of beacon processing. */
-
#include "core.h"
/*
- * Configure parameters for the beacon queue
- *
* This function will modify certain transmit queue properties depending on
* the operating mode of the station (AP or AdHoc). Parameters are AIFS
* settings and channel width min/max
@@ -30,33 +26,38 @@ static int ath_beaconq_config(struct ath_softc *sc)
struct ath_hal *ah = sc->sc_ah;
struct ath9k_tx_queue_info qi;
- ath9k_hw_get_txq_props(ah, sc->sc_bhalq, &qi);
- if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) {
+ ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
+ if (sc->sc_ah->ah_opmode == NL80211_IFTYPE_AP) {
/* Always burst out beacon and CAB traffic. */
qi.tqi_aifs = 1;
qi.tqi_cwmin = 0;
qi.tqi_cwmax = 0;
} else {
/* Adhoc mode; important thing is to use 2x cwmin. */
- qi.tqi_aifs = sc->sc_beacon_qi.tqi_aifs;
- qi.tqi_cwmin = 2*sc->sc_beacon_qi.tqi_cwmin;
- qi.tqi_cwmax = sc->sc_beacon_qi.tqi_cwmax;
+ qi.tqi_aifs = sc->beacon.beacon_qi.tqi_aifs;
+ qi.tqi_cwmin = 2*sc->beacon.beacon_qi.tqi_cwmin;
+ qi.tqi_cwmax = sc->beacon.beacon_qi.tqi_cwmax;
}
- if (!ath9k_hw_set_txq_props(ah, sc->sc_bhalq, &qi)) {
+ if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) {
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to update h/w beacon queue parameters\n",
- __func__);
+ "unable to update h/w beacon queue parameters\n");
return 0;
} else {
- ath9k_hw_resettxqueue(ah, sc->sc_bhalq); /* push to h/w */
+ ath9k_hw_resettxqueue(ah, sc->beacon.beaconq); /* push to h/w */
return 1;
}
}
+static void ath_bstuck_process(struct ath_softc *sc)
+{
+ DPRINTF(sc, ATH_DBG_BEACON,
+ "stuck beacon; resetting (bmiss count %u)\n",
+ sc->beacon.bmisscnt);
+ ath_reset(sc, false);
+}
+
/*
- * Setup the beacon frame for transmit.
- *
* Associates the beacon frame buffer with a transmit descriptor. Will set
* up all required antenna switch parameters, rate codes, and channel flags.
* Beacons are always sent out at the lowest rate, and are not retried.
@@ -68,21 +69,20 @@ static void ath_beacon_setup(struct ath_softc *sc,
struct ath_hal *ah = sc->sc_ah;
struct ath_desc *ds;
struct ath9k_11n_rate_series series[4];
- const struct ath9k_rate_table *rt;
+ struct ath_rate_table *rt;
int flags, antenna;
u8 rix, rate;
int ctsrate = 0;
int ctsduration = 0;
- DPRINTF(sc, ATH_DBG_BEACON, "%s: m %p len %u\n",
- __func__, skb, skb->len);
+ DPRINTF(sc, ATH_DBG_BEACON, "m %p len %u\n", skb, skb->len);
/* setup descriptors */
ds = bf->bf_desc;
flags = ATH9K_TXDESC_NOACK;
- if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS &&
+ if (sc->sc_ah->ah_opmode == NL80211_IFTYPE_ADHOC &&
(ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
ds->ds_link = bf->bf_daddr; /* self-linked */
flags |= ATH9K_TXDESC_VEOL;
@@ -96,7 +96,7 @@ static void ath_beacon_setup(struct ath_softc *sc,
* SWBA's
* XXX assumes two antenna
*/
- antenna = ((sc->ast_be_xmit / sc->sc_nbcnvaps) & 1 ? 2 : 1);
+ antenna = ((sc->beacon.ast_be_xmit / sc->sc_nbcnvaps) & 1 ? 2 : 1);
}
ds->ds_data = bf->bf_buf_addr;
@@ -106,15 +106,15 @@ static void ath_beacon_setup(struct ath_softc *sc,
* XXX everything at min xmit rate
*/
rix = 0;
- rt = sc->sc_currates;
- rate = rt->info[rix].rateCode;
+ rt = sc->cur_rate_table;
+ rate = rt->info[rix].ratecode;
if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
- rate |= rt->info[rix].shortPreamble;
+ rate |= rt->info[rix].short_preamble;
ath9k_hw_set11n_txdesc(ah, ds,
skb->len + FCS_LEN, /* frame length */
ATH9K_PKT_TYPE_BEACON, /* Atheros packet type */
- avp->av_btxctl.txpower, /* txpower XXX */
+ MAX_RATE_POWER, /* FIXME */
ATH9K_TXKEYIX_INVALID, /* no encryption */
ATH9K_KEY_TYPE_CLEAR, /* no encryption */
flags /* no ack,
@@ -138,31 +138,26 @@ static void ath_beacon_setup(struct ath_softc *sc,
ctsrate, ctsduration, series, 4, 0);
}
-/*
- * Generate beacon frame and queue cab data for a vap.
- *
- * Updates the contents of the beacon frame. It is assumed that the buffer for
- * the beacon frame has been allocated in the ATH object, and simply needs to
- * be filled for this cycle. Also, any CAB (crap after beacon?) traffic will
- * be added to the beacon frame at this point.
-*/
+/* Generate beacon frame and queue cab data for a vap */
static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
{
struct ath_buf *bf;
struct ath_vap *avp;
struct sk_buff *skb;
struct ath_txq *cabq;
+ struct ieee80211_vif *vif;
struct ieee80211_tx_info *info;
int cabq_depth;
- avp = sc->sc_vaps[if_id];
- ASSERT(avp);
+ vif = sc->sc_vaps[if_id];
+ ASSERT(vif);
- cabq = sc->sc_cabq;
+ avp = (void *)vif->drv_priv;
+ cabq = sc->beacon.cabq;
if (avp->av_bcbuf == NULL) {
- DPRINTF(sc, ATH_DBG_BEACON, "%s: avp=%p av_bcbuf=%p\n",
- __func__, avp, avp->av_bcbuf);
+ DPRINTF(sc, ATH_DBG_BEACON, "avp=%p av_bcbuf=%p\n",
+ avp, avp->av_bcbuf);
return NULL;
}
@@ -172,9 +167,10 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
pci_unmap_single(sc->pdev, bf->bf_dmacontext,
skb->len,
PCI_DMA_TODEVICE);
+ dev_kfree_skb_any(skb);
}
- skb = ieee80211_beacon_get(sc->hw, avp->av_if_data);
+ skb = ieee80211_beacon_get(sc->hw, vif);
bf->bf_mpdu = skb;
if (skb == NULL)
return NULL;
@@ -186,17 +182,24 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
* TX frames)
*/
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- sc->seq_no += 0x10;
+ sc->tx.seq_no += 0x10;
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
- hdr->seq_ctrl |= cpu_to_le16(sc->seq_no);
+ hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
}
bf->bf_buf_addr = bf->bf_dmacontext =
pci_map_single(sc->pdev, skb->data,
skb->len,
PCI_DMA_TODEVICE);
+ if (unlikely(pci_dma_mapping_error(sc->pdev, bf->bf_buf_addr))) {
+ dev_kfree_skb_any(skb);
+ bf->bf_mpdu = NULL;
+ DPRINTF(sc, ATH_DBG_CONFIG,
+ "pci_dma_mapping_error() on beaconing\n");
+ return NULL;
+ }
- skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data);
+ skb = ieee80211_get_buffered_bc(sc->hw, vif);
/*
* if the CABQ traffic from previous DTIM is pending and the current
@@ -219,7 +222,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
if (sc->sc_nvaps > 1) {
ath_tx_draintxq(sc, cabq, false);
DPRINTF(sc, ATH_DBG_BEACON,
- "%s: flush previous cabq traffic\n", __func__);
+ "flush previous cabq traffic\n");
}
}
@@ -232,7 +235,7 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
*/
while (skb) {
ath_tx_cabq(sc, skb);
- skb = ieee80211_get_buffered_bc(sc->hw, avp->av_if_data);
+ skb = ieee80211_get_buffered_bc(sc->hw, vif);
}
return bf;
@@ -244,17 +247,20 @@ static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
*/
static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id)
{
+ struct ieee80211_vif *vif;
struct ath_hal *ah = sc->sc_ah;
struct ath_buf *bf;
struct ath_vap *avp;
struct sk_buff *skb;
- avp = sc->sc_vaps[if_id];
- ASSERT(avp);
+ vif = sc->sc_vaps[if_id];
+ ASSERT(vif);
+
+ avp = (void *)vif->drv_priv;
if (avp->av_bcbuf == NULL) {
- DPRINTF(sc, ATH_DBG_BEACON, "%s: avp=%p av_bcbuf=%p\n",
- __func__, avp, avp != NULL ? avp->av_bcbuf : NULL);
+ DPRINTF(sc, ATH_DBG_BEACON, "avp=%p av_bcbuf=%p\n",
+ avp, avp != NULL ? avp->av_bcbuf : NULL);
return;
}
bf = avp->av_bcbuf;
@@ -264,20 +270,12 @@ static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id)
ath_beacon_setup(sc, avp, bf);
/* NB: caller is known to have already stopped tx dma */
- ath9k_hw_puttxbuf(ah, sc->sc_bhalq, bf->bf_daddr);
- ath9k_hw_txstart(ah, sc->sc_bhalq);
- DPRINTF(sc, ATH_DBG_BEACON, "%s: TXDP%u = %llx (%p)\n", __func__,
- sc->sc_bhalq, ito64(bf->bf_daddr), bf->bf_desc);
+ ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr);
+ ath9k_hw_txstart(ah, sc->beacon.beaconq);
+ DPRINTF(sc, ATH_DBG_BEACON, "TXDP%u = %llx (%p)\n",
+ sc->beacon.beaconq, ito64(bf->bf_daddr), bf->bf_desc);
}
-/*
- * Setup a h/w transmit queue for beacons.
- *
- * This function allocates an information structure (struct ath9k_txq_info)
- * on the stack, sets some specific parameters (zero out channel width
- * min/max, and enable aifs). The info structure does not need to be
- * persistant.
-*/
int ath_beaconq_setup(struct ath_hal *ah)
{
struct ath9k_tx_queue_info qi;
@@ -290,35 +288,29 @@ int ath_beaconq_setup(struct ath_hal *ah)
return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
}
-
-/*
- * Allocate and setup an initial beacon frame.
- *
- * Allocate a beacon state variable for a specific VAP instance created on
- * the ATH interface. This routine also calculates the beacon "slot" for
- * staggared beacons in the mBSSID case.
-*/
int ath_beacon_alloc(struct ath_softc *sc, int if_id)
{
+ struct ieee80211_vif *vif;
struct ath_vap *avp;
struct ieee80211_hdr *hdr;
struct ath_buf *bf;
struct sk_buff *skb;
__le64 tstamp;
- avp = sc->sc_vaps[if_id];
- ASSERT(avp);
+ vif = sc->sc_vaps[if_id];
+ ASSERT(vif);
+
+ avp = (void *)vif->drv_priv;
/* Allocate a beacon descriptor if we haven't done so. */
if (!avp->av_bcbuf) {
/* Allocate beacon state for hostap/ibss. We know
* a buffer is available. */
-
- avp->av_bcbuf = list_first_entry(&sc->sc_bbuf,
+ avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf,
struct ath_buf, list);
list_del(&avp->av_bcbuf->list);
- if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP ||
+ if (sc->sc_ah->ah_opmode == NL80211_IFTYPE_AP ||
!(sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
int slot;
/*
@@ -327,13 +319,13 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
*/
avp->av_bslot = 0;
for (slot = 0; slot < ATH_BCBUF; slot++)
- if (sc->sc_bslot[slot] == ATH_IF_ID_ANY) {
+ if (sc->beacon.bslot[slot] == ATH_IF_ID_ANY) {
/*
* XXX hack, space out slots to better
* deal with misses
*/
if (slot+1 < ATH_BCBUF &&
- sc->sc_bslot[slot+1] ==
+ sc->beacon.bslot[slot+1] ==
ATH_IF_ID_ANY) {
avp->av_bslot = slot+1;
break;
@@ -341,8 +333,8 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
avp->av_bslot = slot;
/* NB: keep looking for a double slot */
}
- BUG_ON(sc->sc_bslot[avp->av_bslot] != ATH_IF_ID_ANY);
- sc->sc_bslot[avp->av_bslot] = if_id;
+ BUG_ON(sc->beacon.bslot[avp->av_bslot] != ATH_IF_ID_ANY);
+ sc->beacon.bslot[avp->av_bslot] = if_id;
sc->sc_nbcnvaps++;
}
}
@@ -363,15 +355,14 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
* FIXME: Fill avp->av_btxctl.txpower and
* avp->av_btxctl.shortPreamble
*/
- skb = ieee80211_beacon_get(sc->hw, avp->av_if_data);
+ skb = ieee80211_beacon_get(sc->hw, vif);
if (skb == NULL) {
- DPRINTF(sc, ATH_DBG_BEACON, "%s: cannot get skb\n",
- __func__);
+ DPRINTF(sc, ATH_DBG_BEACON, "cannot get skb\n");
return -ENOMEM;
}
tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
- sc->bc_tstamp = le64_to_cpu(tstamp);
+ sc->beacon.bc_tstamp = le64_to_cpu(tstamp);
/*
* Calculate a TSF adjustment factor required for
@@ -402,36 +393,36 @@ int ath_beacon_alloc(struct ath_softc *sc, int if_id)
val = cpu_to_le64(tsfadjust << 10); /* TU->TSF */
DPRINTF(sc, ATH_DBG_BEACON,
- "%s: %s beacons, bslot %d intval %u tsfadjust %llu\n",
- __func__, "stagger",
+ "stagger beacons, bslot %d intval %u tsfadjust %llu\n",
avp->av_bslot, intval, (unsigned long long)tsfadjust);
hdr = (struct ieee80211_hdr *)skb->data;
memcpy(&hdr[1], &val, sizeof(val));
}
+ bf->bf_mpdu = skb;
bf->bf_buf_addr = bf->bf_dmacontext =
pci_map_single(sc->pdev, skb->data,
skb->len,
PCI_DMA_TODEVICE);
- bf->bf_mpdu = skb;
+ if (unlikely(pci_dma_mapping_error(sc->pdev, bf->bf_buf_addr))) {
+ dev_kfree_skb_any(skb);
+ bf->bf_mpdu = NULL;
+ DPRINTF(sc, ATH_DBG_CONFIG,
+ "pci_dma_mapping_error() on beacon alloc\n");
+ return -ENOMEM;
+ }
return 0;
}
-/*
- * Reclaim beacon resources and return buffer to the pool.
- *
- * Checks the VAP to put the beacon frame buffer back to the ATH object
- * queue, and de-allocates any skbs that were sent as CAB traffic.
-*/
void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
{
if (avp->av_bcbuf != NULL) {
struct ath_buf *bf;
if (avp->av_bslot != -1) {
- sc->sc_bslot[avp->av_bslot] = ATH_IF_ID_ANY;
+ sc->beacon.bslot[avp->av_bslot] = ATH_IF_ID_ANY;
sc->sc_nbcnvaps--;
}
@@ -444,19 +435,12 @@ void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
dev_kfree_skb_any(skb);
bf->bf_mpdu = NULL;
}
- list_add_tail(&bf->list, &sc->sc_bbuf);
+ list_add_tail(&bf->list, &sc->beacon.bbuf);
avp->av_bcbuf = NULL;
}
}
-/*
- * Tasklet for Sending Beacons
- *
- * Transmit one or more beacon frames at SWBA. Dynamic updates to the frame
- * contents are done as needed and the slot time is also adjusted based on
- * current state.
-*/
void ath9k_beacon_tasklet(unsigned long data)
{
struct ath_softc *sc = (struct ath_softc *)data;
@@ -473,9 +457,7 @@ void ath9k_beacon_tasklet(unsigned long data)
if (sc->sc_flags & SC_OP_NO_RESET) {
show_cycles = ath9k_hw_GetMibCycleCountsPct(ah,
- &rx_clear,
- &rx_frame,
- &tx_frame);
+ &rx_clear, &rx_frame, &tx_frame);
}
/*
@@ -487,67 +469,65 @@ void ath9k_beacon_tasklet(unsigned long data)
*
* FIXME: Clean up this mess !!
*/
- if (ath9k_hw_numtxpending(ah, sc->sc_bhalq) != 0) {
- sc->sc_bmisscount++;
+ if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) {
+ sc->beacon.bmisscnt++;
/* XXX: doth needs the chanchange IE countdown decremented.
* We should consider adding a mac80211 call to indicate
* a beacon miss so appropriate action could be taken
* (in that layer).
*/
- if (sc->sc_bmisscount < BSTUCK_THRESH) {
+ if (sc->beacon.bmisscnt < BSTUCK_THRESH) {
if (sc->sc_flags & SC_OP_NO_RESET) {
DPRINTF(sc, ATH_DBG_BEACON,
- "%s: missed %u consecutive beacons\n",
- __func__, sc->sc_bmisscount);
+ "missed %u consecutive beacons\n",
+ sc->beacon.bmisscnt);
if (show_cycles) {
/*
* Display cycle counter stats from HW
* to aide in debug of stickiness.
*/
DPRINTF(sc, ATH_DBG_BEACON,
- "%s: busy times: rx_clear=%d, "
+ "busy times: rx_clear=%d, "
"rx_frame=%d, tx_frame=%d\n",
- __func__, rx_clear, rx_frame,
+ rx_clear, rx_frame,
tx_frame);
} else {
DPRINTF(sc, ATH_DBG_BEACON,
- "%s: unable to obtain "
- "busy times\n", __func__);
+ "unable to obtain "
+ "busy times\n");
}
} else {
DPRINTF(sc, ATH_DBG_BEACON,
- "%s: missed %u consecutive beacons\n",
- __func__, sc->sc_bmisscount);
+ "missed %u consecutive beacons\n",
+ sc->beacon.bmisscnt);
}
- } else if (sc->sc_bmisscount >= BSTUCK_THRESH) {
+ } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
if (sc->sc_flags & SC_OP_NO_RESET) {
- if (sc->sc_bmisscount == BSTUCK_THRESH) {
+ if (sc->beacon.bmisscnt == BSTUCK_THRESH) {
DPRINTF(sc, ATH_DBG_BEACON,
- "%s: beacon is officially "
- "stuck\n", __func__);
- ath9k_hw_dmaRegDump(ah);
+ "beacon is officially "
+ "stuck\n");
}
} else {
DPRINTF(sc, ATH_DBG_BEACON,
- "%s: beacon is officially stuck\n",
- __func__);
+ "beacon is officially stuck\n");
ath_bstuck_process(sc);
}
}
return;
}
- if (sc->sc_bmisscount != 0) {
+ if (sc->beacon.bmisscnt != 0) {
if (sc->sc_flags & SC_OP_NO_RESET) {
DPRINTF(sc, ATH_DBG_BEACON,
- "%s: resume beacon xmit after %u misses\n",
- __func__, sc->sc_bmisscount);
+ "resume beacon xmit after %u misses\n",
+ sc->beacon.bmisscnt);
} else {
DPRINTF(sc, ATH_DBG_BEACON,
- "%s: resume beacon xmit after %u misses\n",
- __func__, sc->sc_bmisscount);
+ "resume beacon xmit after %u misses\n",
+ sc->beacon.bmisscnt);
}
- sc->sc_bmisscount = 0;
+ sc->beacon.bmisscnt = 0;
}
/*
@@ -562,11 +542,11 @@ void ath9k_beacon_tasklet(unsigned long data)
tsf = ath9k_hw_gettsf64(ah);
tsftu = TSF_TO_TU(tsf>>32, tsf);
slot = ((tsftu % intval) * ATH_BCBUF) / intval;
- if_id = sc->sc_bslot[(slot + 1) % ATH_BCBUF];
+ if_id = sc->beacon.bslot[(slot + 1) % ATH_BCBUF];
DPRINTF(sc, ATH_DBG_BEACON,
- "%s: slot %d [tsf %llu tsftu %u intval %u] if_id %d\n",
- __func__, slot, (unsigned long long)tsf, tsftu,
+ "slot %d [tsf %llu tsftu %u intval %u] if_id %d\n",
+ slot, (unsigned long long)tsf, tsftu,
intval, if_id);
bfaddr = 0;
@@ -594,48 +574,34 @@ void ath9k_beacon_tasklet(unsigned long data)
* set to ATH_BCBUF so this check is a noop.
*/
/* XXX locking */
- if (sc->sc_updateslot == UPDATE) {
- sc->sc_updateslot = COMMIT; /* commit next beacon */
- sc->sc_slotupdate = slot;
- } else if (sc->sc_updateslot == COMMIT && sc->sc_slotupdate == slot)
- ath_setslottime(sc); /* commit change to hardware */
-
+ if (sc->beacon.updateslot == UPDATE) {
+ sc->beacon.updateslot = COMMIT; /* commit next beacon */
+ sc->beacon.slotupdate = slot;
+ } else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) {
+ ath9k_hw_setslottime(sc->sc_ah, sc->beacon.slottime);
+ sc->beacon.updateslot = OK;
+ }
if (bfaddr != 0) {
/*
* Stop any current dma and put the new frame(s) on the queue.
* This should never fail since we check above that no frames
* are still pending on the queue.
*/
- if (!ath9k_hw_stoptxdma(ah, sc->sc_bhalq)) {
+ if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) {
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: beacon queue %u did not stop?\n",
- __func__, sc->sc_bhalq);
+ "beacon queue %u did not stop?\n", sc->beacon.beaconq);
/* NB: the HAL still stops DMA, so proceed */
}
/* NB: cabq traffic should already be queued and primed */
- ath9k_hw_puttxbuf(ah, sc->sc_bhalq, bfaddr);
- ath9k_hw_txstart(ah, sc->sc_bhalq);
+ ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr);
+ ath9k_hw_txstart(ah, sc->beacon.beaconq);
- sc->ast_be_xmit += bc; /* XXX per-vap? */
+ sc->beacon.ast_be_xmit += bc; /* XXX per-vap? */
}
}
/*
- * Tasklet for Beacon Stuck processing
- *
- * Processing for Beacon Stuck.
- * Basically resets the chip.
-*/
-void ath_bstuck_process(struct ath_softc *sc)
-{
- DPRINTF(sc, ATH_DBG_BEACON,
- "%s: stuck beacon; resetting (bmiss count %u)\n",
- __func__, sc->sc_bmisscount);
- ath_reset(sc, false);
-}
-
-/*
* Configure the beacon and sleep timers.
*
* When operating as an AP this resets the TSF and sets
@@ -652,15 +618,21 @@ void ath_bstuck_process(struct ath_softc *sc)
*/
void ath_beacon_config(struct ath_softc *sc, int if_id)
{
+ struct ieee80211_vif *vif;
struct ath_hal *ah = sc->sc_ah;
struct ath_beacon_config conf;
- enum ath9k_opmode av_opmode;
+ struct ath_vap *avp;
+ enum nl80211_iftype opmode;
u32 nexttbtt, intval;
- if (if_id != ATH_IF_ID_ANY)
- av_opmode = sc->sc_vaps[if_id]->av_opmode;
- else
- av_opmode = sc->sc_ah->ah_opmode;
+ if (if_id != ATH_IF_ID_ANY) {
+ vif = sc->sc_vaps[if_id];
+ ASSERT(vif);
+ avp = (void *)vif->drv_priv;
+ opmode = avp->av_opmode;
+ } else {
+ opmode = sc->sc_ah->ah_opmode;
+ }
memset(&conf, 0, sizeof(struct ath_beacon_config));
@@ -672,10 +644,10 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval;
/* extract tstamp from last beacon and convert to TU */
- nexttbtt = TSF_TO_TU(sc->bc_tstamp >> 32, sc->bc_tstamp);
+ nexttbtt = TSF_TO_TU(sc->beacon.bc_tstamp >> 32, sc->beacon.bc_tstamp);
/* XXX conditionalize multi-bss support? */
- if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) {
+ if (sc->sc_ah->ah_opmode == NL80211_IFTYPE_AP) {
/*
* For multi-bss ap support beacons are either staggered
* evenly over N slots or burst together. For the former
@@ -694,11 +666,11 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
else if (intval) /* NB: can be 0 for monitor mode */
nexttbtt = roundup(nexttbtt, intval);
- DPRINTF(sc, ATH_DBG_BEACON, "%s: nexttbtt %u intval %u (%u)\n",
- __func__, nexttbtt, intval, conf.beacon_interval);
+ DPRINTF(sc, ATH_DBG_BEACON, "nexttbtt %u intval %u (%u)\n",
+ nexttbtt, intval, conf.beacon_interval);
- /* Check for ATH9K_M_HOSTAP and sc_nostabeacons for WDS client */
- if (sc->sc_ah->ah_opmode == ATH9K_M_STA) {
+ /* Check for NL80211_IFTYPE_AP and sc_nostabeacons for WDS client */
+ if (sc->sc_ah->ah_opmode == NL80211_IFTYPE_STATION) {
struct ath9k_beacon_state bs;
u64 tsf;
u32 tsftu;
@@ -782,7 +754,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
bs.bs_sleepduration = bs.bs_dtimperiod;
DPRINTF(sc, ATH_DBG_BEACON,
- "%s: tsf %llu "
+ "tsf %llu "
"tsf:tu %u "
"intval %u "
"nexttbtt %u "
@@ -794,7 +766,6 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
"maxdur %u "
"next %u "
"timoffset %u\n",
- __func__,
(unsigned long long)tsf, tsftu,
bs.bs_intval,
bs.bs_nexttbtt,
@@ -818,7 +789,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
ath9k_hw_set_interrupts(ah, 0);
if (nexttbtt == intval)
intval |= ATH9K_BEACON_RESET_TSF;
- if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS) {
+ if (sc->sc_ah->ah_opmode == NL80211_IFTYPE_ADHOC) {
/*
* Pull nexttbtt forward to reflect the current
* TSF
@@ -834,8 +805,8 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
}
#undef FUDGE
DPRINTF(sc, ATH_DBG_BEACON,
- "%s: IBSS nexttbtt %u intval %u (%u)\n",
- __func__, nexttbtt,
+ "IBSS nexttbtt %u intval %u (%u)\n",
+ nexttbtt,
intval & ~ATH9K_BEACON_RESET_TSF,
conf.beacon_interval);
@@ -850,7 +821,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
if (!(ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL))
sc->sc_imask |= ATH9K_INT_SWBA;
ath_beaconq_config(sc);
- } else if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP) {
+ } else if (sc->sc_ah->ah_opmode == NL80211_IFTYPE_AP) {
/*
* In AP mode we enable the beacon timers and
* SWBA interrupts to prepare beacon frames.
@@ -860,20 +831,18 @@ void ath_beacon_config(struct ath_softc *sc, int if_id)
ath_beaconq_config(sc);
}
ath9k_hw_beaconinit(ah, nexttbtt, intval);
- sc->sc_bmisscount = 0;
+ sc->beacon.bmisscnt = 0;
ath9k_hw_set_interrupts(ah, sc->sc_imask);
/*
* When using a self-linked beacon descriptor in
* ibss mode load it once here.
*/
- if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS &&
+ if (sc->sc_ah->ah_opmode == NL80211_IFTYPE_ADHOC &&
(ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL))
ath_beacon_start_adhoc(sc, 0);
}
}
-/* Function to collect beacon rssi data and resync beacon if necessary */
-
void ath_beacon_sync(struct ath_softc *sc, int if_id)
{
/*
diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c
new file mode 100644
index 000000000000..3c7454fc51bd
--- /dev/null
+++ b/drivers/net/wireless/ath9k/calib.c
@@ -0,0 +1,1021 @@
+/*
+ * Copyright (c) 2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "core.h"
+#include "hw.h"
+#include "reg.h"
+#include "phy.h"
+
+static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93, -96 };
+
+/* We can tune this as we go by monitoring really low values */
+#define ATH9K_NF_TOO_LOW -60
+
+/* AR5416 may return very high value (like -31 dBm), in those cases the nf
+ * is incorrect and we should use the static NF value. Later we can try to
+ * find out why they are reporting these values */
+
+static bool ath9k_hw_nf_in_range(struct ath_hal *ah, s16 nf)
+{
+ if (nf > ATH9K_NF_TOO_LOW) {
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "noise floor value detected (%d) is "
+ "lower than what we think is a "
+ "reasonable value (%d)\n",
+ nf, ATH9K_NF_TOO_LOW);
+ return false;
+ }
+ return true;
+}
+
+static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
+{
+ int16_t nfval;
+ int16_t sort[ATH9K_NF_CAL_HIST_MAX];
+ int i, j;
+
+ for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
+ sort[i] = nfCalBuffer[i];
+
+ for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
+ for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
+ if (sort[j] > sort[j - 1]) {
+ nfval = sort[j];
+ sort[j] = sort[j - 1];
+ sort[j - 1] = nfval;
+ }
+ }
+ }
+ nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];
+
+ return nfval;
+}
+
+static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
+ int16_t *nfarray)
+{
+ int i;
+
+ for (i = 0; i < NUM_NF_READINGS; i++) {
+ h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
+
+ if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
+ h[i].currIndex = 0;
+
+ if (h[i].invalidNFcount > 0) {
+ if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE ||
+ nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) {
+ h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX;
+ } else {
+ h[i].invalidNFcount--;
+ h[i].privNF = nfarray[i];
+ }
+ } else {
+ h[i].privNF =
+ ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
+ }
+ }
+ return;
+}
+
+static void ath9k_hw_do_getnf(struct ath_hal *ah,
+ int16_t nfarray[NUM_NF_READINGS])
+{
+ int16_t nf;
+
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
+ else
+ nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
+
+ if (nf & 0x100)
+ nf = 0 - ((nf ^ 0x1ff) + 1);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "NF calibrated [ctl] [chain 0] is %d\n", nf);
+ nfarray[0] = nf;
+
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
+ AR9280_PHY_CH1_MINCCA_PWR);
+ else
+ nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
+ AR_PHY_CH1_MINCCA_PWR);
+
+ if (nf & 0x100)
+ nf = 0 - ((nf ^ 0x1ff) + 1);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "NF calibrated [ctl] [chain 1] is %d\n", nf);
+ nfarray[1] = nf;
+
+ if (!AR_SREV_9280(ah)) {
+ nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
+ AR_PHY_CH2_MINCCA_PWR);
+ if (nf & 0x100)
+ nf = 0 - ((nf ^ 0x1ff) + 1);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "NF calibrated [ctl] [chain 2] is %d\n", nf);
+ nfarray[2] = nf;
+ }
+
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
+ AR9280_PHY_EXT_MINCCA_PWR);
+ else
+ nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
+ AR_PHY_EXT_MINCCA_PWR);
+
+ if (nf & 0x100)
+ nf = 0 - ((nf ^ 0x1ff) + 1);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "NF calibrated [ext] [chain 0] is %d\n", nf);
+ nfarray[3] = nf;
+
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
+ AR9280_PHY_CH1_EXT_MINCCA_PWR);
+ else
+ nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
+ AR_PHY_CH1_EXT_MINCCA_PWR);
+
+ if (nf & 0x100)
+ nf = 0 - ((nf ^ 0x1ff) + 1);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "NF calibrated [ext] [chain 1] is %d\n", nf);
+ nfarray[4] = nf;
+
+ if (!AR_SREV_9280(ah)) {
+ nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
+ AR_PHY_CH2_EXT_MINCCA_PWR);
+ if (nf & 0x100)
+ nf = 0 - ((nf ^ 0x1ff) + 1);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "NF calibrated [ext] [chain 2] is %d\n", nf);
+ nfarray[5] = nf;
+ }
+}
+
+static bool getNoiseFloorThresh(struct ath_hal *ah,
+ const struct ath9k_channel *chan,
+ int16_t *nft)
+{
+ switch (chan->chanmode) {
+ case CHANNEL_A:
+ case CHANNEL_A_HT20:
+ case CHANNEL_A_HT40PLUS:
+ case CHANNEL_A_HT40MINUS:
+ *nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_5);
+ break;
+ case CHANNEL_B:
+ case CHANNEL_G:
+ case CHANNEL_G_HT20:
+ case CHANNEL_G_HT40PLUS:
+ case CHANNEL_G_HT40MINUS:
+ *nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_2);
+ break;
+ default:
+ DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
+ "invalid channel flags 0x%x\n", chan->channelFlags);
+ return false;
+ }
+
+ return true;
+}
+
+static void ath9k_hw_setup_calibration(struct ath_hal *ah,
+ struct hal_cal_list *currCal)
+{
+ REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
+ AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
+ currCal->calData->calCountMax);
+
+ switch (currCal->calData->calType) {
+ case IQ_MISMATCH_CAL:
+ REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "starting IQ Mismatch Calibration\n");
+ break;
+ case ADC_GAIN_CAL:
+ REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "starting ADC Gain Calibration\n");
+ break;
+ case ADC_DC_CAL:
+ REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "starting ADC DC Calibration\n");
+ break;
+ case ADC_DC_INIT_CAL:
+ REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "starting Init ADC DC Calibration\n");
+ break;
+ }
+
+ REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
+ AR_PHY_TIMING_CTRL4_DO_CAL);
+}
+
+static void ath9k_hw_reset_calibration(struct ath_hal *ah,
+ struct hal_cal_list *currCal)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ int i;
+
+ ath9k_hw_setup_calibration(ah, currCal);
+
+ currCal->calState = CAL_RUNNING;
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ ahp->ah_Meas0.sign[i] = 0;
+ ahp->ah_Meas1.sign[i] = 0;
+ ahp->ah_Meas2.sign[i] = 0;
+ ahp->ah_Meas3.sign[i] = 0;
+ }
+
+ ahp->ah_CalSamples = 0;
+}
+
+static void ath9k_hw_per_calibration(struct ath_hal *ah,
+ struct ath9k_channel *ichan,
+ u8 rxchainmask,
+ struct hal_cal_list *currCal,
+ bool *isCalDone)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ *isCalDone = false;
+
+ if (currCal->calState == CAL_RUNNING) {
+ if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) &
+ AR_PHY_TIMING_CTRL4_DO_CAL)) {
+
+ currCal->calData->calCollect(ah);
+ ahp->ah_CalSamples++;
+
+ if (ahp->ah_CalSamples >= currCal->calData->calNumSamples) {
+ int i, numChains = 0;
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ if (rxchainmask & (1 << i))
+ numChains++;
+ }
+
+ currCal->calData->calPostProc(ah, numChains);
+ ichan->CalValid |= currCal->calData->calType;
+ currCal->calState = CAL_DONE;
+ *isCalDone = true;
+ } else {
+ ath9k_hw_setup_calibration(ah, currCal);
+ }
+ }
+ } else if (!(ichan->CalValid & currCal->calData->calType)) {
+ ath9k_hw_reset_calibration(ah, currCal);
+ }
+}
+
+static bool ath9k_hw_iscal_supported(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ enum hal_cal_types calType)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ bool retval = false;
+
+ switch (calType & ahp->ah_suppCals) {
+ case IQ_MISMATCH_CAL:
+ if (!IS_CHAN_B(chan))
+ retval = true;
+ break;
+ case ADC_GAIN_CAL:
+ case ADC_DC_CAL:
+ if (!IS_CHAN_B(chan)
+ && !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)))
+ retval = true;
+ break;
+ }
+
+ return retval;
+}
+
+static void ath9k_hw_iqcal_collect(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ int i;
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ ahp->ah_totalPowerMeasI[i] +=
+ REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+ ahp->ah_totalPowerMeasQ[i] +=
+ REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+ ahp->ah_totalIqCorrMeas[i] +=
+ (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
+ ahp->ah_CalSamples, i, ahp->ah_totalPowerMeasI[i],
+ ahp->ah_totalPowerMeasQ[i],
+ ahp->ah_totalIqCorrMeas[i]);
+ }
+}
+
+static void ath9k_hw_adc_gaincal_collect(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ int i;
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ ahp->ah_totalAdcIOddPhase[i] +=
+ REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+ ahp->ah_totalAdcIEvenPhase[i] +=
+ REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+ ahp->ah_totalAdcQOddPhase[i] +=
+ REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+ ahp->ah_totalAdcQEvenPhase[i] +=
+ REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
+
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
+ "oddq=0x%08x; evenq=0x%08x;\n",
+ ahp->ah_CalSamples, i,
+ ahp->ah_totalAdcIOddPhase[i],
+ ahp->ah_totalAdcIEvenPhase[i],
+ ahp->ah_totalAdcQOddPhase[i],
+ ahp->ah_totalAdcQEvenPhase[i]);
+ }
+}
+
+static void ath9k_hw_adc_dccal_collect(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ int i;
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ ahp->ah_totalAdcDcOffsetIOddPhase[i] +=
+ (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
+ ahp->ah_totalAdcDcOffsetIEvenPhase[i] +=
+ (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
+ ahp->ah_totalAdcDcOffsetQOddPhase[i] +=
+ (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
+ ahp->ah_totalAdcDcOffsetQEvenPhase[i] +=
+ (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
+
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
+ "oddq=0x%08x; evenq=0x%08x;\n",
+ ahp->ah_CalSamples, i,
+ ahp->ah_totalAdcDcOffsetIOddPhase[i],
+ ahp->ah_totalAdcDcOffsetIEvenPhase[i],
+ ahp->ah_totalAdcDcOffsetQOddPhase[i],
+ ahp->ah_totalAdcDcOffsetQEvenPhase[i]);
+ }
+}
+
+static void ath9k_hw_iqcalibrate(struct ath_hal *ah, u8 numChains)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ u32 powerMeasQ, powerMeasI, iqCorrMeas;
+ u32 qCoffDenom, iCoffDenom;
+ int32_t qCoff, iCoff;
+ int iqCorrNeg, i;
+
+ for (i = 0; i < numChains; i++) {
+ powerMeasI = ahp->ah_totalPowerMeasI[i];
+ powerMeasQ = ahp->ah_totalPowerMeasQ[i];
+ iqCorrMeas = ahp->ah_totalIqCorrMeas[i];
+
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Starting IQ Cal and Correction for Chain %d\n",
+ i);
+
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Orignal: Chn %diq_corr_meas = 0x%08x\n",
+ i, ahp->ah_totalIqCorrMeas[i]);
+
+ iqCorrNeg = 0;
+
+ if (iqCorrMeas > 0x80000000) {
+ iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
+ iqCorrNeg = 1;
+ }
+
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
+ iqCorrNeg);
+
+ iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
+ qCoffDenom = powerMeasQ / 64;
+
+ if (powerMeasQ != 0) {
+ iCoff = iqCorrMeas / iCoffDenom;
+ qCoff = powerMeasI / qCoffDenom - 64;
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Chn %d iCoff = 0x%08x\n", i, iCoff);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Chn %d qCoff = 0x%08x\n", i, qCoff);
+
+ iCoff = iCoff & 0x3f;
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
+ if (iqCorrNeg == 0x0)
+ iCoff = 0x40 - iCoff;
+
+ if (qCoff > 15)
+ qCoff = 15;
+ else if (qCoff <= -16)
+ qCoff = 16;
+
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
+ i, iCoff, qCoff);
+
+ REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
+ iCoff);
+ REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
+ qCoff);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "IQ Cal and Correction done for Chain %d\n",
+ i);
+ }
+ }
+
+ REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
+ AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
+}
+
+static void ath9k_hw_adc_gaincal_calibrate(struct ath_hal *ah, u8 numChains)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset;
+ u32 qGainMismatch, iGainMismatch, val, i;
+
+ for (i = 0; i < numChains; i++) {
+ iOddMeasOffset = ahp->ah_totalAdcIOddPhase[i];
+ iEvenMeasOffset = ahp->ah_totalAdcIEvenPhase[i];
+ qOddMeasOffset = ahp->ah_totalAdcQOddPhase[i];
+ qEvenMeasOffset = ahp->ah_totalAdcQEvenPhase[i];
+
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Starting ADC Gain Cal for Chain %d\n", i);
+
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Chn %d pwr_meas_odd_i = 0x%08x\n", i,
+ iOddMeasOffset);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Chn %d pwr_meas_even_i = 0x%08x\n", i,
+ iEvenMeasOffset);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Chn %d pwr_meas_odd_q = 0x%08x\n", i,
+ qOddMeasOffset);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Chn %d pwr_meas_even_q = 0x%08x\n", i,
+ qEvenMeasOffset);
+
+ if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
+ iGainMismatch =
+ ((iEvenMeasOffset * 32) /
+ iOddMeasOffset) & 0x3f;
+ qGainMismatch =
+ ((qOddMeasOffset * 32) /
+ qEvenMeasOffset) & 0x3f;
+
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Chn %d gain_mismatch_i = 0x%08x\n", i,
+ iGainMismatch);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Chn %d gain_mismatch_q = 0x%08x\n", i,
+ qGainMismatch);
+
+ val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
+ val &= 0xfffff000;
+ val |= (qGainMismatch) | (iGainMismatch << 6);
+ REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
+
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "ADC Gain Cal done for Chain %d\n", i);
+ }
+ }
+
+ REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
+ REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
+ AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
+}
+
+static void ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah, u8 numChains)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ u32 iOddMeasOffset, iEvenMeasOffset, val, i;
+ int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
+ const struct hal_percal_data *calData =
+ ahp->ah_cal_list_curr->calData;
+ u32 numSamples =
+ (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
+
+ for (i = 0; i < numChains; i++) {
+ iOddMeasOffset = ahp->ah_totalAdcDcOffsetIOddPhase[i];
+ iEvenMeasOffset = ahp->ah_totalAdcDcOffsetIEvenPhase[i];
+ qOddMeasOffset = ahp->ah_totalAdcDcOffsetQOddPhase[i];
+ qEvenMeasOffset = ahp->ah_totalAdcDcOffsetQEvenPhase[i];
+
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Starting ADC DC Offset Cal for Chain %d\n", i);
+
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Chn %d pwr_meas_odd_i = %d\n", i,
+ iOddMeasOffset);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Chn %d pwr_meas_even_i = %d\n", i,
+ iEvenMeasOffset);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Chn %d pwr_meas_odd_q = %d\n", i,
+ qOddMeasOffset);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Chn %d pwr_meas_even_q = %d\n", i,
+ qEvenMeasOffset);
+
+ iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
+ numSamples) & 0x1ff;
+ qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
+ numSamples) & 0x1ff;
+
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
+ iDcMismatch);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
+ qDcMismatch);
+
+ val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
+ val &= 0xc0000fff;
+ val |= (qDcMismatch << 12) | (iDcMismatch << 21);
+ REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
+
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "ADC DC Offset Cal done for Chain %d\n", i);
+ }
+
+ REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
+ REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
+ AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
+}
+
+void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
+ bool *isCalDone)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_channel *ichan =
+ ath9k_regd_check_channel(ah, chan);
+ struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
+
+ *isCalDone = true;
+
+ if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
+ return;
+
+ if (currCal == NULL)
+ return;
+
+ if (ichan == NULL) {
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "invalid channel %u/0x%x; no mapping\n",
+ chan->channel, chan->channelFlags);
+ return;
+ }
+
+
+ if (currCal->calState != CAL_DONE) {
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Calibration state incorrect, %d\n",
+ currCal->calState);
+ return;
+ }
+
+
+ if (!ath9k_hw_iscal_supported(ah, chan, currCal->calData->calType))
+ return;
+
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "Resetting Cal %d state for channel %u/0x%x\n",
+ currCal->calData->calType, chan->channel,
+ chan->channelFlags);
+
+ ichan->CalValid &= ~currCal->calData->calType;
+ currCal->calState = CAL_WAITING;
+
+ *isCalDone = false;
+}
+
+void ath9k_hw_start_nfcal(struct ath_hal *ah)
+{
+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_ENABLE_NF);
+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+}
+
+void ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ struct ath9k_nfcal_hist *h;
+ int i, j;
+ int32_t val;
+ const u32 ar5416_cca_regs[6] = {
+ AR_PHY_CCA,
+ AR_PHY_CH1_CCA,
+ AR_PHY_CH2_CCA,
+ AR_PHY_EXT_CCA,
+ AR_PHY_CH1_EXT_CCA,
+ AR_PHY_CH2_EXT_CCA
+ };
+ u8 chainmask;
+
+ if (AR_SREV_9280(ah))
+ chainmask = 0x1B;
+ else
+ chainmask = 0x3F;
+
+#ifdef ATH_NF_PER_CHAN
+ h = chan->nfCalHist;
+#else
+ h = ah->nfCalHist;
+#endif
+
+ for (i = 0; i < NUM_NF_READINGS; i++) {
+ if (chainmask & (1 << i)) {
+ val = REG_READ(ah, ar5416_cca_regs[i]);
+ val &= 0xFFFFFE00;
+ val |= (((u32) (h[i].privNF) << 1) & 0x1ff);
+ REG_WRITE(ah, ar5416_cca_regs[i], val);
+ }
+ }
+
+ REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_ENABLE_NF);
+ REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
+ AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
+ REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
+
+ for (j = 0; j < 1000; j++) {
+ if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
+ AR_PHY_AGC_CONTROL_NF) == 0)
+ break;
+ udelay(10);
+ }
+
+ for (i = 0; i < NUM_NF_READINGS; i++) {
+ if (chainmask & (1 << i)) {
+ val = REG_READ(ah, ar5416_cca_regs[i]);
+ val &= 0xFFFFFE00;
+ val |= (((u32) (-50) << 1) & 0x1ff);
+ REG_WRITE(ah, ar5416_cca_regs[i], val);
+ }
+ }
+}
+
+int16_t ath9k_hw_getnf(struct ath_hal *ah,
+ struct ath9k_channel *chan)
+{
+ int16_t nf, nfThresh;
+ int16_t nfarray[NUM_NF_READINGS] = { 0 };
+ struct ath9k_nfcal_hist *h;
+ u8 chainmask;
+
+ if (AR_SREV_9280(ah))
+ chainmask = 0x1B;
+ else
+ chainmask = 0x3F;
+
+ chan->channelFlags &= (~CHANNEL_CW_INT);
+ if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "NF did not complete in calibration window\n");
+ nf = 0;
+ chan->rawNoiseFloor = nf;
+ return chan->rawNoiseFloor;
+ } else {
+ ath9k_hw_do_getnf(ah, nfarray);
+ nf = nfarray[0];
+ if (getNoiseFloorThresh(ah, chan, &nfThresh)
+ && nf > nfThresh) {
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "noise floor failed detected; "
+ "detected %d, threshold %d\n",
+ nf, nfThresh);
+ chan->channelFlags |= CHANNEL_CW_INT;
+ }
+ }
+
+#ifdef ATH_NF_PER_CHAN
+ h = chan->nfCalHist;
+#else
+ h = ah->nfCalHist;
+#endif
+
+ ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
+ chan->rawNoiseFloor = h[0].privNF;
+
+ return chan->rawNoiseFloor;
+}
+
+void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah)
+{
+ int i, j;
+
+ for (i = 0; i < NUM_NF_READINGS; i++) {
+ ah->nfCalHist[i].currIndex = 0;
+ ah->nfCalHist[i].privNF = AR_PHY_CCA_MAX_GOOD_VALUE;
+ ah->nfCalHist[i].invalidNFcount =
+ AR_PHY_CCA_FILTERWINDOW_LENGTH;
+ for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
+ ah->nfCalHist[i].nfCalBuffer[j] =
+ AR_PHY_CCA_MAX_GOOD_VALUE;
+ }
+ }
+ return;
+}
+
+s16 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ struct ath9k_channel *ichan;
+ s16 nf;
+
+ ichan = ath9k_regd_check_channel(ah, chan);
+ if (ichan == NULL) {
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "invalid channel %u/0x%x; no mapping\n",
+ chan->channel, chan->channelFlags);
+ return ATH_DEFAULT_NOISE_FLOOR;
+ }
+ if (ichan->rawNoiseFloor == 0) {
+ enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan);
+ nf = NOISE_FLOOR[mode];
+ } else
+ nf = ichan->rawNoiseFloor;
+
+ if (!ath9k_hw_nf_in_range(ah, nf))
+ nf = ATH_DEFAULT_NOISE_FLOOR;
+
+ return nf;
+}
+
+bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
+ u8 rxchainmask, bool longcal,
+ bool *isCalDone)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
+ struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);
+
+ *isCalDone = true;
+
+ if (ichan == NULL) {
+ DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
+ "invalid channel %u/0x%x; no mapping\n",
+ chan->channel, chan->channelFlags);
+ return false;
+ }
+
+ if (currCal &&
+ (currCal->calState == CAL_RUNNING ||
+ currCal->calState == CAL_WAITING)) {
+ ath9k_hw_per_calibration(ah, ichan, rxchainmask, currCal,
+ isCalDone);
+ if (*isCalDone) {
+ ahp->ah_cal_list_curr = currCal = currCal->calNext;
+
+ if (currCal->calState == CAL_WAITING) {
+ *isCalDone = false;
+ ath9k_hw_reset_calibration(ah, currCal);
+ }
+ }
+ }
+
+ if (longcal) {
+ ath9k_hw_getnf(ah, ichan);
+ ath9k_hw_loadnf(ah, ah->ah_curchan);
+ ath9k_hw_start_nfcal(ah);
+
+ if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) {
+ chan->channelFlags |= CHANNEL_CW_INT;
+ ichan->channelFlags &= ~CHANNEL_CW_INT;
+ }
+ }
+
+ return true;
+}
+
+static inline void ath9k_hw_9285_pa_cal(struct ath_hal *ah)
+{
+
+ u32 regVal;
+ int i, offset, offs_6_1, offs_0;
+ u32 ccomp_org, reg_field;
+ u32 regList[][2] = {
+ { 0x786c, 0 },
+ { 0x7854, 0 },
+ { 0x7820, 0 },
+ { 0x7824, 0 },
+ { 0x7868, 0 },
+ { 0x783c, 0 },
+ { 0x7838, 0 },
+ };
+
+ if (AR_SREV_9285_11(ah)) {
+ REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
+ udelay(10);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(regList); i++)
+ regList[i][1] = REG_READ(ah, regList[i][0]);
+
+ regVal = REG_READ(ah, 0x7834);
+ regVal &= (~(0x1));
+ REG_WRITE(ah, 0x7834, regVal);
+ regVal = REG_READ(ah, 0x9808);
+ regVal |= (0x1 << 27);
+ REG_WRITE(ah, 0x9808, regVal);
+
+ REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1);
+ REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1);
+ REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1);
+ REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 1);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0);
+ ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 7);
+
+ REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0);
+ udelay(30);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0);
+
+ for (i = 6; i > 0; i--) {
+ regVal = REG_READ(ah, 0x7834);
+ regVal |= (1 << (19 + i));
+ REG_WRITE(ah, 0x7834, regVal);
+ udelay(1);
+ regVal = REG_READ(ah, 0x7834);
+ regVal &= (~(0x1 << (19 + i)));
+ reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9);
+ regVal |= (reg_field << (19 + i));
+ REG_WRITE(ah, 0x7834, regVal);
+ }
+
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1);
+ udelay(1);
+ reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field);
+ offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS);
+ offs_0 = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP);
+
+ offset = (offs_6_1<<1) | offs_0;
+ offset = offset - 0;
+ offs_6_1 = offset>>1;
+ offs_0 = offset & 1;
+
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1);
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0);
+
+ regVal = REG_READ(ah, 0x7834);
+ regVal |= 0x1;
+ REG_WRITE(ah, 0x7834, regVal);
+ regVal = REG_READ(ah, 0x9808);
+ regVal &= (~(0x1 << 27));
+ REG_WRITE(ah, 0x9808, regVal);
+
+ for (i = 0; i < ARRAY_SIZE(regList); i++)
+ REG_WRITE(ah, regList[i][0], regList[i][1]);
+
+ REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org);
+
+ if (AR_SREV_9285_11(ah))
+ REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
+
+}
+
+bool ath9k_hw_init_cal(struct ath_hal *ah,
+ struct ath9k_channel *chan)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan);
+
+ REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+ REG_READ(ah, AR_PHY_AGC_CONTROL) |
+ AR_PHY_AGC_CONTROL_CAL);
+
+ if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "offset calibration failed to complete in 1ms; "
+ "noisy environment?\n");
+ return false;
+ }
+
+ if (AR_SREV_9285(ah) && AR_SREV_9285_11_OR_LATER(ah))
+ ath9k_hw_9285_pa_cal(ah);
+
+ REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+ REG_READ(ah, AR_PHY_AGC_CONTROL) |
+ AR_PHY_AGC_CONTROL_NF);
+
+ ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = NULL;
+
+ if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
+ if (ath9k_hw_iscal_supported(ah, chan, ADC_GAIN_CAL)) {
+ INIT_CAL(&ahp->ah_adcGainCalData);
+ INSERT_CAL(ahp, &ahp->ah_adcGainCalData);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "enabling ADC Gain Calibration.\n");
+ }
+ if (ath9k_hw_iscal_supported(ah, chan, ADC_DC_CAL)) {
+ INIT_CAL(&ahp->ah_adcDcCalData);
+ INSERT_CAL(ahp, &ahp->ah_adcDcCalData);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "enabling ADC DC Calibration.\n");
+ }
+ if (ath9k_hw_iscal_supported(ah, chan, IQ_MISMATCH_CAL)) {
+ INIT_CAL(&ahp->ah_iqCalData);
+ INSERT_CAL(ahp, &ahp->ah_iqCalData);
+ DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
+ "enabling IQ Calibration.\n");
+ }
+
+ ahp->ah_cal_list_curr = ahp->ah_cal_list;
+
+ if (ahp->ah_cal_list_curr)
+ ath9k_hw_reset_calibration(ah, ahp->ah_cal_list_curr);
+ }
+
+ ichan->CalValid = 0;
+
+ return true;
+}
+
+const struct hal_percal_data iq_cal_multi_sample = {
+ IQ_MISMATCH_CAL,
+ MAX_CAL_SAMPLES,
+ PER_MIN_LOG_COUNT,
+ ath9k_hw_iqcal_collect,
+ ath9k_hw_iqcalibrate
+};
+const struct hal_percal_data iq_cal_single_sample = {
+ IQ_MISMATCH_CAL,
+ MIN_CAL_SAMPLES,
+ PER_MAX_LOG_COUNT,
+ ath9k_hw_iqcal_collect,
+ ath9k_hw_iqcalibrate
+};
+const struct hal_percal_data adc_gain_cal_multi_sample = {
+ ADC_GAIN_CAL,
+ MAX_CAL_SAMPLES,
+ PER_MIN_LOG_COUNT,
+ ath9k_hw_adc_gaincal_collect,
+ ath9k_hw_adc_gaincal_calibrate
+};
+const struct hal_percal_data adc_gain_cal_single_sample = {
+ ADC_GAIN_CAL,
+ MIN_CAL_SAMPLES,
+ PER_MAX_LOG_COUNT,
+ ath9k_hw_adc_gaincal_collect,
+ ath9k_hw_adc_gaincal_calibrate
+};
+const struct hal_percal_data adc_dc_cal_multi_sample = {
+ ADC_DC_CAL,
+ MAX_CAL_SAMPLES,
+ PER_MIN_LOG_COUNT,
+ ath9k_hw_adc_dccal_collect,
+ ath9k_hw_adc_dccal_calibrate
+};
+const struct hal_percal_data adc_dc_cal_single_sample = {
+ ADC_DC_CAL,
+ MIN_CAL_SAMPLES,
+ PER_MAX_LOG_COUNT,
+ ath9k_hw_adc_dccal_collect,
+ ath9k_hw_adc_dccal_calibrate
+};
+const struct hal_percal_data adc_init_dc_cal = {
+ ADC_DC_INIT_CAL,
+ MIN_CAL_SAMPLES,
+ INIT_LOG_COUNT,
+ ath9k_hw_adc_dccal_collect,
+ ath9k_hw_adc_dccal_calibrate
+};
diff --git a/drivers/net/wireless/ath9k/core.c b/drivers/net/wireless/ath9k/core.c
deleted file mode 100644
index c5033f6f42ac..000000000000
--- a/drivers/net/wireless/ath9k/core.c
+++ /dev/null
@@ -1,1886 +0,0 @@
-/*
- * Copyright (c) 2008, Atheros Communications Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
- /* Implementation of the main "ATH" layer. */
-
-#include "core.h"
-#include "regd.h"
-
-static int ath_outdoor; /* enable outdoor use */
-
-static u32 ath_chainmask_sel_up_rssi_thres =
- ATH_CHAINMASK_SEL_UP_RSSI_THRES;
-static u32 ath_chainmask_sel_down_rssi_thres =
- ATH_CHAINMASK_SEL_DOWN_RSSI_THRES;
-static u32 ath_chainmask_sel_period =
- ATH_CHAINMASK_SEL_TIMEOUT;
-
-/* return bus cachesize in 4B word units */
-
-static void bus_read_cachesize(struct ath_softc *sc, int *csz)
-{
- u8 u8tmp;
-
- pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, (u8 *)&u8tmp);
- *csz = (int)u8tmp;
-
- /*
- * This check was put in to avoid "unplesant" consequences if
- * the bootrom has not fully initialized all PCI devices.
- * Sometimes the cache line size register is not set
- */
-
- if (*csz == 0)
- *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */
-}
-
-/*
- * Set current operating mode
- *
- * This function initializes and fills the rate table in the ATH object based
- * on the operating mode.
-*/
-static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode)
-{
- const struct ath9k_rate_table *rt;
- int i;
-
- memset(sc->sc_rixmap, 0xff, sizeof(sc->sc_rixmap));
- rt = ath9k_hw_getratetable(sc->sc_ah, mode);
- BUG_ON(!rt);
-
- for (i = 0; i < rt->rateCount; i++)
- sc->sc_rixmap[rt->info[i].rateCode] = (u8) i;
-
- memset(sc->sc_hwmap, 0, sizeof(sc->sc_hwmap));
- for (i = 0; i < 256; i++) {
- u8 ix = rt->rateCodeToIndex[i];
-
- if (ix == 0xff)
- continue;
-
- sc->sc_hwmap[i].ieeerate =
- rt->info[ix].dot11Rate & IEEE80211_RATE_VAL;
- sc->sc_hwmap[i].rateKbps = rt->info[ix].rateKbps;
-
- if (rt->info[ix].shortPreamble ||
- rt->info[ix].phy == PHY_OFDM) {
- /* XXX: Handle this */
- }
-
- /* NB: this uses the last entry if the rate isn't found */
- /* XXX beware of overlow */
- }
- sc->sc_currates = rt;
- sc->sc_curmode = mode;
- /*
- * All protection frames are transmited at 2Mb/s for
- * 11g, otherwise at 1Mb/s.
- * XXX select protection rate index from rate table.
- */
- sc->sc_protrix = (mode == ATH9K_MODE_11G ? 1 : 0);
-}
-
-/*
- * Set up rate table (legacy rates)
- */
-static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band)
-{
- struct ath_hal *ah = sc->sc_ah;
- const struct ath9k_rate_table *rt = NULL;
- struct ieee80211_supported_band *sband;
- struct ieee80211_rate *rate;
- int i, maxrates;
-
- switch (band) {
- case IEEE80211_BAND_2GHZ:
- rt = ath9k_hw_getratetable(ah, ATH9K_MODE_11G);
- break;
- case IEEE80211_BAND_5GHZ:
- rt = ath9k_hw_getratetable(ah, ATH9K_MODE_11A);
- break;
- default:
- break;
- }
-
- if (rt == NULL)
- return;
-
- sband = &sc->sbands[band];
- rate = sc->rates[band];
-
- if (rt->rateCount > ATH_RATE_MAX)
- maxrates = ATH_RATE_MAX;
- else
- maxrates = rt->rateCount;
-
- for (i = 0; i < maxrates; i++) {
- rate[i].bitrate = rt->info[i].rateKbps / 100;
- rate[i].hw_value = rt->info[i].rateCode;
- sband->n_bitrates++;
- DPRINTF(sc, ATH_DBG_CONFIG,
- "%s: Rate: %2dMbps, ratecode: %2d\n",
- __func__,
- rate[i].bitrate / 10,
- rate[i].hw_value);
- }
-}
-
-/*
- * Set up channel list
- */
-static int ath_setup_channels(struct ath_softc *sc)
-{
- struct ath_hal *ah = sc->sc_ah;
- int nchan, i, a = 0, b = 0;
- u8 regclassids[ATH_REGCLASSIDS_MAX];
- u32 nregclass = 0;
- struct ieee80211_supported_band *band_2ghz;
- struct ieee80211_supported_band *band_5ghz;
- struct ieee80211_channel *chan_2ghz;
- struct ieee80211_channel *chan_5ghz;
- struct ath9k_channel *c;
-
- /* Fill in ah->ah_channels */
- if (!ath9k_regd_init_channels(ah,
- ATH_CHAN_MAX,
- (u32 *)&nchan,
- regclassids,
- ATH_REGCLASSIDS_MAX,
- &nregclass,
- CTRY_DEFAULT,
- false,
- 1)) {
- u32 rd = ah->ah_currentRD;
-
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to collect channel list; "
- "regdomain likely %u country code %u\n",
- __func__, rd, CTRY_DEFAULT);
- return -EINVAL;
- }
-
- band_2ghz = &sc->sbands[IEEE80211_BAND_2GHZ];
- band_5ghz = &sc->sbands[IEEE80211_BAND_5GHZ];
- chan_2ghz = sc->channels[IEEE80211_BAND_2GHZ];
- chan_5ghz = sc->channels[IEEE80211_BAND_5GHZ];
-
- for (i = 0; i < nchan; i++) {
- c = &ah->ah_channels[i];
- if (IS_CHAN_2GHZ(c)) {
- chan_2ghz[a].band = IEEE80211_BAND_2GHZ;
- chan_2ghz[a].center_freq = c->channel;
- chan_2ghz[a].max_power = c->maxTxPower;
-
- if (c->privFlags & CHANNEL_DISALLOW_ADHOC)
- chan_2ghz[a].flags |=
- IEEE80211_CHAN_NO_IBSS;
- if (c->channelFlags & CHANNEL_PASSIVE)
- chan_2ghz[a].flags |=
- IEEE80211_CHAN_PASSIVE_SCAN;
-
- band_2ghz->n_channels = ++a;
-
- DPRINTF(sc, ATH_DBG_CONFIG,
- "%s: 2MHz channel: %d, "
- "channelFlags: 0x%x\n",
- __func__,
- c->channel,
- c->channelFlags);
- } else if (IS_CHAN_5GHZ(c)) {
- chan_5ghz[b].band = IEEE80211_BAND_5GHZ;
- chan_5ghz[b].center_freq = c->channel;
- chan_5ghz[b].max_power = c->maxTxPower;
-
- if (c->privFlags & CHANNEL_DISALLOW_ADHOC)
- chan_5ghz[b].flags |=
- IEEE80211_CHAN_NO_IBSS;
- if (c->channelFlags & CHANNEL_PASSIVE)
- chan_5ghz[b].flags |=
- IEEE80211_CHAN_PASSIVE_SCAN;
-
- band_5ghz->n_channels = ++b;
-
- DPRINTF(sc, ATH_DBG_CONFIG,
- "%s: 5MHz channel: %d, "
- "channelFlags: 0x%x\n",
- __func__,
- c->channel,
- c->channelFlags);
- }
- }
-
- return 0;
-}
-
-/*
- * Determine mode from channel flags
- *
- * This routine will provide the enumerated WIRELESSS_MODE value based
- * on the settings of the channel flags. If no valid set of flags
- * exist, the lowest mode (11b) is selected.
-*/
-
-static enum wireless_mode ath_chan2mode(struct ath9k_channel *chan)
-{
- if (chan->chanmode == CHANNEL_A)
- return ATH9K_MODE_11A;
- else if (chan->chanmode == CHANNEL_G)
- return ATH9K_MODE_11G;
- else if (chan->chanmode == CHANNEL_B)
- return ATH9K_MODE_11B;
- else if (chan->chanmode == CHANNEL_A_HT20)
- return ATH9K_MODE_11NA_HT20;
- else if (chan->chanmode == CHANNEL_G_HT20)
- return ATH9K_MODE_11NG_HT20;
- else if (chan->chanmode == CHANNEL_A_HT40PLUS)
- return ATH9K_MODE_11NA_HT40PLUS;
- else if (chan->chanmode == CHANNEL_A_HT40MINUS)
- return ATH9K_MODE_11NA_HT40MINUS;
- else if (chan->chanmode == CHANNEL_G_HT40PLUS)
- return ATH9K_MODE_11NG_HT40PLUS;
- else if (chan->chanmode == CHANNEL_G_HT40MINUS)
- return ATH9K_MODE_11NG_HT40MINUS;
-
- WARN_ON(1); /* should not get here */
-
- return ATH9K_MODE_11B;
-}
-
-/*
- * Stop the device, grabbing the top-level lock to protect
- * against concurrent entry through ath_init (which can happen
- * if another thread does a system call and the thread doing the
- * stop is preempted).
- */
-
-static int ath_stop(struct ath_softc *sc)
-{
- struct ath_hal *ah = sc->sc_ah;
-
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: invalid %ld\n",
- __func__, sc->sc_flags & SC_OP_INVALID);
-
- /*
- * Shutdown the hardware and driver:
- * stop output from above
- * turn off timers
- * disable interrupts
- * clear transmit machinery
- * clear receive machinery
- * turn off the radio
- * reclaim beacon resources
- *
- * Note that some of this work is not possible if the
- * hardware is gone (invalid).
- */
-
- ath_draintxq(sc, false);
- if (!(sc->sc_flags & SC_OP_INVALID)) {
- ath_stoprecv(sc);
- ath9k_hw_phy_disable(ah);
- } else
- sc->sc_rxlink = NULL;
-
- return 0;
-}
-
-/*
- * Set the current channel
- *
- * Set/change channels. If the channel is really being changed, it's done
- * by reseting the chip. To accomplish this we must first cleanup any pending
- * DMA, then restart stuff after a la ath_init.
-*/
-int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan)
-{
- struct ath_hal *ah = sc->sc_ah;
- bool fastcc = true, stopped;
-
- if (sc->sc_flags & SC_OP_INVALID) /* the device is invalid or removed */
- return -EIO;
-
- DPRINTF(sc, ATH_DBG_CONFIG,
- "%s: %u (%u MHz) -> %u (%u MHz), cflags:%x\n",
- __func__,
- ath9k_hw_mhz2ieee(ah, sc->sc_ah->ah_curchan->channel,
- sc->sc_ah->ah_curchan->channelFlags),
- sc->sc_ah->ah_curchan->channel,
- ath9k_hw_mhz2ieee(ah, hchan->channel, hchan->channelFlags),
- hchan->channel, hchan->channelFlags);
-
- if (hchan->channel != sc->sc_ah->ah_curchan->channel ||
- hchan->channelFlags != sc->sc_ah->ah_curchan->channelFlags ||
- (sc->sc_flags & SC_OP_CHAINMASK_UPDATE) ||
- (sc->sc_flags & SC_OP_FULL_RESET)) {
- int status;
- /*
- * This is only performed if the channel settings have
- * actually changed.
- *
- * To switch channels clear any pending DMA operations;
- * wait long enough for the RX fifo to drain, reset the
- * hardware at the new frequency, and then re-enable
- * the relevant bits of the h/w.
- */
- ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */
- ath_draintxq(sc, false); /* clear pending tx frames */
- stopped = ath_stoprecv(sc); /* turn off frame recv */
-
- /* XXX: do not flush receive queue here. We don't want
- * to flush data frames already in queue because of
- * changing channel. */
-
- if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET))
- fastcc = false;
-
- spin_lock_bh(&sc->sc_resetlock);
- if (!ath9k_hw_reset(ah, hchan,
- sc->sc_ht_info.tx_chan_width,
- sc->sc_tx_chainmask,
- sc->sc_rx_chainmask,
- sc->sc_ht_extprotspacing,
- fastcc, &status)) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to reset channel %u (%uMhz) "
- "flags 0x%x hal status %u\n", __func__,
- ath9k_hw_mhz2ieee(ah, hchan->channel,
- hchan->channelFlags),
- hchan->channel, hchan->channelFlags, status);
- spin_unlock_bh(&sc->sc_resetlock);
- return -EIO;
- }
- spin_unlock_bh(&sc->sc_resetlock);
-
- sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE;
- sc->sc_flags &= ~SC_OP_FULL_RESET;
-
- /* Re-enable rx framework */
- if (ath_startrecv(sc) != 0) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to restart recv logic\n", __func__);
- return -EIO;
- }
- /*
- * Change channels and update the h/w rate map
- * if we're switching; e.g. 11a to 11b/g.
- */
- ath_setcurmode(sc, ath_chan2mode(hchan));
-
- ath_update_txpow(sc); /* update tx power state */
- /*
- * Re-enable interrupts.
- */
- ath9k_hw_set_interrupts(ah, sc->sc_imask);
- }
- return 0;
-}
-
-/**********************/
-/* Chainmask Handling */
-/**********************/
-
-static void ath_chainmask_sel_timertimeout(unsigned long data)
-{
- struct ath_chainmask_sel *cm = (struct ath_chainmask_sel *)data;
- cm->switch_allowed = 1;
-}
-
-/* Start chainmask select timer */
-static void ath_chainmask_sel_timerstart(struct ath_chainmask_sel *cm)
-{
- cm->switch_allowed = 0;
- mod_timer(&cm->timer, ath_chainmask_sel_period);
-}
-
-/* Stop chainmask select timer */
-static void ath_chainmask_sel_timerstop(struct ath_chainmask_sel *cm)
-{
- cm->switch_allowed = 0;
- del_timer_sync(&cm->timer);
-}
-
-static void ath_chainmask_sel_init(struct ath_softc *sc, struct ath_node *an)
-{
- struct ath_chainmask_sel *cm = &an->an_chainmask_sel;
-
- memset(cm, 0, sizeof(struct ath_chainmask_sel));
-
- cm->cur_tx_mask = sc->sc_tx_chainmask;
- cm->cur_rx_mask = sc->sc_rx_chainmask;
- cm->tx_avgrssi = ATH_RSSI_DUMMY_MARKER;
- setup_timer(&cm->timer,
- ath_chainmask_sel_timertimeout, (unsigned long) cm);
-}
-
-int ath_chainmask_sel_logic(struct ath_softc *sc, struct ath_node *an)
-{
- struct ath_chainmask_sel *cm = &an->an_chainmask_sel;
-
- /*
- * Disable auto-swtiching in one of the following if conditions.
- * sc_chainmask_auto_sel is used for internal global auto-switching
- * enabled/disabled setting
- */
- if (sc->sc_ah->ah_caps.tx_chainmask != ATH_CHAINMASK_SEL_3X3) {
- cm->cur_tx_mask = sc->sc_tx_chainmask;
- return cm->cur_tx_mask;
- }
-
- if (cm->tx_avgrssi == ATH_RSSI_DUMMY_MARKER)
- return cm->cur_tx_mask;
-
- if (cm->switch_allowed) {
- /* Switch down from tx 3 to tx 2. */
- if (cm->cur_tx_mask == ATH_CHAINMASK_SEL_3X3 &&
- ATH_RSSI_OUT(cm->tx_avgrssi) >=
- ath_chainmask_sel_down_rssi_thres) {
- cm->cur_tx_mask = sc->sc_tx_chainmask;
-
- /* Don't let another switch happen until
- * this timer expires */
- ath_chainmask_sel_timerstart(cm);
- }
- /* Switch up from tx 2 to 3. */
- else if (cm->cur_tx_mask == sc->sc_tx_chainmask &&
- ATH_RSSI_OUT(cm->tx_avgrssi) <=
- ath_chainmask_sel_up_rssi_thres) {
- cm->cur_tx_mask = ATH_CHAINMASK_SEL_3X3;
-
- /* Don't let another switch happen
- * until this timer expires */
- ath_chainmask_sel_timerstart(cm);
- }
- }
-
- return cm->cur_tx_mask;
-}
-
-/*
- * Update tx/rx chainmask. For legacy association,
- * hard code chainmask to 1x1, for 11n association, use
- * the chainmask configuration.
- */
-
-void ath_update_chainmask(struct ath_softc *sc, int is_ht)
-{
- sc->sc_flags |= SC_OP_CHAINMASK_UPDATE;
- if (is_ht) {
- sc->sc_tx_chainmask = sc->sc_ah->ah_caps.tx_chainmask;
- sc->sc_rx_chainmask = sc->sc_ah->ah_caps.rx_chainmask;
- } else {
- sc->sc_tx_chainmask = 1;
- sc->sc_rx_chainmask = 1;
- }
-
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: tx chmask: %d, rx chmask: %d\n",
- __func__, sc->sc_tx_chainmask, sc->sc_rx_chainmask);
-}
-
-/*******/
-/* ANI */
-/*******/
-
-/*
- * This routine performs the periodic noise floor calibration function
- * that is used to adjust and optimize the chip performance. This
- * takes environmental changes (location, temperature) into account.
- * When the task is complete, it reschedules itself depending on the
- * appropriate interval that was calculated.
- */
-
-static void ath_ani_calibrate(unsigned long data)
-{
- struct ath_softc *sc;
- struct ath_hal *ah;
- bool longcal = false;
- bool shortcal = false;
- bool aniflag = false;
- unsigned int timestamp = jiffies_to_msecs(jiffies);
- u32 cal_interval;
-
- sc = (struct ath_softc *)data;
- ah = sc->sc_ah;
-
- /*
- * don't calibrate when we're scanning.
- * we are most likely not on our home channel.
- */
- if (sc->rx_filter & FIF_BCN_PRBRESP_PROMISC)
- return;
-
- /* Long calibration runs independently of short calibration. */
- if ((timestamp - sc->sc_ani.sc_longcal_timer) >= ATH_LONG_CALINTERVAL) {
- longcal = true;
- DPRINTF(sc, ATH_DBG_ANI, "%s: longcal @%lu\n",
- __func__, jiffies);
- sc->sc_ani.sc_longcal_timer = timestamp;
- }
-
- /* Short calibration applies only while sc_caldone is false */
- if (!sc->sc_ani.sc_caldone) {
- if ((timestamp - sc->sc_ani.sc_shortcal_timer) >=
- ATH_SHORT_CALINTERVAL) {
- shortcal = true;
- DPRINTF(sc, ATH_DBG_ANI, "%s: shortcal @%lu\n",
- __func__, jiffies);
- sc->sc_ani.sc_shortcal_timer = timestamp;
- sc->sc_ani.sc_resetcal_timer = timestamp;
- }
- } else {
- if ((timestamp - sc->sc_ani.sc_resetcal_timer) >=
- ATH_RESTART_CALINTERVAL) {
- ath9k_hw_reset_calvalid(ah, ah->ah_curchan,
- &sc->sc_ani.sc_caldone);
- if (sc->sc_ani.sc_caldone)
- sc->sc_ani.sc_resetcal_timer = timestamp;
- }
- }
-
- /* Verify whether we must check ANI */
- if ((timestamp - sc->sc_ani.sc_checkani_timer) >=
- ATH_ANI_POLLINTERVAL) {
- aniflag = true;
- sc->sc_ani.sc_checkani_timer = timestamp;
- }
-
- /* Skip all processing if there's nothing to do. */
- if (longcal || shortcal || aniflag) {
- /* Call ANI routine if necessary */
- if (aniflag)
- ath9k_hw_ani_monitor(ah, &sc->sc_halstats,
- ah->ah_curchan);
-
- /* Perform calibration if necessary */
- if (longcal || shortcal) {
- bool iscaldone = false;
-
- if (ath9k_hw_calibrate(ah, ah->ah_curchan,
- sc->sc_rx_chainmask, longcal,
- &iscaldone)) {
- if (longcal)
- sc->sc_ani.sc_noise_floor =
- ath9k_hw_getchan_noise(ah,
- ah->ah_curchan);
-
- DPRINTF(sc, ATH_DBG_ANI,
- "%s: calibrate chan %u/%x nf: %d\n",
- __func__,
- ah->ah_curchan->channel,
- ah->ah_curchan->channelFlags,
- sc->sc_ani.sc_noise_floor);
- } else {
- DPRINTF(sc, ATH_DBG_ANY,
- "%s: calibrate chan %u/%x failed\n",
- __func__,
- ah->ah_curchan->channel,
- ah->ah_curchan->channelFlags);
- }
- sc->sc_ani.sc_caldone = iscaldone;
- }
- }
-
- /*
- * Set timer interval based on previous results.
- * The interval must be the shortest necessary to satisfy ANI,
- * short calibration and long calibration.
- */
-
- cal_interval = ATH_ANI_POLLINTERVAL;
- if (!sc->sc_ani.sc_caldone)
- cal_interval = min(cal_interval, (u32)ATH_SHORT_CALINTERVAL);
-
- mod_timer(&sc->sc_ani.timer, jiffies + msecs_to_jiffies(cal_interval));
-}
-
-/******************/
-/* VAP management */
-/******************/
-
-int ath_vap_attach(struct ath_softc *sc,
- int if_id,
- struct ieee80211_vif *if_data,
- enum ath9k_opmode opmode)
-{
- struct ath_vap *avp;
-
- if (if_id >= ATH_BCBUF || sc->sc_vaps[if_id] != NULL) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: Invalid interface id = %u\n", __func__, if_id);
- return -EINVAL;
- }
-
- switch (opmode) {
- case ATH9K_M_STA:
- case ATH9K_M_IBSS:
- case ATH9K_M_MONITOR:
- break;
- case ATH9K_M_HOSTAP:
- /* XXX not right, beacon buffer is allocated on RUN trans */
- if (list_empty(&sc->sc_bbuf))
- return -ENOMEM;
- break;
- default:
- return -EINVAL;
- }
-
- /* create ath_vap */
- avp = kmalloc(sizeof(struct ath_vap), GFP_KERNEL);
- if (avp == NULL)
- return -ENOMEM;
-
- memset(avp, 0, sizeof(struct ath_vap));
- avp->av_if_data = if_data;
- /* Set the VAP opmode */
- avp->av_opmode = opmode;
- avp->av_bslot = -1;
-
- if (opmode == ATH9K_M_HOSTAP)
- ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
-
- sc->sc_vaps[if_id] = avp;
- sc->sc_nvaps++;
- /* Set the device opmode */
- sc->sc_ah->ah_opmode = opmode;
-
- /* default VAP configuration */
- avp->av_config.av_fixed_rateset = IEEE80211_FIXED_RATE_NONE;
- avp->av_config.av_fixed_retryset = 0x03030303;
-
- return 0;
-}
-
-int ath_vap_detach(struct ath_softc *sc, int if_id)
-{
- struct ath_hal *ah = sc->sc_ah;
- struct ath_vap *avp;
-
- avp = sc->sc_vaps[if_id];
- if (avp == NULL) {
- DPRINTF(sc, ATH_DBG_FATAL, "%s: invalid interface id %u\n",
- __func__, if_id);
- return -EINVAL;
- }
-
- /*
- * Quiesce the hardware while we remove the vap. In
- * particular we need to reclaim all references to the
- * vap state by any frames pending on the tx queues.
- *
- * XXX can we do this w/o affecting other vap's?
- */
- ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */
- ath_draintxq(sc, false); /* stop xmit side */
- ath_stoprecv(sc); /* stop recv side */
- ath_flushrecv(sc); /* flush recv queue */
-
- kfree(avp);
- sc->sc_vaps[if_id] = NULL;
- sc->sc_nvaps--;
-
- return 0;
-}
-
-int ath_vap_config(struct ath_softc *sc,
- int if_id, struct ath_vap_config *if_config)
-{
- struct ath_vap *avp;
-
- if (if_id >= ATH_BCBUF) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: Invalid interface id = %u\n", __func__, if_id);
- return -EINVAL;
- }
-
- avp = sc->sc_vaps[if_id];
- ASSERT(avp != NULL);
-
- if (avp)
- memcpy(&avp->av_config, if_config, sizeof(avp->av_config));
-
- return 0;
-}
-
-/********/
-/* Core */
-/********/
-
-int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan)
-{
- struct ath_hal *ah = sc->sc_ah;
- int status;
- int error = 0;
-
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: mode %d\n",
- __func__, sc->sc_ah->ah_opmode);
-
- /*
- * Stop anything previously setup. This is safe
- * whether this is the first time through or not.
- */
- ath_stop(sc);
-
- /* Initialize chanmask selection */
- sc->sc_tx_chainmask = ah->ah_caps.tx_chainmask;
- sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask;
-
- /* Reset SERDES registers */
- ath9k_hw_configpcipowersave(ah, 0);
-
- /*
- * The basic interface to setting the hardware in a good
- * state is ``reset''. On return the hardware is known to
- * be powered up and with interrupts disabled. This must
- * be followed by initialization of the appropriate bits
- * and then setup of the interrupt mask.
- */
-
- spin_lock_bh(&sc->sc_resetlock);
- if (!ath9k_hw_reset(ah, initial_chan,
- sc->sc_ht_info.tx_chan_width,
- sc->sc_tx_chainmask, sc->sc_rx_chainmask,
- sc->sc_ht_extprotspacing, false, &status)) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to reset hardware; hal status %u "
- "(freq %u flags 0x%x)\n", __func__, status,
- initial_chan->channel, initial_chan->channelFlags);
- error = -EIO;
- spin_unlock_bh(&sc->sc_resetlock);
- goto done;
- }
- spin_unlock_bh(&sc->sc_resetlock);
- /*
- * This is needed only to setup initial state
- * but it's best done after a reset.
- */
- ath_update_txpow(sc);
-
- /*
- * Setup the hardware after reset:
- * The receive engine is set going.
- * Frame transmit is handled entirely
- * in the frame output path; there's nothing to do
- * here except setup the interrupt mask.
- */
- if (ath_startrecv(sc) != 0) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to start recv logic\n", __func__);
- error = -EIO;
- goto done;
- }
- /* Setup our intr mask. */
- sc->sc_imask = ATH9K_INT_RX | ATH9K_INT_TX
- | ATH9K_INT_RXEOL | ATH9K_INT_RXORN
- | ATH9K_INT_FATAL | ATH9K_INT_GLOBAL;
-
- if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_GTT)
- sc->sc_imask |= ATH9K_INT_GTT;
-
- if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
- sc->sc_imask |= ATH9K_INT_CST;
-
- /*
- * Enable MIB interrupts when there are hardware phy counters.
- * Note we only do this (at the moment) for station mode.
- */
- if (ath9k_hw_phycounters(ah) &&
- ((sc->sc_ah->ah_opmode == ATH9K_M_STA) ||
- (sc->sc_ah->ah_opmode == ATH9K_M_IBSS)))
- sc->sc_imask |= ATH9K_INT_MIB;
- /*
- * Some hardware processes the TIM IE and fires an
- * interrupt when the TIM bit is set. For hardware
- * that does, if not overridden by configuration,
- * enable the TIM interrupt when operating as station.
- */
- if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) &&
- (sc->sc_ah->ah_opmode == ATH9K_M_STA) &&
- !sc->sc_config.swBeaconProcess)
- sc->sc_imask |= ATH9K_INT_TIM;
- /*
- * Don't enable interrupts here as we've not yet built our
- * vap and node data structures, which will be needed as soon
- * as we start receiving.
- */
- ath_setcurmode(sc, ath_chan2mode(initial_chan));
-
- /* XXX: we must make sure h/w is ready and clear invalid flag
- * before turning on interrupt. */
- sc->sc_flags &= ~SC_OP_INVALID;
-done:
- return error;
-}
-
-int ath_reset(struct ath_softc *sc, bool retry_tx)
-{
- struct ath_hal *ah = sc->sc_ah;
- int status;
- int error = 0;
-
- ath9k_hw_set_interrupts(ah, 0); /* disable interrupts */
- ath_draintxq(sc, retry_tx); /* stop xmit */
- ath_stoprecv(sc); /* stop recv */
- ath_flushrecv(sc); /* flush recv queue */
-
- /* Reset chip */
- spin_lock_bh(&sc->sc_resetlock);
- if (!ath9k_hw_reset(ah, sc->sc_ah->ah_curchan,
- sc->sc_ht_info.tx_chan_width,
- sc->sc_tx_chainmask, sc->sc_rx_chainmask,
- sc->sc_ht_extprotspacing, false, &status)) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to reset hardware; hal status %u\n",
- __func__, status);
- error = -EIO;
- }
- spin_unlock_bh(&sc->sc_resetlock);
-
- if (ath_startrecv(sc) != 0) /* restart recv */
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to start recv logic\n", __func__);
-
- /*
- * We may be doing a reset in response to a request
- * that changes the channel so update any state that
- * might change as a result.
- */
- ath_setcurmode(sc, ath_chan2mode(sc->sc_ah->ah_curchan));
-
- ath_update_txpow(sc);
-
- if (sc->sc_flags & SC_OP_BEACONS)
- ath_beacon_config(sc, ATH_IF_ID_ANY); /* restart beacons */
-
- ath9k_hw_set_interrupts(ah, sc->sc_imask);
-
- /* Restart the txq */
- if (retry_tx) {
- int i;
- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
- if (ATH_TXQ_SETUP(sc, i)) {
- spin_lock_bh(&sc->sc_txq[i].axq_lock);
- ath_txq_schedule(sc, &sc->sc_txq[i]);
- spin_unlock_bh(&sc->sc_txq[i].axq_lock);
- }
- }
- }
-
- return error;
-}
-
-int ath_suspend(struct ath_softc *sc)
-{
- struct ath_hal *ah = sc->sc_ah;
-
- /* No I/O if device has been surprise removed */
- if (sc->sc_flags & SC_OP_INVALID)
- return -EIO;
-
- /* Shut off the interrupt before setting sc->sc_invalid to '1' */
- ath9k_hw_set_interrupts(ah, 0);
-
- /* XXX: we must make sure h/w will not generate any interrupt
- * before setting the invalid flag. */
- sc->sc_flags |= SC_OP_INVALID;
-
- /* disable HAL and put h/w to sleep */
- ath9k_hw_disable(sc->sc_ah);
-
- ath9k_hw_configpcipowersave(sc->sc_ah, 1);
-
- return 0;
-}
-
-/* Interrupt handler. Most of the actual processing is deferred.
- * It's the caller's responsibility to ensure the chip is awake. */
-
-irqreturn_t ath_isr(int irq, void *dev)
-{
- struct ath_softc *sc = dev;
- struct ath_hal *ah = sc->sc_ah;
- enum ath9k_int status;
- bool sched = false;
-
- do {
- if (sc->sc_flags & SC_OP_INVALID) {
- /*
- * The hardware is not ready/present, don't
- * touch anything. Note this can happen early
- * on if the IRQ is shared.
- */
- return IRQ_NONE;
- }
- if (!ath9k_hw_intrpend(ah)) { /* shared irq, not for us */
- return IRQ_NONE;
- }
-
- /*
- * Figure out the reason(s) for the interrupt. Note
- * that the hal returns a pseudo-ISR that may include
- * bits we haven't explicitly enabled so we mask the
- * value to insure we only process bits we requested.
- */
- ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */
-
- status &= sc->sc_imask; /* discard unasked-for bits */
-
- /*
- * If there are no status bits set, then this interrupt was not
- * for me (should have been caught above).
- */
-
- if (!status)
- return IRQ_NONE;
-
- sc->sc_intrstatus = status;
-
- if (status & ATH9K_INT_FATAL) {
- /* need a chip reset */
- sched = true;
- } else if (status & ATH9K_INT_RXORN) {
- /* need a chip reset */
- sched = true;
- } else {
- if (status & ATH9K_INT_SWBA) {
- /* schedule a tasklet for beacon handling */
- tasklet_schedule(&sc->bcon_tasklet);
- }
- if (status & ATH9K_INT_RXEOL) {
- /*
- * NB: the hardware should re-read the link when
- * RXE bit is written, but it doesn't work
- * at least on older hardware revs.
- */
- sched = true;
- }
-
- if (status & ATH9K_INT_TXURN)
- /* bump tx trigger level */
- ath9k_hw_updatetxtriglevel(ah, true);
- /* XXX: optimize this */
- if (status & ATH9K_INT_RX)
- sched = true;
- if (status & ATH9K_INT_TX)
- sched = true;
- if (status & ATH9K_INT_BMISS)
- sched = true;
- /* carrier sense timeout */
- if (status & ATH9K_INT_CST)
- sched = true;
- if (status & ATH9K_INT_MIB) {
- /*
- * Disable interrupts until we service the MIB
- * interrupt; otherwise it will continue to
- * fire.
- */
- ath9k_hw_set_interrupts(ah, 0);
- /*
- * Let the hal handle the event. We assume
- * it will clear whatever condition caused
- * the interrupt.
- */
- ath9k_hw_procmibevent(ah, &sc->sc_halstats);
- ath9k_hw_set_interrupts(ah, sc->sc_imask);
- }
- if (status & ATH9K_INT_TIM_TIMER) {
- if (!(ah->ah_caps.hw_caps &
- ATH9K_HW_CAP_AUTOSLEEP)) {
- /* Clear RxAbort bit so that we can
- * receive frames */
- ath9k_hw_setrxabort(ah, 0);
- sched = true;
- }
- }
- }
- } while (0);
-
- if (sched) {
- /* turn off every interrupt except SWBA */
- ath9k_hw_set_interrupts(ah, (sc->sc_imask & ATH9K_INT_SWBA));
- tasklet_schedule(&sc->intr_tq);
- }
-
- return IRQ_HANDLED;
-}
-
-/* Deferred interrupt processing */
-
-static void ath9k_tasklet(unsigned long data)
-{
- struct ath_softc *sc = (struct ath_softc *)data;
- u32 status = sc->sc_intrstatus;
-
- if (status & ATH9K_INT_FATAL) {
- /* need a chip reset */
- ath_reset(sc, false);
- return;
- } else {
-
- if (status &
- (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) {
- /* XXX: fill me in */
- /*
- if (status & ATH9K_INT_RXORN) {
- }
- if (status & ATH9K_INT_RXEOL) {
- }
- */
- spin_lock_bh(&sc->sc_rxflushlock);
- ath_rx_tasklet(sc, 0);
- spin_unlock_bh(&sc->sc_rxflushlock);
- }
- /* XXX: optimize this */
- if (status & ATH9K_INT_TX)
- ath_tx_tasklet(sc);
- /* XXX: fill me in */
- /*
- if (status & ATH9K_INT_BMISS) {
- }
- if (status & (ATH9K_INT_TIM | ATH9K_INT_DTIMSYNC)) {
- if (status & ATH9K_INT_TIM) {
- }
- if (status & ATH9K_INT_DTIMSYNC) {
- }
- }
- */
- }
-
- /* re-enable hardware interrupt */
- ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask);
-}
-
-int ath_init(u16 devid, struct ath_softc *sc)
-{
- struct ath_hal *ah = NULL;
- int status;
- int error = 0, i;
- int csz = 0;
-
- /* XXX: hardware will not be ready until ath_open() being called */
- sc->sc_flags |= SC_OP_INVALID;
-
- sc->sc_debug = DBG_DEFAULT;
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: devid 0x%x\n", __func__, devid);
-
- /* Initialize tasklet */
- tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
- tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet,
- (unsigned long)sc);
-
- /*
- * Cache line size is used to size and align various
- * structures used to communicate with the hardware.
- */
- bus_read_cachesize(sc, &csz);
- /* XXX assert csz is non-zero */
- sc->sc_cachelsz = csz << 2; /* convert to bytes */
-
- spin_lock_init(&sc->sc_resetlock);
-
- ah = ath9k_hw_attach(devid, sc, sc->mem, &status);
- if (ah == NULL) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to attach hardware; HAL status %u\n",
- __func__, status);
- error = -ENXIO;
- goto bad;
- }
- sc->sc_ah = ah;
-
- /* Initializes the noise floor to a reasonable default value.
- * Later on this will be updated during ANI processing. */
- sc->sc_ani.sc_noise_floor = ATH_DEFAULT_NOISE_FLOOR;
-
- /* Get the hardware key cache size. */
- sc->sc_keymax = ah->ah_caps.keycache_size;
- if (sc->sc_keymax > ATH_KEYMAX) {
- DPRINTF(sc, ATH_DBG_KEYCACHE,
- "%s: Warning, using only %u entries in %u key cache\n",
- __func__, ATH_KEYMAX, sc->sc_keymax);
- sc->sc_keymax = ATH_KEYMAX;
- }
-
- /*
- * Reset the key cache since some parts do not
- * reset the contents on initial power up.
- */
- for (i = 0; i < sc->sc_keymax; i++)
- ath9k_hw_keyreset(ah, (u16) i);
- /*
- * Mark key cache slots associated with global keys
- * as in use. If we knew TKIP was not to be used we
- * could leave the +32, +64, and +32+64 slots free.
- * XXX only for splitmic.
- */
- for (i = 0; i < IEEE80211_WEP_NKID; i++) {
- set_bit(i, sc->sc_keymap);
- set_bit(i + 32, sc->sc_keymap);
- set_bit(i + 64, sc->sc_keymap);
- set_bit(i + 32 + 64, sc->sc_keymap);
- }
- /*
- * Collect the channel list using the default country
- * code and including outdoor channels. The 802.11 layer
- * is resposible for filtering this list based on settings
- * like the phy mode.
- */
- error = ath_setup_channels(sc);
- if (error)
- goto bad;
-
- /* default to STA mode */
- sc->sc_ah->ah_opmode = ATH9K_M_MONITOR;
-
- /* Setup rate tables */
-
- ath_setup_rates(sc, IEEE80211_BAND_2GHZ);
- ath_setup_rates(sc, IEEE80211_BAND_5GHZ);
-
- /* NB: setup here so ath_rate_update is happy */
- ath_setcurmode(sc, ATH9K_MODE_11A);
-
- /*
- * Allocate hardware transmit queues: one queue for
- * beacon frames and one data queue for each QoS
- * priority. Note that the hal handles reseting
- * these queues at the needed time.
- */
- sc->sc_bhalq = ath_beaconq_setup(ah);
- if (sc->sc_bhalq == -1) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to setup a beacon xmit queue\n", __func__);
- error = -EIO;
- goto bad2;
- }
- sc->sc_cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
- if (sc->sc_cabq == NULL) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to setup CAB xmit queue\n", __func__);
- error = -EIO;
- goto bad2;
- }
-
- sc->sc_config.cabqReadytime = ATH_CABQ_READY_TIME;
- ath_cabq_update(sc);
-
- for (i = 0; i < ARRAY_SIZE(sc->sc_haltype2q); i++)
- sc->sc_haltype2q[i] = -1;
-
- /* Setup data queues */
- /* NB: ensure BK queue is the lowest priority h/w queue */
- if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to setup xmit queue for BK traffic\n",
- __func__);
- error = -EIO;
- goto bad2;
- }
-
- if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to setup xmit queue for BE traffic\n",
- __func__);
- error = -EIO;
- goto bad2;
- }
- if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to setup xmit queue for VI traffic\n",
- __func__);
- error = -EIO;
- goto bad2;
- }
- if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to setup xmit queue for VO traffic\n",
- __func__);
- error = -EIO;
- goto bad2;
- }
-
- setup_timer(&sc->sc_ani.timer, ath_ani_calibrate, (unsigned long)sc);
-
- sc->sc_rc = ath_rate_attach(ah);
- if (sc->sc_rc == NULL) {
- error = -EIO;
- goto bad2;
- }
-
- if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
- ATH9K_CIPHER_TKIP, NULL)) {
- /*
- * Whether we should enable h/w TKIP MIC.
- * XXX: if we don't support WME TKIP MIC, then we wouldn't
- * report WMM capable, so it's always safe to turn on
- * TKIP MIC in this case.
- */
- ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC,
- 0, 1, NULL);
- }
-
- /*
- * Check whether the separate key cache entries
- * are required to handle both tx+rx MIC keys.
- * With split mic keys the number of stations is limited
- * to 27 otherwise 59.
- */
- if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
- ATH9K_CIPHER_TKIP, NULL)
- && ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
- ATH9K_CIPHER_MIC, NULL)
- && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT,
- 0, NULL))
- sc->sc_splitmic = 1;
-
- /* turn on mcast key search if possible */
- if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL))
- (void)ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1,
- 1, NULL);
-
- sc->sc_config.txpowlimit = ATH_TXPOWER_MAX;
- sc->sc_config.txpowlimit_override = 0;
-
- /* 11n Capabilities */
- if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) {
- sc->sc_flags |= SC_OP_TXAGGR;
- sc->sc_flags |= SC_OP_RXAGGR;
- }
-
- sc->sc_tx_chainmask = ah->ah_caps.tx_chainmask;
- sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask;
-
- ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL);
- sc->sc_defant = ath9k_hw_getdefantenna(ah);
-
- ath9k_hw_getmac(ah, sc->sc_myaddr);
- if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) {
- ath9k_hw_getbssidmask(ah, sc->sc_bssidmask);
- ATH_SET_VAP_BSSID_MASK(sc->sc_bssidmask);
- ath9k_hw_setbssidmask(ah, sc->sc_bssidmask);
- }
- sc->sc_slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */
-
- /* initialize beacon slots */
- for (i = 0; i < ARRAY_SIZE(sc->sc_bslot); i++)
- sc->sc_bslot[i] = ATH_IF_ID_ANY;
-
- /* save MISC configurations */
- sc->sc_config.swBeaconProcess = 1;
-
-#ifdef CONFIG_SLOW_ANT_DIV
- /* range is 40 - 255, we use something in the middle */
- ath_slow_ant_div_init(&sc->sc_antdiv, sc, 0x127);
-#endif
-
- return 0;
-bad2:
- /* cleanup tx queues */
- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
- if (ATH_TXQ_SETUP(sc, i))
- ath_tx_cleanupq(sc, &sc->sc_txq[i]);
-bad:
- if (ah)
- ath9k_hw_detach(ah);
- return error;
-}
-
-void ath_deinit(struct ath_softc *sc)
-{
- struct ath_hal *ah = sc->sc_ah;
- int i;
-
- DPRINTF(sc, ATH_DBG_CONFIG, "%s\n", __func__);
-
- tasklet_kill(&sc->intr_tq);
- tasklet_kill(&sc->bcon_tasklet);
- ath_stop(sc);
- if (!(sc->sc_flags & SC_OP_INVALID))
- ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
- ath_rate_detach(sc->sc_rc);
- /* cleanup tx queues */
- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
- if (ATH_TXQ_SETUP(sc, i))
- ath_tx_cleanupq(sc, &sc->sc_txq[i]);
- ath9k_hw_detach(ah);
-}
-
-/*******************/
-/* Node Management */
-/*******************/
-
-struct ath_node *ath_node_attach(struct ath_softc *sc, u8 *addr, int if_id)
-{
- struct ath_vap *avp;
- struct ath_node *an;
- DECLARE_MAC_BUF(mac);
-
- avp = sc->sc_vaps[if_id];
- ASSERT(avp != NULL);
-
- /* mac80211 sta_notify callback is from an IRQ context, so no sleep */
- an = kmalloc(sizeof(struct ath_node), GFP_ATOMIC);
- if (an == NULL)
- return NULL;
- memset(an, 0, sizeof(*an));
-
- an->an_sc = sc;
- memcpy(an->an_addr, addr, ETH_ALEN);
- atomic_set(&an->an_refcnt, 1);
-
- /* set up per-node tx/rx state */
- ath_tx_node_init(sc, an);
- ath_rx_node_init(sc, an);
-
- ath_chainmask_sel_init(sc, an);
- ath_chainmask_sel_timerstart(&an->an_chainmask_sel);
- list_add(&an->list, &sc->node_list);
-
- return an;
-}
-
-void ath_node_detach(struct ath_softc *sc, struct ath_node *an, bool bh_flag)
-{
- unsigned long flags;
-
- DECLARE_MAC_BUF(mac);
-
- ath_chainmask_sel_timerstop(&an->an_chainmask_sel);
- an->an_flags |= ATH_NODE_CLEAN;
- ath_tx_node_cleanup(sc, an, bh_flag);
- ath_rx_node_cleanup(sc, an);
-
- ath_tx_node_free(sc, an);
- ath_rx_node_free(sc, an);
-
- spin_lock_irqsave(&sc->node_lock, flags);
-
- list_del(&an->list);
-
- spin_unlock_irqrestore(&sc->node_lock, flags);
-
- kfree(an);
-}
-
-/* Finds a node and increases the refcnt if found */
-
-struct ath_node *ath_node_get(struct ath_softc *sc, u8 *addr)
-{
- struct ath_node *an = NULL, *an_found = NULL;
-
- if (list_empty(&sc->node_list)) /* FIXME */
- goto out;
- list_for_each_entry(an, &sc->node_list, list) {
- if (!compare_ether_addr(an->an_addr, addr)) {
- atomic_inc(&an->an_refcnt);
- an_found = an;
- break;
- }
- }
-out:
- return an_found;
-}
-
-/* Decrements the refcnt and if it drops to zero, detach the node */
-
-void ath_node_put(struct ath_softc *sc, struct ath_node *an, bool bh_flag)
-{
- if (atomic_dec_and_test(&an->an_refcnt))
- ath_node_detach(sc, an, bh_flag);
-}
-
-/* Finds a node, doesn't increment refcnt. Caller must hold sc->node_lock */
-struct ath_node *ath_node_find(struct ath_softc *sc, u8 *addr)
-{
- struct ath_node *an = NULL, *an_found = NULL;
-
- if (list_empty(&sc->node_list))
- return NULL;
-
- list_for_each_entry(an, &sc->node_list, list)
- if (!compare_ether_addr(an->an_addr, addr)) {
- an_found = an;
- break;
- }
-
- return an_found;
-}
-
-/*
- * Set up New Node
- *
- * Setup driver-specific state for a newly associated node. This routine
- * really only applies if compression or XR are enabled, there is no code
- * covering any other cases.
-*/
-
-void ath_newassoc(struct ath_softc *sc,
- struct ath_node *an, int isnew, int isuapsd)
-{
- int tidno;
-
- /* if station reassociates, tear down the aggregation state. */
- if (!isnew) {
- for (tidno = 0; tidno < WME_NUM_TID; tidno++) {
- if (sc->sc_flags & SC_OP_TXAGGR)
- ath_tx_aggr_teardown(sc, an, tidno);
- if (sc->sc_flags & SC_OP_RXAGGR)
- ath_rx_aggr_teardown(sc, an, tidno);
- }
- }
- an->an_flags = 0;
-}
-
-/**************/
-/* Encryption */
-/**************/
-
-void ath_key_reset(struct ath_softc *sc, u16 keyix, int freeslot)
-{
- ath9k_hw_keyreset(sc->sc_ah, keyix);
- if (freeslot)
- clear_bit(keyix, sc->sc_keymap);
-}
-
-int ath_keyset(struct ath_softc *sc,
- u16 keyix,
- struct ath9k_keyval *hk,
- const u8 mac[ETH_ALEN])
-{
- bool status;
-
- status = ath9k_hw_set_keycache_entry(sc->sc_ah,
- keyix, hk, mac, false);
-
- return status != false;
-}
-
-/***********************/
-/* TX Power/Regulatory */
-/***********************/
-
-/*
- * Set Transmit power in HAL
- *
- * This routine makes the actual HAL calls to set the new transmit power
- * limit.
-*/
-
-void ath_update_txpow(struct ath_softc *sc)
-{
- struct ath_hal *ah = sc->sc_ah;
- u32 txpow;
-
- if (sc->sc_curtxpow != sc->sc_config.txpowlimit) {
- ath9k_hw_set_txpowerlimit(ah, sc->sc_config.txpowlimit);
- /* read back in case value is clamped */
- ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow);
- sc->sc_curtxpow = txpow;
- }
-}
-
-/* Return the current country and domain information */
-void ath_get_currentCountry(struct ath_softc *sc,
- struct ath9k_country_entry *ctry)
-{
- ath9k_regd_get_current_country(sc->sc_ah, ctry);
-
- /* If HAL not specific yet, since it is band dependent,
- * use the one we passed in. */
- if (ctry->countryCode == CTRY_DEFAULT) {
- ctry->iso[0] = 0;
- ctry->iso[1] = 0;
- } else if (ctry->iso[0] && ctry->iso[1]) {
- if (!ctry->iso[2]) {
- if (ath_outdoor)
- ctry->iso[2] = 'O';
- else
- ctry->iso[2] = 'I';
- }
- }
-}
-
-/**************************/
-/* Slow Antenna Diversity */
-/**************************/
-
-void ath_slow_ant_div_init(struct ath_antdiv *antdiv,
- struct ath_softc *sc,
- int32_t rssitrig)
-{
- int trig;
-
- /* antdivf_rssitrig can range from 40 - 0xff */
- trig = (rssitrig > 0xff) ? 0xff : rssitrig;
- trig = (rssitrig < 40) ? 40 : rssitrig;
-
- antdiv->antdiv_sc = sc;
- antdiv->antdivf_rssitrig = trig;
-}
-
-void ath_slow_ant_div_start(struct ath_antdiv *antdiv,
- u8 num_antcfg,
- const u8 *bssid)
-{
- antdiv->antdiv_num_antcfg =
- num_antcfg < ATH_ANT_DIV_MAX_CFG ?
- num_antcfg : ATH_ANT_DIV_MAX_CFG;
- antdiv->antdiv_state = ATH_ANT_DIV_IDLE;
- antdiv->antdiv_curcfg = 0;
- antdiv->antdiv_bestcfg = 0;
- antdiv->antdiv_laststatetsf = 0;
-
- memcpy(antdiv->antdiv_bssid, bssid, sizeof(antdiv->antdiv_bssid));
-
- antdiv->antdiv_start = 1;
-}
-
-void ath_slow_ant_div_stop(struct ath_antdiv *antdiv)
-{
- antdiv->antdiv_start = 0;
-}
-
-static int32_t ath_find_max_val(int32_t *val,
- u8 num_val, u8 *max_index)
-{
- u32 MaxVal = *val++;
- u32 cur_index = 0;
-
- *max_index = 0;
- while (++cur_index < num_val) {
- if (*val > MaxVal) {
- MaxVal = *val;
- *max_index = cur_index;
- }
-
- val++;
- }
-
- return MaxVal;
-}
-
-void ath_slow_ant_div(struct ath_antdiv *antdiv,
- struct ieee80211_hdr *hdr,
- struct ath_rx_status *rx_stats)
-{
- struct ath_softc *sc = antdiv->antdiv_sc;
- struct ath_hal *ah = sc->sc_ah;
- u64 curtsf = 0;
- u8 bestcfg, curcfg = antdiv->antdiv_curcfg;
- __le16 fc = hdr->frame_control;
-
- if (antdiv->antdiv_start && ieee80211_is_beacon(fc)
- && !compare_ether_addr(hdr->addr3, antdiv->antdiv_bssid)) {
- antdiv->antdiv_lastbrssi[curcfg] = rx_stats->rs_rssi;
- antdiv->antdiv_lastbtsf[curcfg] = ath9k_hw_gettsf64(sc->sc_ah);
- curtsf = antdiv->antdiv_lastbtsf[curcfg];
- } else {
- return;
- }
-
- switch (antdiv->antdiv_state) {
- case ATH_ANT_DIV_IDLE:
- if ((antdiv->antdiv_lastbrssi[curcfg] <
- antdiv->antdivf_rssitrig)
- && ((curtsf - antdiv->antdiv_laststatetsf) >
- ATH_ANT_DIV_MIN_IDLE_US)) {
-
- curcfg++;
- if (curcfg == antdiv->antdiv_num_antcfg)
- curcfg = 0;
-
- if (!ath9k_hw_select_antconfig(ah, curcfg)) {
- antdiv->antdiv_bestcfg = antdiv->antdiv_curcfg;
- antdiv->antdiv_curcfg = curcfg;
- antdiv->antdiv_laststatetsf = curtsf;
- antdiv->antdiv_state = ATH_ANT_DIV_SCAN;
- }
- }
- break;
-
- case ATH_ANT_DIV_SCAN:
- if ((curtsf - antdiv->antdiv_laststatetsf) <
- ATH_ANT_DIV_MIN_SCAN_US)
- break;
-
- curcfg++;
- if (curcfg == antdiv->antdiv_num_antcfg)
- curcfg = 0;
-
- if (curcfg == antdiv->antdiv_bestcfg) {
- ath_find_max_val(antdiv->antdiv_lastbrssi,
- antdiv->antdiv_num_antcfg, &bestcfg);
- if (!ath9k_hw_select_antconfig(ah, bestcfg)) {
- antdiv->antdiv_bestcfg = bestcfg;
- antdiv->antdiv_curcfg = bestcfg;
- antdiv->antdiv_laststatetsf = curtsf;
- antdiv->antdiv_state = ATH_ANT_DIV_IDLE;
- }
- } else {
- if (!ath9k_hw_select_antconfig(ah, curcfg)) {
- antdiv->antdiv_curcfg = curcfg;
- antdiv->antdiv_laststatetsf = curtsf;
- antdiv->antdiv_state = ATH_ANT_DIV_SCAN;
- }
- }
-
- break;
- }
-}
-
-/***********************/
-/* Descriptor Handling */
-/***********************/
-
-/*
- * Set up DMA descriptors
- *
- * This function will allocate both the DMA descriptor structure, and the
- * buffers it contains. These are used to contain the descriptors used
- * by the system.
-*/
-
-int ath_descdma_setup(struct ath_softc *sc,
- struct ath_descdma *dd,
- struct list_head *head,
- const char *name,
- int nbuf,
- int ndesc)
-{
-#define DS2PHYS(_dd, _ds) \
- ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
-#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
-#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
-
- struct ath_desc *ds;
- struct ath_buf *bf;
- int i, bsize, error;
-
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: %s DMA: %u buffers %u desc/buf\n",
- __func__, name, nbuf, ndesc);
-
- /* ath_desc must be a multiple of DWORDs */
- if ((sizeof(struct ath_desc) % 4) != 0) {
- DPRINTF(sc, ATH_DBG_FATAL, "%s: ath_desc not DWORD aligned\n",
- __func__);
- ASSERT((sizeof(struct ath_desc) % 4) == 0);
- error = -ENOMEM;
- goto fail;
- }
-
- dd->dd_name = name;
- dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc;
-
- /*
- * Need additional DMA memory because we can't use
- * descriptors that cross the 4K page boundary. Assume
- * one skipped descriptor per 4K page.
- */
- if (!(sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) {
- u32 ndesc_skipped =
- ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len);
- u32 dma_len;
-
- while (ndesc_skipped) {
- dma_len = ndesc_skipped * sizeof(struct ath_desc);
- dd->dd_desc_len += dma_len;
-
- ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len);
- };
- }
-
- /* allocate descriptors */
- dd->dd_desc = pci_alloc_consistent(sc->pdev,
- dd->dd_desc_len,
- &dd->dd_desc_paddr);
- if (dd->dd_desc == NULL) {
- error = -ENOMEM;
- goto fail;
- }
- ds = dd->dd_desc;
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: %s DMA map: %p (%u) -> %llx (%u)\n",
- __func__, dd->dd_name, ds, (u32) dd->dd_desc_len,
- ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
-
- /* allocate buffers */
- bsize = sizeof(struct ath_buf) * nbuf;
- bf = kmalloc(bsize, GFP_KERNEL);
- if (bf == NULL) {
- error = -ENOMEM;
- goto fail2;
- }
- memset(bf, 0, bsize);
- dd->dd_bufptr = bf;
-
- INIT_LIST_HEAD(head);
- for (i = 0; i < nbuf; i++, bf++, ds += ndesc) {
- bf->bf_desc = ds;
- bf->bf_daddr = DS2PHYS(dd, ds);
-
- if (!(sc->sc_ah->ah_caps.hw_caps &
- ATH9K_HW_CAP_4KB_SPLITTRANS)) {
- /*
- * Skip descriptor addresses which can cause 4KB
- * boundary crossing (addr + length) with a 32 dword
- * descriptor fetch.
- */
- while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) {
- ASSERT((caddr_t) bf->bf_desc <
- ((caddr_t) dd->dd_desc +
- dd->dd_desc_len));
-
- ds += ndesc;
- bf->bf_desc = ds;
- bf->bf_daddr = DS2PHYS(dd, ds);
- }
- }
- list_add_tail(&bf->list, head);
- }
- return 0;
-fail2:
- pci_free_consistent(sc->pdev,
- dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr);
-fail:
- memset(dd, 0, sizeof(*dd));
- return error;
-#undef ATH_DESC_4KB_BOUND_CHECK
-#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED
-#undef DS2PHYS
-}
-
-/*
- * Cleanup DMA descriptors
- *
- * This function will free the DMA block that was allocated for the descriptor
- * pool. Since this was allocated as one "chunk", it is freed in the same
- * manner.
-*/
-
-void ath_descdma_cleanup(struct ath_softc *sc,
- struct ath_descdma *dd,
- struct list_head *head)
-{
- /* Free memory associated with descriptors */
- pci_free_consistent(sc->pdev,
- dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr);
-
- INIT_LIST_HEAD(head);
- kfree(dd->dd_bufptr);
- memset(dd, 0, sizeof(*dd));
-}
-
-/*************/
-/* Utilities */
-/*************/
-
-int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
-{
- int qnum;
-
- switch (queue) {
- case 0:
- qnum = sc->sc_haltype2q[ATH9K_WME_AC_VO];
- break;
- case 1:
- qnum = sc->sc_haltype2q[ATH9K_WME_AC_VI];
- break;
- case 2:
- qnum = sc->sc_haltype2q[ATH9K_WME_AC_BE];
- break;
- case 3:
- qnum = sc->sc_haltype2q[ATH9K_WME_AC_BK];
- break;
- default:
- qnum = sc->sc_haltype2q[ATH9K_WME_AC_BE];
- break;
- }
-
- return qnum;
-}
-
-int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc)
-{
- int qnum;
-
- switch (queue) {
- case ATH9K_WME_AC_VO:
- qnum = 0;
- break;
- case ATH9K_WME_AC_VI:
- qnum = 1;
- break;
- case ATH9K_WME_AC_BE:
- qnum = 2;
- break;
- case ATH9K_WME_AC_BK:
- qnum = 3;
- break;
- default:
- qnum = -1;
- break;
- }
-
- return qnum;
-}
-
-
-/*
- * Expand time stamp to TSF
- *
- * Extend 15-bit time stamp from rx descriptor to
- * a full 64-bit TSF using the current h/w TSF.
-*/
-
-u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp)
-{
- u64 tsf;
-
- tsf = ath9k_hw_gettsf64(sc->sc_ah);
- if ((tsf & 0x7fff) < rstamp)
- tsf -= 0x8000;
- return (tsf & ~0x7fff) | rstamp;
-}
-
-/*
- * Set Default Antenna
- *
- * Call into the HAL to set the default antenna to use. Not really valid for
- * MIMO technology.
-*/
-
-void ath_setdefantenna(void *context, u32 antenna)
-{
- struct ath_softc *sc = (struct ath_softc *)context;
- struct ath_hal *ah = sc->sc_ah;
-
- /* XXX block beacon interrupts */
- ath9k_hw_setantenna(ah, antenna);
- sc->sc_defant = antenna;
- sc->sc_rxotherant = 0;
-}
-
-/*
- * Set Slot Time
- *
- * This will wake up the chip if required, and set the slot time for the
- * frame (maximum transmit time). Slot time is assumed to be already set
- * in the ATH object member sc_slottime
-*/
-
-void ath_setslottime(struct ath_softc *sc)
-{
- ath9k_hw_setslottime(sc->sc_ah, sc->sc_slottime);
- sc->sc_updateslot = OK;
-}
diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h
index cb3e61e57c4d..4ca2aed236e0 100644
--- a/drivers/net/wireless/ath9k/core.h
+++ b/drivers/net/wireless/ath9k/core.h
@@ -17,27 +17,8 @@
#ifndef CORE_H
#define CORE_H
-#include <linux/version.h>
-#include <linux/autoconf.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <linux/errno.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
#include <linux/etherdevice.h>
-#include <linux/ip.h>
-#include <linux/tcp.h>
-#include <linux/in.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
#include <linux/pci.h>
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/list.h>
-#include <asm/byteorder.h>
-#include <linux/scatterlist.h>
-#include <asm/page.h>
#include <net/mac80211.h>
#include <linux/leds.h>
#include <linux/rfkill.h>
@@ -47,10 +28,6 @@
struct ath_node;
-/******************/
-/* Utility macros */
-/******************/
-
/* Macro to expand scalars to 64-bit objects */
#define ito64(x) (sizeof(x) == 8) ? \
@@ -84,94 +61,125 @@ struct ath_node;
#define TSF_TO_TU(_h,_l) \
((((u32)(_h)) << 22) | (((u32)(_l)) >> 10))
-#define ATH9K_BH_STATUS_INTACT 0
-#define ATH9K_BH_STATUS_CHANGE 1
-
-#define ATH_TXQ_SETUP(sc, i) ((sc)->sc_txqsetup & (1<<i))
-
-static inline unsigned long get_timestamp(void)
-{
- return ((jiffies / HZ) * 1000) + (jiffies % HZ) * (1000 / HZ);
-}
+#define ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<<i))
static const u8 ath_bcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-/*************/
-/* Debugging */
-/*************/
-
enum ATH_DEBUG {
ATH_DBG_RESET = 0x00000001,
- ATH_DBG_PHY_IO = 0x00000002,
- ATH_DBG_REG_IO = 0x00000004,
- ATH_DBG_QUEUE = 0x00000008,
- ATH_DBG_EEPROM = 0x00000010,
- ATH_DBG_NF_CAL = 0x00000020,
- ATH_DBG_CALIBRATE = 0x00000040,
- ATH_DBG_CHANNEL = 0x00000080,
- ATH_DBG_INTERRUPT = 0x00000100,
- ATH_DBG_REGULATORY = 0x00000200,
- ATH_DBG_ANI = 0x00000400,
- ATH_DBG_POWER_MGMT = 0x00000800,
- ATH_DBG_XMIT = 0x00001000,
- ATH_DBG_BEACON = 0x00002000,
- ATH_DBG_RATE = 0x00004000,
- ATH_DBG_CONFIG = 0x00008000,
- ATH_DBG_KEYCACHE = 0x00010000,
- ATH_DBG_AGGR = 0x00020000,
- ATH_DBG_FATAL = 0x00040000,
+ ATH_DBG_REG_IO = 0x00000002,
+ ATH_DBG_QUEUE = 0x00000004,
+ ATH_DBG_EEPROM = 0x00000008,
+ ATH_DBG_CALIBRATE = 0x00000010,
+ ATH_DBG_CHANNEL = 0x00000020,
+ ATH_DBG_INTERRUPT = 0x00000040,
+ ATH_DBG_REGULATORY = 0x00000080,
+ ATH_DBG_ANI = 0x00000100,
+ ATH_DBG_POWER_MGMT = 0x00000200,
+ ATH_DBG_XMIT = 0x00000400,
+ ATH_DBG_BEACON = 0x00001000,
+ ATH_DBG_CONFIG = 0x00002000,
+ ATH_DBG_KEYCACHE = 0x00004000,
+ ATH_DBG_FATAL = 0x00008000,
ATH_DBG_ANY = 0xffffffff
};
#define DBG_DEFAULT (ATH_DBG_FATAL)
-#define DPRINTF(sc, _m, _fmt, ...) do { \
- if (sc->sc_debug & (_m)) \
- printk(_fmt , ##__VA_ARGS__); \
- } while (0)
+#ifdef CONFIG_ATH9K_DEBUG
+
+/**
+ * struct ath_interrupt_stats - Contains statistics about interrupts
+ * @total: Total no. of interrupts generated so far
+ * @rxok: RX with no errors
+ * @rxeol: RX with no more RXDESC available
+ * @rxorn: RX FIFO overrun
+ * @txok: TX completed at the requested rate
+ * @txurn: TX FIFO underrun
+ * @mib: MIB regs reaching its threshold
+ * @rxphyerr: RX with phy errors
+ * @rx_keycache_miss: RX with key cache misses
+ * @swba: Software Beacon Alert
+ * @bmiss: Beacon Miss
+ * @bnr: Beacon Not Ready
+ * @cst: Carrier Sense TImeout
+ * @gtt: Global TX Timeout
+ * @tim: RX beacon TIM occurrence
+ * @cabend: RX End of CAB traffic
+ * @dtimsync: DTIM sync lossage
+ * @dtim: RX Beacon with DTIM
+ */
+struct ath_interrupt_stats {
+ u32 total;
+ u32 rxok;
+ u32 rxeol;
+ u32 rxorn;
+ u32 txok;
+ u32 txeol;
+ u32 txurn;
+ u32 mib;
+ u32 rxphyerr;
+ u32 rx_keycache_miss;
+ u32 swba;
+ u32 bmiss;
+ u32 bnr;
+ u32 cst;
+ u32 gtt;
+ u32 tim;
+ u32 cabend;
+ u32 dtimsync;
+ u32 dtim;
+};
+
+struct ath_stats {
+ struct ath_interrupt_stats istats;
+};
+
+struct ath9k_debug {
+ int debug_mask;
+ struct dentry *debugfs_root;
+ struct dentry *debugfs_phy;
+ struct dentry *debugfs_dma;
+ struct dentry *debugfs_interrupt;
+ struct ath_stats stats;
+};
+
+void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...);
+int ath9k_init_debug(struct ath_softc *sc);
+void ath9k_exit_debug(struct ath_softc *sc);
+void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
+
+#else
+
+static inline void DPRINTF(struct ath_softc *sc, int dbg_mask,
+ const char *fmt, ...)
+{
+}
+
+static inline int ath9k_init_debug(struct ath_softc *sc)
+{
+ return 0;
+}
-/***************************/
-/* Load-time Configuration */
-/***************************/
+static inline void ath9k_exit_debug(struct ath_softc *sc)
+{
+}
+
+static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
+ enum ath9k_int status)
+{
+}
+
+#endif /* CONFIG_ATH9K_DEBUG */
-/* Per-instance load-time (note: NOT run-time) configurations
- * for Atheros Device */
struct ath_config {
u32 ath_aggr_prot;
u16 txpowlimit;
u16 txpowlimit_override;
- u8 cabqReadytime; /* Cabq Readytime % */
- u8 swBeaconProcess; /* Process received beacons in SW (vs HW) */
-};
-
-/***********************/
-/* Chainmask Selection */
-/***********************/
-
-#define ATH_CHAINMASK_SEL_TIMEOUT 6000
-/* Default - Number of last RSSI values that is used for
- * chainmask selection */
-#define ATH_CHAINMASK_SEL_RSSI_CNT 10
-/* Means use 3x3 chainmask instead of configured chainmask */
-#define ATH_CHAINMASK_SEL_3X3 7
-/* Default - Rssi threshold below which we have to switch to 3x3 */
-#define ATH_CHAINMASK_SEL_UP_RSSI_THRES 20
-/* Default - Rssi threshold above which we have to switch to
- * user configured values */
-#define ATH_CHAINMASK_SEL_DOWN_RSSI_THRES 35
-/* Struct to store the chainmask select related info */
-struct ath_chainmask_sel {
- struct timer_list timer;
- int cur_tx_mask; /* user configured or 3x3 */
- int cur_rx_mask; /* user configured or 3x3 */
- int tx_avgrssi;
- u8 switch_allowed:1, /* timer will set this */
- cm_sel_enabled : 1;
+ u8 cabqReadytime;
+ u8 swBeaconProcess;
};
-int ath_chainmask_sel_logic(struct ath_softc *sc, struct ath_node *an);
-void ath_update_chainmask(struct ath_softc *sc, int is_ht);
-
/*************************/
/* Descriptor Management */
/*************************/
@@ -200,15 +208,14 @@ enum buffer_type {
};
struct ath_buf_state {
- int bfs_nframes; /* # frames in aggregate */
- u16 bfs_al; /* length of aggregate */
- u16 bfs_frmlen; /* length of frame */
- int bfs_seqno; /* sequence number */
- int bfs_tidno; /* tid of this frame */
- int bfs_retries; /* current retries */
- struct ath_rc_series bfs_rcs[4]; /* rate series */
- u32 bf_type; /* BUF_* (enum buffer_type) */
- /* key type use to encrypt this frame */
+ int bfs_nframes; /* # frames in aggregate */
+ u16 bfs_al; /* length of aggregate */
+ u16 bfs_frmlen; /* length of frame */
+ int bfs_seqno; /* sequence number */
+ int bfs_tidno; /* tid of this frame */
+ int bfs_retries; /* current retries */
+ u32 bf_type; /* BUF_* (enum buffer_type) */
+ u32 bfs_keyix;
enum ath9k_key_type bfs_keytype;
};
@@ -219,6 +226,7 @@ struct ath_buf_state {
#define bf_seqno bf_state.bfs_seqno
#define bf_tidno bf_state.bfs_tidno
#define bf_rcs bf_state.bfs_rcs
+#define bf_keyix bf_state.bfs_keyix
#define bf_keytype bf_state.bfs_keytype
#define bf_isdata(bf) (bf->bf_state.bf_type & BUF_DATA)
#define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR)
@@ -242,9 +250,7 @@ struct ath_buf {
an aggregate) */
struct ath_buf *bf_lastfrm; /* last buf of this frame */
struct ath_buf *bf_next; /* next subframe in the aggregate */
- struct ath_buf *bf_rifslast; /* last buf for RIFS burst */
void *bf_mpdu; /* enclosing frame structure */
- void *bf_node; /* pointer to the node */
struct ath_desc *bf_desc; /* virtual addr of desc */
dma_addr_t bf_daddr; /* physical addr of desc */
dma_addr_t bf_buf_addr; /* physical addr of data buffer */
@@ -254,13 +260,6 @@ struct ath_buf {
dma_addr_t bf_dmacontext;
};
-/*
- * reset the rx buffer.
- * any new fields added to the athbuf and require
- * reset need to be added to this macro.
- * currently bf_status is the only one requires that
- * requires reset.
- */
#define ATH_RXBUF_RESET(_bf) ((_bf)->bf_status = 0)
/* hw processing complete, desc processed by hal */
@@ -281,159 +280,81 @@ struct ath_descdma {
dma_addr_t dd_dmacontext;
};
-/* Abstraction of a received RX MPDU/MMPDU, or a RX fragment */
-
-struct ath_rx_context {
- struct ath_buf *ctx_rxbuf; /* associated ath_buf for rx */
-};
-#define ATH_RX_CONTEXT(skb) ((struct ath_rx_context *)skb->cb)
-
-int ath_descdma_setup(struct ath_softc *sc,
- struct ath_descdma *dd,
- struct list_head *head,
- const char *name,
- int nbuf,
- int ndesc);
-int ath_desc_alloc(struct ath_softc *sc);
-void ath_desc_free(struct ath_softc *sc);
-void ath_descdma_cleanup(struct ath_softc *sc,
- struct ath_descdma *dd,
+int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
+ struct list_head *head, const char *name,
+ int nbuf, int ndesc);
+void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
struct list_head *head);
-/******/
-/* RX */
-/******/
-
-#define ATH_MAX_ANTENNA 3
-#define ATH_RXBUF 512
-#define ATH_RX_TIMEOUT 40 /* 40 milliseconds */
-#define WME_NUM_TID 16
-#define IEEE80211_BAR_CTL_TID_M 0xF000 /* tid mask */
-#define IEEE80211_BAR_CTL_TID_S 12 /* tid shift */
-
-enum ATH_RX_TYPE {
- ATH_RX_NON_CONSUMED = 0,
- ATH_RX_CONSUMED
-};
-
-/* per frame rx status block */
-struct ath_recv_status {
- u64 tsf; /* mac tsf */
- int8_t rssi; /* RSSI (noise floor ajusted) */
- int8_t rssictl[ATH_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */
- int8_t rssiextn[ATH_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */
- int8_t abs_rssi; /* absolute RSSI */
- u8 rateieee; /* data rate received (IEEE rate code) */
- u8 ratecode; /* phy rate code */
- int rateKbps; /* data rate received (Kbps) */
- int antenna; /* rx antenna */
- int flags; /* status of associated skb */
-#define ATH_RX_FCS_ERROR 0x01
-#define ATH_RX_MIC_ERROR 0x02
-#define ATH_RX_DECRYPT_ERROR 0x04
-#define ATH_RX_RSSI_VALID 0x08
-/* if any of ctl,extn chainrssis are valid */
-#define ATH_RX_CHAIN_RSSI_VALID 0x10
-/* if extn chain rssis are valid */
-#define ATH_RX_RSSI_EXTN_VALID 0x20
-/* set if 40Mhz, clear if 20Mhz */
-#define ATH_RX_40MHZ 0x40
-/* set if short GI, clear if full GI */
-#define ATH_RX_SHORT_GI 0x80
-};
-
-struct ath_rxbuf {
- struct sk_buff *rx_wbuf;
- unsigned long rx_time; /* system time when received */
- struct ath_recv_status rx_status; /* cached rx status */
-};
-
-/* Per-TID aggregate receiver state for a node */
-struct ath_arx_tid {
- struct ath_node *an;
- struct ath_rxbuf *rxbuf; /* re-ordering buffer */
- struct timer_list timer;
- spinlock_t tidlock;
- int baw_head; /* seq_next at head */
- int baw_tail; /* tail of block-ack window */
- int seq_reset; /* need to reset start sequence */
- int addba_exchangecomplete;
- u16 seq_next; /* next expected sequence */
- u16 baw_size; /* block-ack window size */
-};
-
-/* Per-node receiver aggregate state */
-struct ath_arx {
- struct ath_arx_tid tid[WME_NUM_TID];
-};
-
-int ath_startrecv(struct ath_softc *sc);
-bool ath_stoprecv(struct ath_softc *sc);
-void ath_flushrecv(struct ath_softc *sc);
-u32 ath_calcrxfilter(struct ath_softc *sc);
-void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an);
-void ath_rx_node_free(struct ath_softc *sc, struct ath_node *an);
-void ath_rx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
-void ath_handle_rx_intr(struct ath_softc *sc);
-int ath_rx_init(struct ath_softc *sc, int nbufs);
-void ath_rx_cleanup(struct ath_softc *sc);
-int ath_rx_tasklet(struct ath_softc *sc, int flush);
-int ath_rx_input(struct ath_softc *sc,
- struct ath_node *node,
- int is_ampdu,
- struct sk_buff *skb,
- struct ath_recv_status *rx_status,
- enum ATH_RX_TYPE *status);
-int _ath_rx_indicate(struct ath_softc *sc,
- struct sk_buff *skb,
- struct ath_recv_status *status,
- u16 keyix);
-int ath_rx_subframe(struct ath_node *an, struct sk_buff *skb,
- struct ath_recv_status *status);
-
-/******/
-/* TX */
-/******/
+/***********/
+/* RX / TX */
+/***********/
+#define ATH_MAX_ANTENNA 3
+#define ATH_RXBUF 512
+#define WME_NUM_TID 16
#define ATH_TXBUF 512
-/* max number of transmit attempts (tries) */
#define ATH_TXMAXTRY 13
-/* max number of 11n transmit attempts (tries) */
#define ATH_11N_TXMAXTRY 10
-/* max number of tries for management and control frames */
#define ATH_MGT_TXMAXTRY 4
#define WME_BA_BMP_SIZE 64
#define WME_MAX_BA WME_BA_BMP_SIZE
#define ATH_TID_MAX_BUFS (2 * WME_MAX_BA)
+
#define TID_TO_WME_AC(_tid) \
((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \
(((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \
(((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \
WME_AC_VO)
+#define WME_AC_BE 0
+#define WME_AC_BK 1
+#define WME_AC_VI 2
+#define WME_AC_VO 3
+#define WME_NUM_AC 4
+
+#define ADDBA_EXCHANGE_ATTEMPTS 10
+#define ATH_AGGR_DELIM_SZ 4
+#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */
+/* number of delimiters for encryption padding */
+#define ATH_AGGR_ENCRYPTDELIM 10
+/* minimum h/w qdepth to be sustained to maximize aggregation */
+#define ATH_AGGR_MIN_QDEPTH 2
+#define ATH_AMPDU_SUBFRAME_DEFAULT 32
+#define IEEE80211_SEQ_SEQ_SHIFT 4
+#define IEEE80211_SEQ_MAX 4096
+#define IEEE80211_MIN_AMPDU_BUF 0x8
+#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13
+
+/* return whether a bit at index _n in bitmap _bm is set
+ * _sz is the size of the bitmap */
+#define ATH_BA_ISSET(_bm, _n) (((_n) < (WME_BA_BMP_SIZE)) && \
+ ((_bm)[(_n) >> 5] & (1 << ((_n) & 31))))
+
+/* return block-ack bitmap index given sequence and starting sequence */
+#define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1))
+
+/* returns delimiter padding required given the packet length */
+#define ATH_AGGR_GET_NDELIM(_len) \
+ (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \
+ (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
+
+#define BAW_WITHIN(_start, _bawsz, _seqno) \
+ ((((_seqno) - (_start)) & 4095) < (_bawsz))
-/* Wireless Multimedia Extension Defines */
-#define WME_AC_BE 0 /* best effort */
-#define WME_AC_BK 1 /* background */
-#define WME_AC_VI 2 /* video */
-#define WME_AC_VO 3 /* voice */
-#define WME_NUM_AC 4
+#define ATH_DS_BA_SEQ(_ds) ((_ds)->ds_us.tx.ts_seqnum)
+#define ATH_DS_BA_BITMAP(_ds) (&(_ds)->ds_us.tx.ba_low)
+#define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA)
+#define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)])
-enum ATH_SM_PWRSAV{
- ATH_SM_ENABLE,
- ATH_SM_PWRSAV_STATIC,
- ATH_SM_PWRSAV_DYNAMIC,
+enum ATH_AGGR_STATUS {
+ ATH_AGGR_DONE,
+ ATH_AGGR_BAW_CLOSED,
+ ATH_AGGR_LIMITED,
+ ATH_AGGR_SHORTPKT,
+ ATH_AGGR_8K_LIMITED,
};
-/*
- * Data transmit queue state. One of these exists for each
- * hardware transmit queue. Packets sent to us from above
- * are assigned to queues based on their priority. Not all
- * devices support a complete set of hardware transmit queues.
- * For those devices the array sc_ac2q will map multiple
- * priorities to fewer hardware queues (typically all to one
- * hardware queue).
- */
struct ath_txq {
u32 axq_qnum; /* hardware q number */
u32 *axq_link; /* link ptr in last TX desc */
@@ -443,10 +364,6 @@ struct ath_txq {
u32 axq_depth; /* queue depth */
u8 axq_aggr_depth; /* aggregates queued */
u32 axq_totalqueued; /* total ever queued */
-
- /* count to determine if descriptor should generate int on this txq. */
- u32 axq_intrcnt;
-
bool stopped; /* Is mac80211 queue stopped ? */
struct ath_buf *axq_linkbuf; /* virtual addr of last buffer*/
@@ -460,6 +377,10 @@ struct ath_txq {
struct list_head axq_acq;
};
+#define AGGR_CLEANUP BIT(1)
+#define AGGR_ADDBA_COMPLETE BIT(2)
+#define AGGR_ADDBA_PROGRESS BIT(3)
+
/* per TID aggregate tx state for a destination */
struct ath_atx_tid {
struct list_head list; /* round-robin tid entry */
@@ -475,9 +396,7 @@ struct ath_atx_tid {
int baw_tail; /* next unused tx buffer slot */
int sched;
int paused;
- int cleanup_inprogress;
- u32 addba_exchangecomplete:1;
- int32_t addba_exchangeinprogress;
+ u8 state;
int addba_exchangeattempts;
};
@@ -490,32 +409,10 @@ struct ath_atx_ac {
struct list_head tid_q; /* queue of TIDs with buffers */
};
-/* per dest tx state */
-struct ath_atx {
- struct ath_atx_tid tid[WME_NUM_TID];
- struct ath_atx_ac ac[WME_NUM_AC];
-};
-
/* per-frame tx control block */
struct ath_tx_control {
- struct ath_node *an;
+ struct ath_txq *txq;
int if_id;
- int qnum;
- u32 ht:1;
- u32 ps:1;
- u32 use_minrate:1;
- enum ath9k_pkt_type atype;
- enum ath9k_key_type keytype;
- u32 flags;
- u16 seqno;
- u16 tidno;
- u16 txpower;
- u16 frmlen;
- u32 keyix;
- int min_rate;
- int mcast_rate;
- struct ath_softc *dev;
- dma_addr_t dmacontext;
};
/* per frame tx status block */
@@ -528,21 +425,63 @@ struct ath_xmit_status {
#define ATH_TX_BAR 0x04
};
+/* All RSSI values are noise floor adjusted */
struct ath_tx_stat {
- int rssi; /* RSSI (noise floor ajusted) */
- int rssictl[ATH_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */
- int rssiextn[ATH_MAX_ANTENNA]; /* RSSI (noise floor ajusted) */
- int rateieee; /* data rate xmitted (IEEE rate code) */
- int rateKbps; /* data rate xmitted (Kbps) */
- int ratecode; /* phy rate code */
- int flags; /* validity flags */
-/* if any of ctl,extn chain rssis are valid */
-#define ATH_TX_CHAIN_RSSI_VALID 0x01
-/* if extn chain rssis are valid */
-#define ATH_TX_RSSI_EXTN_VALID 0x02
+ int rssi;
+ int rssictl[ATH_MAX_ANTENNA];
+ int rssiextn[ATH_MAX_ANTENNA];
+ int rateieee;
+ int rateKbps;
+ int ratecode;
+ int flags;
u32 airtime; /* time on air per final tx rate */
};
+struct aggr_rifs_param {
+ int param_max_frames;
+ int param_max_len;
+ int param_rl;
+ int param_al;
+ struct ath_rc_series *param_rcs;
+};
+
+struct ath_node {
+ struct ath_softc *an_sc;
+ struct ath_atx_tid tid[WME_NUM_TID];
+ struct ath_atx_ac ac[WME_NUM_AC];
+ u16 maxampdu;
+ u8 mpdudensity;
+};
+
+struct ath_tx {
+ u16 seq_no;
+ u32 txqsetup;
+ int hwq_map[ATH9K_WME_AC_VO+1];
+ spinlock_t txbuflock;
+ struct list_head txbuf;
+ struct ath_txq txq[ATH9K_NUM_TX_QUEUES];
+ struct ath_descdma txdma;
+};
+
+struct ath_rx {
+ u8 defant;
+ u8 rxotherant;
+ u32 *rxlink;
+ int bufsize;
+ unsigned int rxfilter;
+ spinlock_t rxflushlock;
+ spinlock_t rxbuflock;
+ struct list_head rxbuf;
+ struct ath_descdma rxdma;
+};
+
+int ath_startrecv(struct ath_softc *sc);
+bool ath_stoprecv(struct ath_softc *sc);
+void ath_flushrecv(struct ath_softc *sc);
+u32 ath_calcrxfilter(struct ath_softc *sc);
+int ath_rx_init(struct ath_softc *sc, int nbufs);
+void ath_rx_cleanup(struct ath_softc *sc);
+int ath_rx_tasklet(struct ath_softc *sc, int flush);
struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype);
void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq);
int ath_tx_setup(struct ath_softc *sc, int haltype);
@@ -550,139 +489,51 @@ void ath_draintxq(struct ath_softc *sc, bool retry_tx);
void ath_tx_draintxq(struct ath_softc *sc,
struct ath_txq *txq, bool retry_tx);
void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an);
-void ath_tx_node_cleanup(struct ath_softc *sc,
- struct ath_node *an, bool bh_flag);
+void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an);
void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an);
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq);
int ath_tx_init(struct ath_softc *sc, int nbufs);
int ath_tx_cleanup(struct ath_softc *sc);
int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype);
+struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb);
int ath_txq_update(struct ath_softc *sc, int qnum,
struct ath9k_tx_queue_info *q);
-int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb);
+int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb,
+ struct ath_tx_control *txctl);
void ath_tx_tasklet(struct ath_softc *sc);
u32 ath_txq_depth(struct ath_softc *sc, int qnum);
u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum);
-void ath_notify_txq_status(struct ath_softc *sc, u16 queue_depth);
-void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
- struct ath_xmit_status *tx_status, struct ath_node *an);
void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb);
+void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid);
+bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);
+void ath_tx_aggr_teardown(struct ath_softc *sc, struct ath_node *an, u8 tidno);
+int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
+ u16 tid, u16 *ssn);
+int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
+void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
-/**********************/
-/* Node / Aggregation */
-/**********************/
-
-/* indicates the node is clened up */
-#define ATH_NODE_CLEAN 0x1
-/* indicates the node is 80211 power save */
-#define ATH_NODE_PWRSAVE 0x2
-
-#define ADDBA_EXCHANGE_ATTEMPTS 10
-#define ATH_AGGR_DELIM_SZ 4 /* delimiter size */
-#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */
-/* number of delimiters for encryption padding */
-#define ATH_AGGR_ENCRYPTDELIM 10
-/* minimum h/w qdepth to be sustained to maximize aggregation */
-#define ATH_AGGR_MIN_QDEPTH 2
-#define ATH_AMPDU_SUBFRAME_DEFAULT 32
-#define IEEE80211_SEQ_SEQ_SHIFT 4
-#define IEEE80211_SEQ_MAX 4096
-#define IEEE80211_MIN_AMPDU_BUF 0x8
-
-/* return whether a bit at index _n in bitmap _bm is set
- * _sz is the size of the bitmap */
-#define ATH_BA_ISSET(_bm, _n) (((_n) < (WME_BA_BMP_SIZE)) && \
- ((_bm)[(_n) >> 5] & (1 << ((_n) & 31))))
-
-/* return block-ack bitmap index given sequence and starting sequence */
-#define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1))
-
-/* returns delimiter padding required given the packet length */
-#define ATH_AGGR_GET_NDELIM(_len) \
- (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \
- (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
-
-#define BAW_WITHIN(_start, _bawsz, _seqno) \
- ((((_seqno) - (_start)) & 4095) < (_bawsz))
-
-#define ATH_DS_BA_SEQ(_ds) ((_ds)->ds_us.tx.ts_seqnum)
-#define ATH_DS_BA_BITMAP(_ds) (&(_ds)->ds_us.tx.ba_low)
-#define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA)
-#define ATH_AN_2_TID(_an, _tidno) (&(_an)->an_aggr.tx.tid[(_tidno)])
-
-enum ATH_AGGR_STATUS {
- ATH_AGGR_DONE,
- ATH_AGGR_BAW_CLOSED,
- ATH_AGGR_LIMITED,
- ATH_AGGR_SHORTPKT,
- ATH_AGGR_8K_LIMITED,
-};
-
-enum ATH_AGGR_CHECK {
- AGGR_NOT_REQUIRED,
- AGGR_REQUIRED,
- AGGR_CLEANUP_PROGRESS,
- AGGR_EXCHANGE_PROGRESS,
- AGGR_EXCHANGE_DONE
-};
+/********/
+/* VAPs */
+/********/
-struct aggr_rifs_param {
- int param_max_frames;
- int param_max_len;
- int param_rl;
- int param_al;
- struct ath_rc_series *param_rcs;
-};
+/*
+ * Define the scheme that we select MAC address for multiple
+ * BSS on the same radio. The very first VAP will just use the MAC
+ * address from the EEPROM. For the next 3 VAPs, we set the
+ * U/L bit (bit 1) in MAC address, and use the next two bits as the
+ * index of the VAP.
+ */
-/* Per-node aggregation state */
-struct ath_node_aggr {
- struct ath_atx tx; /* node transmit state */
- struct ath_arx rx; /* node receive state */
-};
+#define ATH_SET_VAP_BSSID_MASK(bssid_mask) \
+ ((bssid_mask)[0] &= ~(((ATH_BCBUF-1)<<2)|0x02))
-/* driver-specific node state */
-struct ath_node {
- struct list_head list;
- struct ath_softc *an_sc;
- atomic_t an_refcnt;
- struct ath_chainmask_sel an_chainmask_sel;
- struct ath_node_aggr an_aggr;
- u8 an_smmode; /* SM Power save mode */
- u8 an_flags;
- u8 an_addr[ETH_ALEN];
+struct ath_vap {
+ int av_bslot;
+ enum nl80211_iftype av_opmode;
+ struct ath_buf *av_bcbuf;
+ struct ath_tx_control av_btxctl;
};
-void ath_tx_resume_tid(struct ath_softc *sc,
- struct ath_atx_tid *tid);
-enum ATH_AGGR_CHECK ath_tx_aggr_check(struct ath_softc *sc,
- struct ath_node *an, u8 tidno);
-void ath_tx_aggr_teardown(struct ath_softc *sc,
- struct ath_node *an, u8 tidno);
-void ath_rx_aggr_teardown(struct ath_softc *sc,
- struct ath_node *an, u8 tidno);
-int ath_rx_aggr_start(struct ath_softc *sc,
- const u8 *addr,
- u16 tid,
- u16 *ssn);
-int ath_rx_aggr_stop(struct ath_softc *sc,
- const u8 *addr,
- u16 tid);
-int ath_tx_aggr_start(struct ath_softc *sc,
- const u8 *addr,
- u16 tid,
- u16 *ssn);
-int ath_tx_aggr_stop(struct ath_softc *sc,
- const u8 *addr,
- u16 tid);
-void ath_newassoc(struct ath_softc *sc,
- struct ath_node *node, int isnew, int isuapsd);
-struct ath_node *ath_node_attach(struct ath_softc *sc,
- u8 addr[ETH_ALEN], int if_id);
-void ath_node_detach(struct ath_softc *sc, struct ath_node *an, bool bh_flag);
-struct ath_node *ath_node_get(struct ath_softc *sc, u8 addr[ETH_ALEN]);
-void ath_node_put(struct ath_softc *sc, struct ath_node *an, bool bh_flag);
-struct ath_node *ath_node_find(struct ath_softc *sc, u8 *addr);
-
/*******************/
/* Beacon Handling */
/*******************/
@@ -693,12 +544,11 @@ struct ath_node *ath_node_find(struct ath_softc *sc, u8 *addr);
* number of beacon intervals, the game's up.
*/
#define BSTUCK_THRESH (9 * ATH_BCBUF)
-#define ATH_BCBUF 4 /* number of beacon buffers */
-#define ATH_DEFAULT_BINTVAL 100 /* default beacon interval in TU */
+#define ATH_BCBUF 1
+#define ATH_DEFAULT_BINTVAL 100 /* TU */
#define ATH_DEFAULT_BMISS_LIMIT 10
#define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024)
-/* beacon configuration */
struct ath_beacon_config {
u16 beacon_interval;
u16 listen_interval;
@@ -712,93 +562,32 @@ struct ath_beacon_config {
} u; /* last received beacon/probe response timestamp of this BSS. */
};
+struct ath_beacon {
+ enum {
+ OK, /* no change needed */
+ UPDATE, /* update pending */
+ COMMIT /* beacon sent, commit change */
+ } updateslot; /* slot time update fsm */
+
+ u32 beaconq;
+ u32 bmisscnt;
+ u32 ast_be_xmit;
+ u64 bc_tstamp;
+ int bslot[ATH_BCBUF];
+ int slottime;
+ int slotupdate;
+ struct ath9k_tx_queue_info beacon_qi;
+ struct ath_descdma bdma;
+ struct ath_txq *cabq;
+ struct list_head bbuf;
+};
+
void ath9k_beacon_tasklet(unsigned long data);
void ath_beacon_config(struct ath_softc *sc, int if_id);
int ath_beaconq_setup(struct ath_hal *ah);
int ath_beacon_alloc(struct ath_softc *sc, int if_id);
-void ath_bstuck_process(struct ath_softc *sc);
void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp);
void ath_beacon_sync(struct ath_softc *sc, int if_id);
-void ath_get_beaconconfig(struct ath_softc *sc,
- int if_id,
- struct ath_beacon_config *conf);
-/********/
-/* VAPs */
-/********/
-
-/*
- * Define the scheme that we select MAC address for multiple
- * BSS on the same radio. The very first VAP will just use the MAC
- * address from the EEPROM. For the next 3 VAPs, we set the
- * U/L bit (bit 1) in MAC address, and use the next two bits as the
- * index of the VAP.
- */
-
-#define ATH_SET_VAP_BSSID_MASK(bssid_mask) \
- ((bssid_mask)[0] &= ~(((ATH_BCBUF-1)<<2)|0x02))
-
-/* VAP configuration (from protocol layer) */
-struct ath_vap_config {
- u32 av_fixed_rateset;
- u32 av_fixed_retryset;
-};
-
-/* driver-specific vap state */
-struct ath_vap {
- struct ieee80211_vif *av_if_data;
- enum ath9k_opmode av_opmode; /* VAP operational mode */
- struct ath_buf *av_bcbuf; /* beacon buffer */
- struct ath_tx_control av_btxctl; /* txctl information for beacon */
- int av_bslot; /* beacon slot index */
- struct ath_vap_config av_config;/* vap configuration parameters*/
- struct ath_rate_node *rc_node;
-};
-
-int ath_vap_attach(struct ath_softc *sc,
- int if_id,
- struct ieee80211_vif *if_data,
- enum ath9k_opmode opmode);
-int ath_vap_detach(struct ath_softc *sc, int if_id);
-int ath_vap_config(struct ath_softc *sc,
- int if_id, struct ath_vap_config *if_config);
-
-/*********************/
-/* Antenna diversity */
-/*********************/
-
-#define ATH_ANT_DIV_MAX_CFG 2
-#define ATH_ANT_DIV_MIN_IDLE_US 1000000 /* us */
-#define ATH_ANT_DIV_MIN_SCAN_US 50000 /* us */
-
-enum ATH_ANT_DIV_STATE{
- ATH_ANT_DIV_IDLE,
- ATH_ANT_DIV_SCAN, /* evaluating antenna */
-};
-
-struct ath_antdiv {
- struct ath_softc *antdiv_sc;
- u8 antdiv_start;
- enum ATH_ANT_DIV_STATE antdiv_state;
- u8 antdiv_num_antcfg;
- u8 antdiv_curcfg;
- u8 antdiv_bestcfg;
- int32_t antdivf_rssitrig;
- int32_t antdiv_lastbrssi[ATH_ANT_DIV_MAX_CFG];
- u64 antdiv_lastbtsf[ATH_ANT_DIV_MAX_CFG];
- u64 antdiv_laststatetsf;
- u8 antdiv_bssid[ETH_ALEN];
-};
-
-void ath_slow_ant_div_init(struct ath_antdiv *antdiv,
- struct ath_softc *sc, int32_t rssitrig);
-void ath_slow_ant_div_start(struct ath_antdiv *antdiv,
- u8 num_antcfg,
- const u8 *bssid);
-void ath_slow_ant_div_stop(struct ath_antdiv *antdiv);
-void ath_slow_ant_div(struct ath_antdiv *antdiv,
- struct ieee80211_hdr *wh,
- struct ath_rx_status *rx_stats);
-void ath_setdefantenna(void *sc, u32 antenna);
/*******/
/* ANI */
@@ -863,7 +652,7 @@ struct ath_rfkill {
#define DEFAULT_CACHELINE 32
#define ATH_DEFAULT_NOISE_FLOOR -95
#define ATH_REGCLASSIDS_MAX 10
-#define ATH_CABQ_READY_TIME 80 /* % of beacon interval */
+#define ATH_CABQ_READY_TIME 80 /* % of beacon interval */
#define ATH_MAX_SW_RETRIES 10
#define ATH_CHAN_MAX 255
#define IEEE80211_WEP_NKID 4 /* number of key ids */
@@ -876,34 +665,12 @@ struct ath_rfkill {
* Different parts have different size key caches. We handle
* up to ATH_KEYMAX entries (could dynamically allocate state).
*/
-#define ATH_KEYMAX 128 /* max key cache size we handle */
+#define ATH_KEYMAX 128 /* max key cache size we handle */
#define ATH_IF_ID_ANY 0xff
#define ATH_TXPOWER_MAX 100 /* .5 dBm units */
-
-#define RSSI_LPF_THRESHOLD -20
-#define ATH_RSSI_EP_MULTIPLIER (1<<7) /* pow2 to optimize out * and / */
-#define ATH_RATE_DUMMY_MARKER 0
-#define ATH_RSSI_LPF_LEN 10
-#define ATH_RSSI_DUMMY_MARKER 0x127
-
-#define ATH_EP_MUL(x, mul) ((x) * (mul))
-#define ATH_EP_RND(x, mul) \
- ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul))
-#define ATH_RSSI_OUT(x) \
- (((x) != ATH_RSSI_DUMMY_MARKER) ? \
- (ATH_EP_RND((x), ATH_RSSI_EP_MULTIPLIER)) : ATH_RSSI_DUMMY_MARKER)
-#define ATH_RSSI_IN(x) \
- (ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER))
-#define ATH_LPF_RSSI(x, y, len) \
- ((x != ATH_RSSI_DUMMY_MARKER) ? \
- (((x) * ((len) - 1) + (y)) / (len)) : (y))
-#define ATH_RSSI_LPF(x, y) do { \
- if ((y) >= RSSI_LPF_THRESHOLD) \
- x = ATH_LPF_RSSI((x), \
- ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \
- } while (0)
-
+#define ATH_RSSI_DUMMY_MARKER 0x127
+#define ATH_RATE_DUMMY_MARKER 0
enum PROT_MODE {
PROT_M_NONE = 0,
@@ -911,19 +678,6 @@ enum PROT_MODE {
PROT_M_CTSONLY
};
-enum RATE_TYPE {
- NORMAL_RATE = 0,
- HALF_RATE,
- QUARTER_RATE
-};
-
-struct ath_ht_info {
- enum ath9k_ht_macmode tx_chan_width;
- u16 maxampdu;
- u8 mpdudensity;
- u8 ext_chan_offset;
-};
-
#define SC_OP_INVALID BIT(0)
#define SC_OP_BEACONS BIT(1)
#define SC_OP_RXAGGR BIT(2)
@@ -944,141 +698,57 @@ struct ath_softc {
struct pci_dev *pdev;
struct tasklet_struct intr_tq;
struct tasklet_struct bcon_tasklet;
- struct ath_config sc_config;
struct ath_hal *sc_ah;
- struct ath_rate_softc *sc_rc;
void __iomem *mem;
+ spinlock_t sc_resetlock;
+ struct mutex mutex;
u8 sc_curbssid[ETH_ALEN];
u8 sc_myaddr[ETH_ALEN];
u8 sc_bssidmask[ETH_ALEN];
-
- int sc_debug;
u32 sc_intrstatus;
u32 sc_flags; /* SC_OP_* */
- unsigned int rx_filter;
u16 sc_curtxpow;
u16 sc_curaid;
u16 sc_cachelsz;
- int sc_slotupdate; /* slot to next advance fsm */
- int sc_slottime;
- int sc_bslot[ATH_BCBUF];
+ u8 sc_nbcnvaps;
+ u16 sc_nvaps;
u8 sc_tx_chainmask;
u8 sc_rx_chainmask;
+ u32 sc_keymax;
+ DECLARE_BITMAP(sc_keymap, ATH_KEYMAX);
+ u8 sc_splitmic;
+ u8 sc_protrix;
enum ath9k_int sc_imask;
- enum wireless_mode sc_curmode; /* current phy mode */
enum PROT_MODE sc_protmode;
-
- u8 sc_nbcnvaps; /* # of vaps sending beacons */
- u16 sc_nvaps; /* # of active virtual ap's */
- struct ath_vap *sc_vaps[ATH_BCBUF];
-
- u8 sc_mcastantenna;
- u8 sc_defant; /* current default antenna */
- u8 sc_rxotherant; /* rx's on non-default antenna */
-
- struct ath9k_node_stats sc_halstats; /* station-mode rssi stats */
- struct list_head node_list;
- struct ath_ht_info sc_ht_info;
enum ath9k_ht_extprotspacing sc_ht_extprotspacing;
+ enum ath9k_ht_macmode tx_chan_width;
-#ifdef CONFIG_SLOW_ANT_DIV
- struct ath_antdiv sc_antdiv;
-#endif
- enum {
- OK, /* no change needed */
- UPDATE, /* update pending */
- COMMIT /* beacon sent, commit change */
- } sc_updateslot; /* slot time update fsm */
-
- /* Crypto */
- u32 sc_keymax; /* size of key cache */
- DECLARE_BITMAP(sc_keymap, ATH_KEYMAX); /* key use bit map */
- u8 sc_splitmic; /* split TKIP MIC keys */
-
- /* RX */
- struct list_head sc_rxbuf;
- struct ath_descdma sc_rxdma;
- int sc_rxbufsize; /* rx size based on mtu */
- u32 *sc_rxlink; /* link ptr in last RX desc */
-
- /* TX */
- struct list_head sc_txbuf;
- struct ath_txq sc_txq[ATH9K_NUM_TX_QUEUES];
- struct ath_descdma sc_txdma;
- u32 sc_txqsetup;
- u32 sc_txintrperiod; /* tx interrupt batching */
- int sc_haltype2q[ATH9K_WME_AC_VO+1]; /* HAL WME AC -> h/w qnum */
- u16 seq_no; /* TX sequence number */
-
- /* Beacon */
- struct ath9k_tx_queue_info sc_beacon_qi;
- struct ath_descdma sc_bdma;
- struct ath_txq *sc_cabq;
- struct list_head sc_bbuf;
- u32 sc_bhalq;
- u32 sc_bmisscount;
- u32 ast_be_xmit; /* beacons transmitted */
- u64 bc_tstamp;
-
- /* Rate */
+ struct ath_config sc_config;
+ struct ath_rx rx;
+ struct ath_tx tx;
+ struct ath_beacon beacon;
+ struct ieee80211_vif *sc_vaps[ATH_BCBUF];
struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX];
- const struct ath9k_rate_table *sc_currates;
- u8 sc_rixmap[256]; /* IEEE to h/w rate table ix */
- u8 sc_protrix; /* protection rate index */
- struct {
- u32 rateKbps; /* transfer rate in kbs */
- u8 ieeerate; /* IEEE rate */
- } sc_hwmap[256]; /* h/w rate ix mappings */
-
- /* Channel, Band */
+ struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX];
+ struct ath_rate_table *cur_rate_table;
struct ieee80211_channel channels[IEEE80211_NUM_BANDS][ATH_CHAN_MAX];
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
-
- /* Locks */
- spinlock_t sc_rxflushlock;
- spinlock_t sc_rxbuflock;
- spinlock_t sc_txbuflock;
- spinlock_t sc_resetlock;
- spinlock_t node_lock;
-
- /* LEDs */
struct ath_led radio_led;
struct ath_led assoc_led;
struct ath_led tx_led;
struct ath_led rx_led;
-
- /* Rfkill */
struct ath_rfkill rf_kill;
-
- /* ANI */
struct ath_ani sc_ani;
+ struct ath9k_node_stats sc_halstats;
+#ifdef CONFIG_ATH9K_DEBUG
+ struct ath9k_debug sc_debug;
+#endif
};
-int ath_init(u16 devid, struct ath_softc *sc);
-void ath_deinit(struct ath_softc *sc);
-int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan);
-int ath_suspend(struct ath_softc *sc);
-irqreturn_t ath_isr(int irq, void *dev);
int ath_reset(struct ath_softc *sc, bool retry_tx);
-int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan);
-
-/*********************/
-/* Utility Functions */
-/*********************/
-
-void ath_key_reset(struct ath_softc *sc, u16 keyix, int freeslot);
-int ath_keyset(struct ath_softc *sc,
- u16 keyix,
- struct ath9k_keyval *hk,
- const u8 mac[ETH_ALEN]);
int ath_get_hal_qnum(u16 queue, struct ath_softc *sc);
int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc);
-void ath_setslottime(struct ath_softc *sc);
-void ath_update_txpow(struct ath_softc *sc);
int ath_cabq_update(struct ath_softc *);
-void ath_get_currentCountry(struct ath_softc *sc,
- struct ath9k_country_entry *ctry);
-u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp);
#endif /* CORE_H */
diff --git a/drivers/net/wireless/ath9k/debug.c b/drivers/net/wireless/ath9k/debug.c
new file mode 100644
index 000000000000..a80ed576830f
--- /dev/null
+++ b/drivers/net/wireless/ath9k/debug.c
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "core.h"
+#include "reg.h"
+#include "hw.h"
+
+static unsigned int ath9k_debug = DBG_DEFAULT;
+module_param_named(debug, ath9k_debug, uint, 0);
+
+void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...)
+{
+ if (!sc)
+ return;
+
+ if (sc->sc_debug.debug_mask & dbg_mask) {
+ va_list args;
+
+ va_start(args, fmt);
+ printk(KERN_DEBUG "ath9k: ");
+ vprintk(fmt, args);
+ va_end(args);
+ }
+}
+
+static int ath9k_debugfs_open(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t read_file_dma(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_softc *sc = file->private_data;
+ struct ath_hal *ah = sc->sc_ah;
+ char buf[1024];
+ unsigned int len = 0;
+ u32 val[ATH9K_NUM_DMA_DEBUG_REGS];
+ int i, qcuOffset = 0, dcuOffset = 0;
+ u32 *qcuBase = &val[0], *dcuBase = &val[4];
+
+ REG_WRITE(ah, AR_MACMISC,
+ ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
+ (AR_MACMISC_MISC_OBS_BUS_1 <<
+ AR_MACMISC_MISC_OBS_BUS_MSB_S)));
+
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "Raw DMA Debug values:\n");
+
+ for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) {
+ if (i % 4 == 0)
+ len += snprintf(buf + len, sizeof(buf) - len, "\n");
+
+ val[i] = REG_READ(ah, AR_DMADBG_0 + (i * sizeof(u32)));
+ len += snprintf(buf + len, sizeof(buf) - len, "%d: %08x ",
+ i, val[i]);
+ }
+
+ len += snprintf(buf + len, sizeof(buf) - len, "\n\n");
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
+
+ for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) {
+ if (i == 8) {
+ qcuOffset = 0;
+ qcuBase++;
+ }
+
+ if (i == 6) {
+ dcuOffset = 0;
+ dcuBase++;
+ }
+
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%2d %2x %1x %2x %2x\n",
+ i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
+ (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
+ val[2] & (0x7 << (i * 3)) >> (i * 3),
+ (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
+ }
+
+ len += snprintf(buf + len, sizeof(buf) - len, "\n");
+
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "qcu_stitch state: %2x qcu_fetch state: %2x\n",
+ (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "qcu_complete state: %2x dcu_complete state: %2x\n",
+ (val[3] & 0x1c000000) >> 26, (val[6] & 0x3));
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "dcu_arb state: %2x dcu_fp state: %2x\n",
+ (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n",
+ (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "txfifo_valid_0: %1d txfifo_valid_1: %1d\n",
+ (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n",
+ (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
+
+ len += snprintf(buf + len, sizeof(buf) - len, "pcu observe: 0x%x \n",
+ REG_READ(ah, AR_OBS_BUS_1));
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "AR_CR: 0x%x \n", REG_READ(ah, AR_CR));
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_dma = {
+ .read = read_file_dma,
+ .open = ath9k_debugfs_open,
+ .owner = THIS_MODULE
+};
+
+
+void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status)
+{
+ if (status)
+ sc->sc_debug.stats.istats.total++;
+ if (status & ATH9K_INT_RX)
+ sc->sc_debug.stats.istats.rxok++;
+ if (status & ATH9K_INT_RXEOL)
+ sc->sc_debug.stats.istats.rxeol++;
+ if (status & ATH9K_INT_RXORN)
+ sc->sc_debug.stats.istats.rxorn++;
+ if (status & ATH9K_INT_TX)
+ sc->sc_debug.stats.istats.txok++;
+ if (status & ATH9K_INT_TXURN)
+ sc->sc_debug.stats.istats.txurn++;
+ if (status & ATH9K_INT_MIB)
+ sc->sc_debug.stats.istats.mib++;
+ if (status & ATH9K_INT_RXPHY)
+ sc->sc_debug.stats.istats.rxphyerr++;
+ if (status & ATH9K_INT_RXKCM)
+ sc->sc_debug.stats.istats.rx_keycache_miss++;
+ if (status & ATH9K_INT_SWBA)
+ sc->sc_debug.stats.istats.swba++;
+ if (status & ATH9K_INT_BMISS)
+ sc->sc_debug.stats.istats.bmiss++;
+ if (status & ATH9K_INT_BNR)
+ sc->sc_debug.stats.istats.bnr++;
+ if (status & ATH9K_INT_CST)
+ sc->sc_debug.stats.istats.cst++;
+ if (status & ATH9K_INT_GTT)
+ sc->sc_debug.stats.istats.gtt++;
+ if (status & ATH9K_INT_TIM)
+ sc->sc_debug.stats.istats.tim++;
+ if (status & ATH9K_INT_CABEND)
+ sc->sc_debug.stats.istats.cabend++;
+ if (status & ATH9K_INT_DTIMSYNC)
+ sc->sc_debug.stats.istats.dtimsync++;
+ if (status & ATH9K_INT_DTIM)
+ sc->sc_debug.stats.istats.dtim++;
+}
+
+static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_softc *sc = file->private_data;
+ char buf[512];
+ unsigned int len = 0;
+
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%8s: %10u\n", "RX", sc->sc_debug.stats.istats.rxok);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%8s: %10u\n", "RXEOL", sc->sc_debug.stats.istats.rxeol);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%8s: %10u\n", "RXORN", sc->sc_debug.stats.istats.rxorn);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%8s: %10u\n", "TX", sc->sc_debug.stats.istats.txok);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%8s: %10u\n", "TXURN", sc->sc_debug.stats.istats.txurn);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%8s: %10u\n", "MIB", sc->sc_debug.stats.istats.mib);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%8s: %10u\n", "RXPHY", sc->sc_debug.stats.istats.rxphyerr);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%8s: %10u\n", "RXKCM", sc->sc_debug.stats.istats.rx_keycache_miss);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%8s: %10u\n", "SWBA", sc->sc_debug.stats.istats.swba);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%8s: %10u\n", "BMISS", sc->sc_debug.stats.istats.bmiss);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%8s: %10u\n", "BNR", sc->sc_debug.stats.istats.bnr);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%8s: %10u\n", "CST", sc->sc_debug.stats.istats.cst);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%8s: %10u\n", "GTT", sc->sc_debug.stats.istats.gtt);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%8s: %10u\n", "TIM", sc->sc_debug.stats.istats.tim);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%8s: %10u\n", "CABEND", sc->sc_debug.stats.istats.cabend);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%8s: %10u\n", "DTIMSYNC", sc->sc_debug.stats.istats.dtimsync);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%8s: %10u\n", "DTIM", sc->sc_debug.stats.istats.dtim);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%8s: %10u\n", "TOTAL", sc->sc_debug.stats.istats.total);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_interrupt = {
+ .read = read_file_interrupt,
+ .open = ath9k_debugfs_open,
+ .owner = THIS_MODULE
+};
+
+int ath9k_init_debug(struct ath_softc *sc)
+{
+ sc->sc_debug.debug_mask = ath9k_debug;
+
+ sc->sc_debug.debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
+ if (!sc->sc_debug.debugfs_root)
+ goto err;
+
+ sc->sc_debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy),
+ sc->sc_debug.debugfs_root);
+ if (!sc->sc_debug.debugfs_phy)
+ goto err;
+
+ sc->sc_debug.debugfs_dma = debugfs_create_file("dma", S_IRUGO,
+ sc->sc_debug.debugfs_phy, sc, &fops_dma);
+ if (!sc->sc_debug.debugfs_dma)
+ goto err;
+
+ sc->sc_debug.debugfs_interrupt = debugfs_create_file("interrupt",
+ S_IRUGO,
+ sc->sc_debug.debugfs_phy,
+ sc, &fops_interrupt);
+ if (!sc->sc_debug.debugfs_interrupt)
+ goto err;
+
+ return 0;
+err:
+ ath9k_exit_debug(sc);
+ return -ENOMEM;
+}
+
+void ath9k_exit_debug(struct ath_softc *sc)
+{
+ debugfs_remove(sc->sc_debug.debugfs_interrupt);
+ debugfs_remove(sc->sc_debug.debugfs_dma);
+ debugfs_remove(sc->sc_debug.debugfs_phy);
+ debugfs_remove(sc->sc_debug.debugfs_root);
+}
diff --git a/drivers/net/wireless/ath9k/eeprom.c b/drivers/net/wireless/ath9k/eeprom.c
new file mode 100644
index 000000000000..acd6c5374d44
--- /dev/null
+++ b/drivers/net/wireless/ath9k/eeprom.c
@@ -0,0 +1,2824 @@
+/*
+ * Copyright (c) 2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "core.h"
+#include "hw.h"
+#include "reg.h"
+#include "phy.h"
+
+static void ath9k_hw_analog_shift_rmw(struct ath_hal *ah,
+ u32 reg, u32 mask,
+ u32 shift, u32 val)
+{
+ u32 regVal;
+
+ regVal = REG_READ(ah, reg) & ~mask;
+ regVal |= (val << shift) & mask;
+
+ REG_WRITE(ah, reg, regVal);
+
+ if (ah->ah_config.analog_shiftreg)
+ udelay(100);
+
+ return;
+}
+
+static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz)
+{
+
+ if (fbin == AR5416_BCHAN_UNUSED)
+ return fbin;
+
+ return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
+}
+
+static inline int16_t ath9k_hw_interpolate(u16 target,
+ u16 srcLeft, u16 srcRight,
+ int16_t targetLeft,
+ int16_t targetRight)
+{
+ int16_t rv;
+
+ if (srcRight == srcLeft) {
+ rv = targetLeft;
+ } else {
+ rv = (int16_t) (((target - srcLeft) * targetRight +
+ (srcRight - target) * targetLeft) /
+ (srcRight - srcLeft));
+ }
+ return rv;
+}
+
+static inline bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList,
+ u16 listSize, u16 *indexL,
+ u16 *indexR)
+{
+ u16 i;
+
+ if (target <= pList[0]) {
+ *indexL = *indexR = 0;
+ return true;
+ }
+ if (target >= pList[listSize - 1]) {
+ *indexL = *indexR = (u16) (listSize - 1);
+ return true;
+ }
+
+ for (i = 0; i < listSize - 1; i++) {
+ if (pList[i] == target) {
+ *indexL = *indexR = i;
+ return true;
+ }
+ if (target < pList[i + 1]) {
+ *indexL = i;
+ *indexR = (u16) (i + 1);
+ return false;
+ }
+ }
+ return false;
+}
+
+static bool ath9k_hw_eeprom_read(struct ath_hal *ah, u32 off, u16 *data)
+{
+ (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
+
+ if (!ath9k_hw_wait(ah,
+ AR_EEPROM_STATUS_DATA,
+ AR_EEPROM_STATUS_DATA_BUSY |
+ AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) {
+ return false;
+ }
+
+ *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
+ AR_EEPROM_STATUS_DATA_VAL);
+
+ return true;
+}
+
+static int ath9k_hw_flash_map(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ ahp->ah_cal_mem = ioremap(AR5416_EEPROM_START_ADDR, AR5416_EEPROM_MAX);
+
+ if (!ahp->ah_cal_mem) {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "cannot remap eeprom region \n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static bool ath9k_hw_flash_read(struct ath_hal *ah, u32 off, u16 *data)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ *data = ioread16(ahp->ah_cal_mem + off);
+
+ return true;
+}
+
+static inline bool ath9k_hw_nvram_read(struct ath_hal *ah, u32 off, u16 *data)
+{
+ if (ath9k_hw_use_flash(ah))
+ return ath9k_hw_flash_read(ah, off, data);
+ else
+ return ath9k_hw_eeprom_read(ah, off, data);
+}
+
+static bool ath9k_hw_fill_4k_eeprom(struct ath_hal *ah)
+{
+#define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
+ u16 *eep_data;
+ int addr, eep_start_loc = 0;
+
+ eep_start_loc = 64;
+
+ if (!ath9k_hw_use_flash(ah)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "Reading from EEPROM, not flash\n");
+ }
+
+ eep_data = (u16 *)eep;
+
+ for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
+ if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "Unable to read eeprom region \n");
+ return false;
+ }
+ eep_data++;
+ }
+ return true;
+#undef SIZE_EEPROM_4K
+}
+
+static bool ath9k_hw_fill_def_eeprom(struct ath_hal *ah)
+{
+#define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16))
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
+ u16 *eep_data;
+ int addr, ar5416_eep_start_loc = 0x100;
+
+ eep_data = (u16 *)eep;
+
+ for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) {
+ if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc,
+ eep_data)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "Unable to read eeprom region\n");
+ return false;
+ }
+ eep_data++;
+ }
+ return true;
+#undef SIZE_EEPROM_DEF
+}
+
+static bool (*ath9k_fill_eeprom[]) (struct ath_hal *) = {
+ ath9k_hw_fill_def_eeprom,
+ ath9k_hw_fill_4k_eeprom
+};
+
+static inline bool ath9k_hw_fill_eeprom(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ return ath9k_fill_eeprom[ahp->ah_eep_map](ah);
+}
+
+static int ath9k_hw_check_def_eeprom(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_def *eep =
+ (struct ar5416_eeprom_def *) &ahp->ah_eeprom.def;
+ u16 *eepdata, temp, magic, magic2;
+ u32 sum = 0, el;
+ bool need_swap = false;
+ int i, addr, size;
+
+ if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
+ &magic)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "Reading Magic # failed\n");
+ return false;
+ }
+
+ if (!ath9k_hw_use_flash(ah)) {
+
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "Read Magic = 0x%04X\n", magic);
+
+ if (magic != AR5416_EEPROM_MAGIC) {
+ magic2 = swab16(magic);
+
+ if (magic2 == AR5416_EEPROM_MAGIC) {
+ size = sizeof(struct ar5416_eeprom_def);
+ need_swap = true;
+ eepdata = (u16 *) (&ahp->ah_eeprom);
+
+ for (addr = 0; addr < size / sizeof(u16); addr++) {
+ temp = swab16(*eepdata);
+ *eepdata = temp;
+ eepdata++;
+
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "0x%04X ", *eepdata);
+
+ if (((addr + 1) % 6) == 0)
+ DPRINTF(ah->ah_sc,
+ ATH_DBG_EEPROM, "\n");
+ }
+ } else {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "Invalid EEPROM Magic. "
+ "endianness mismatch.\n");
+ return -EINVAL;
+ }
+ }
+ }
+
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
+ need_swap ? "True" : "False");
+
+ if (need_swap)
+ el = swab16(ahp->ah_eeprom.def.baseEepHeader.length);
+ else
+ el = ahp->ah_eeprom.def.baseEepHeader.length;
+
+ if (el > sizeof(struct ar5416_eeprom_def))
+ el = sizeof(struct ar5416_eeprom_def) / sizeof(u16);
+ else
+ el = el / sizeof(u16);
+
+ eepdata = (u16 *)(&ahp->ah_eeprom);
+
+ for (i = 0; i < el; i++)
+ sum ^= *eepdata++;
+
+ if (need_swap) {
+ u32 integer, j;
+ u16 word;
+
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "EEPROM Endianness is not native.. Changing \n");
+
+ word = swab16(eep->baseEepHeader.length);
+ eep->baseEepHeader.length = word;
+
+ word = swab16(eep->baseEepHeader.checksum);
+ eep->baseEepHeader.checksum = word;
+
+ word = swab16(eep->baseEepHeader.version);
+ eep->baseEepHeader.version = word;
+
+ word = swab16(eep->baseEepHeader.regDmn[0]);
+ eep->baseEepHeader.regDmn[0] = word;
+
+ word = swab16(eep->baseEepHeader.regDmn[1]);
+ eep->baseEepHeader.regDmn[1] = word;
+
+ word = swab16(eep->baseEepHeader.rfSilent);
+ eep->baseEepHeader.rfSilent = word;
+
+ word = swab16(eep->baseEepHeader.blueToothOptions);
+ eep->baseEepHeader.blueToothOptions = word;
+
+ word = swab16(eep->baseEepHeader.deviceCap);
+ eep->baseEepHeader.deviceCap = word;
+
+ for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
+ struct modal_eep_header *pModal =
+ &eep->modalHeader[j];
+ integer = swab32(pModal->antCtrlCommon);
+ pModal->antCtrlCommon = integer;
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ integer = swab32(pModal->antCtrlChain[i]);
+ pModal->antCtrlChain[i] = integer;
+ }
+
+ for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
+ word = swab16(pModal->spurChans[i].spurChan);
+ pModal->spurChans[i].spurChan = word;
+ }
+ }
+ }
+
+ if (sum != 0xffff || ar5416_get_eep_ver(ahp) != AR5416_EEP_VER ||
+ ar5416_get_eep_rev(ahp) < AR5416_EEP_NO_BACK_VER) {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
+ sum, ar5416_get_eep_ver(ahp));
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int ath9k_hw_check_4k_eeprom(struct ath_hal *ah)
+{
+#define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16))
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_4k *eep =
+ (struct ar5416_eeprom_4k *) &ahp->ah_eeprom.map4k;
+ u16 *eepdata, temp, magic, magic2;
+ u32 sum = 0, el;
+ bool need_swap = false;
+ int i, addr;
+
+
+ if (!ath9k_hw_use_flash(ah)) {
+
+ if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
+ &magic)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "Reading Magic # failed\n");
+ return false;
+ }
+
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "Read Magic = 0x%04X\n", magic);
+
+ if (magic != AR5416_EEPROM_MAGIC) {
+ magic2 = swab16(magic);
+
+ if (magic2 == AR5416_EEPROM_MAGIC) {
+ need_swap = true;
+ eepdata = (u16 *) (&ahp->ah_eeprom);
+
+ for (addr = 0; addr < EEPROM_4K_SIZE; addr++) {
+ temp = swab16(*eepdata);
+ *eepdata = temp;
+ eepdata++;
+
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "0x%04X ", *eepdata);
+
+ if (((addr + 1) % 6) == 0)
+ DPRINTF(ah->ah_sc,
+ ATH_DBG_EEPROM, "\n");
+ }
+ } else {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "Invalid EEPROM Magic. "
+ "endianness mismatch.\n");
+ return -EINVAL;
+ }
+ }
+ }
+
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
+ need_swap ? "True" : "False");
+
+ if (need_swap)
+ el = swab16(ahp->ah_eeprom.map4k.baseEepHeader.length);
+ else
+ el = ahp->ah_eeprom.map4k.baseEepHeader.length;
+
+ if (el > sizeof(struct ar5416_eeprom_def))
+ el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16);
+ else
+ el = el / sizeof(u16);
+
+ eepdata = (u16 *)(&ahp->ah_eeprom);
+
+ for (i = 0; i < el; i++)
+ sum ^= *eepdata++;
+
+ if (need_swap) {
+ u32 integer;
+ u16 word;
+
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "EEPROM Endianness is not native.. Changing \n");
+
+ word = swab16(eep->baseEepHeader.length);
+ eep->baseEepHeader.length = word;
+
+ word = swab16(eep->baseEepHeader.checksum);
+ eep->baseEepHeader.checksum = word;
+
+ word = swab16(eep->baseEepHeader.version);
+ eep->baseEepHeader.version = word;
+
+ word = swab16(eep->baseEepHeader.regDmn[0]);
+ eep->baseEepHeader.regDmn[0] = word;
+
+ word = swab16(eep->baseEepHeader.regDmn[1]);
+ eep->baseEepHeader.regDmn[1] = word;
+
+ word = swab16(eep->baseEepHeader.rfSilent);
+ eep->baseEepHeader.rfSilent = word;
+
+ word = swab16(eep->baseEepHeader.blueToothOptions);
+ eep->baseEepHeader.blueToothOptions = word;
+
+ word = swab16(eep->baseEepHeader.deviceCap);
+ eep->baseEepHeader.deviceCap = word;
+
+ integer = swab32(eep->modalHeader.antCtrlCommon);
+ eep->modalHeader.antCtrlCommon = integer;
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ integer = swab32(eep->modalHeader.antCtrlChain[i]);
+ eep->modalHeader.antCtrlChain[i] = integer;
+ }
+
+ for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
+ word = swab16(eep->modalHeader.spurChans[i].spurChan);
+ eep->modalHeader.spurChans[i].spurChan = word;
+ }
+ }
+
+ if (sum != 0xffff || ar5416_get_eep4k_ver(ahp) != AR5416_EEP_VER ||
+ ar5416_get_eep4k_rev(ahp) < AR5416_EEP_NO_BACK_VER) {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
+ sum, ar5416_get_eep4k_ver(ahp));
+ return -EINVAL;
+ }
+
+ return 0;
+#undef EEPROM_4K_SIZE
+}
+
+static int (*ath9k_check_eeprom[]) (struct ath_hal *) = {
+ ath9k_hw_check_def_eeprom,
+ ath9k_hw_check_4k_eeprom
+};
+
+static inline int ath9k_hw_check_eeprom(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ return ath9k_check_eeprom[ahp->ah_eep_map](ah);
+}
+
+static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
+ u8 *pVpdList, u16 numIntercepts,
+ u8 *pRetVpdList)
+{
+ u16 i, k;
+ u8 currPwr = pwrMin;
+ u16 idxL = 0, idxR = 0;
+
+ for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
+ ath9k_hw_get_lower_upper_index(currPwr, pPwrList,
+ numIntercepts, &(idxL),
+ &(idxR));
+ if (idxR < 1)
+ idxR = 1;
+ if (idxL == numIntercepts - 1)
+ idxL = (u16) (numIntercepts - 2);
+ if (pPwrList[idxL] == pPwrList[idxR])
+ k = pVpdList[idxL];
+ else
+ k = (u16)(((currPwr - pPwrList[idxL]) * pVpdList[idxR] +
+ (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
+ (pPwrList[idxR] - pPwrList[idxL]));
+ pRetVpdList[i] = (u8) k;
+ currPwr += 2;
+ }
+
+ return true;
+}
+
+static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ struct cal_data_per_freq_4k *pRawDataSet,
+ u8 *bChans, u16 availPiers,
+ u16 tPdGainOverlap, int16_t *pMinCalPower,
+ u16 *pPdGainBoundaries, u8 *pPDADCValues,
+ u16 numXpdGains)
+{
+#define TMP_VAL_VPD_TABLE \
+ ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep));
+ int i, j, k;
+ int16_t ss;
+ u16 idxL = 0, idxR = 0, numPiers;
+ static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+ static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+ static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+
+ u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
+ u8 minPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
+ u8 maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS];
+ int16_t vpdStep;
+ int16_t tmpVal;
+ u16 sizeCurrVpdTable, maxIndex, tgtIndex;
+ bool match;
+ int16_t minDelta = 0;
+ struct chan_centers centers;
+#define PD_GAIN_BOUNDARY_DEFAULT 58;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ for (numPiers = 0; numPiers < availPiers; numPiers++) {
+ if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
+ break;
+ }
+
+ match = ath9k_hw_get_lower_upper_index(
+ (u8)FREQ2FBIN(centers.synth_center,
+ IS_CHAN_2GHZ(chan)), bChans, numPiers,
+ &idxL, &idxR);
+
+ if (match) {
+ for (i = 0; i < numXpdGains; i++) {
+ minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
+ maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
+ ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pRawDataSet[idxL].pwrPdg[i],
+ pRawDataSet[idxL].vpdPdg[i],
+ AR5416_EEP4K_PD_GAIN_ICEPTS,
+ vpdTableI[i]);
+ }
+ } else {
+ for (i = 0; i < numXpdGains; i++) {
+ pVpdL = pRawDataSet[idxL].vpdPdg[i];
+ pPwrL = pRawDataSet[idxL].pwrPdg[i];
+ pVpdR = pRawDataSet[idxR].vpdPdg[i];
+ pPwrR = pRawDataSet[idxR].pwrPdg[i];
+
+ minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
+
+ maxPwrT4[i] =
+ min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1],
+ pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]);
+
+
+ ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pPwrL, pVpdL,
+ AR5416_EEP4K_PD_GAIN_ICEPTS,
+ vpdTableL[i]);
+ ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pPwrR, pVpdR,
+ AR5416_EEP4K_PD_GAIN_ICEPTS,
+ vpdTableR[i]);
+
+ for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
+ vpdTableI[i][j] =
+ (u8)(ath9k_hw_interpolate((u16)
+ FREQ2FBIN(centers.
+ synth_center,
+ IS_CHAN_2GHZ
+ (chan)),
+ bChans[idxL], bChans[idxR],
+ vpdTableL[i][j], vpdTableR[i][j]));
+ }
+ }
+ }
+
+ *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
+
+ k = 0;
+
+ for (i = 0; i < numXpdGains; i++) {
+ if (i == (numXpdGains - 1))
+ pPdGainBoundaries[i] =
+ (u16)(maxPwrT4[i] / 2);
+ else
+ pPdGainBoundaries[i] =
+ (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
+
+ pPdGainBoundaries[i] =
+ min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
+
+ if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah)) {
+ minDelta = pPdGainBoundaries[0] - 23;
+ pPdGainBoundaries[0] = 23;
+ } else {
+ minDelta = 0;
+ }
+
+ if (i == 0) {
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ ss = (int16_t)(0 - (minPwrT4[i] / 2));
+ else
+ ss = 0;
+ } else {
+ ss = (int16_t)((pPdGainBoundaries[i - 1] -
+ (minPwrT4[i] / 2)) -
+ tPdGainOverlap + 1 + minDelta);
+ }
+ vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
+ vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+ while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+ tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
+ pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
+ ss++;
+ }
+
+ sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
+ tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
+ (minPwrT4[i] / 2));
+ maxIndex = (tgtIndex < sizeCurrVpdTable) ?
+ tgtIndex : sizeCurrVpdTable;
+
+ while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1)))
+ pPDADCValues[k++] = vpdTableI[i][ss++];
+
+ vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
+ vpdTableI[i][sizeCurrVpdTable - 2]);
+ vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+ if (tgtIndex > maxIndex) {
+ while ((ss <= tgtIndex) &&
+ (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+ tmpVal = (int16_t) TMP_VAL_VPD_TABLE;
+ pPDADCValues[k++] = (u8)((tmpVal > 255) ?
+ 255 : tmpVal);
+ ss++;
+ }
+ }
+ }
+
+ while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) {
+ pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT;
+ i++;
+ }
+
+ while (k < AR5416_NUM_PDADC_VALUES) {
+ pPDADCValues[k] = pPDADCValues[k - 1];
+ k++;
+ }
+
+ return;
+#undef TMP_VAL_VPD_TABLE
+}
+
+static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ struct cal_data_per_freq *pRawDataSet,
+ u8 *bChans, u16 availPiers,
+ u16 tPdGainOverlap, int16_t *pMinCalPower,
+ u16 *pPdGainBoundaries, u8 *pPDADCValues,
+ u16 numXpdGains)
+{
+ int i, j, k;
+ int16_t ss;
+ u16 idxL = 0, idxR = 0, numPiers;
+ static u8 vpdTableL[AR5416_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+ static u8 vpdTableR[AR5416_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+ static u8 vpdTableI[AR5416_NUM_PD_GAINS]
+ [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
+
+ u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
+ u8 minPwrT4[AR5416_NUM_PD_GAINS];
+ u8 maxPwrT4[AR5416_NUM_PD_GAINS];
+ int16_t vpdStep;
+ int16_t tmpVal;
+ u16 sizeCurrVpdTable, maxIndex, tgtIndex;
+ bool match;
+ int16_t minDelta = 0;
+ struct chan_centers centers;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ for (numPiers = 0; numPiers < availPiers; numPiers++) {
+ if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
+ break;
+ }
+
+ match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
+ IS_CHAN_2GHZ(chan)),
+ bChans, numPiers, &idxL, &idxR);
+
+ if (match) {
+ for (i = 0; i < numXpdGains; i++) {
+ minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
+ maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
+ ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pRawDataSet[idxL].pwrPdg[i],
+ pRawDataSet[idxL].vpdPdg[i],
+ AR5416_PD_GAIN_ICEPTS,
+ vpdTableI[i]);
+ }
+ } else {
+ for (i = 0; i < numXpdGains; i++) {
+ pVpdL = pRawDataSet[idxL].vpdPdg[i];
+ pPwrL = pRawDataSet[idxL].pwrPdg[i];
+ pVpdR = pRawDataSet[idxR].vpdPdg[i];
+ pPwrR = pRawDataSet[idxR].pwrPdg[i];
+
+ minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
+
+ maxPwrT4[i] =
+ min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1],
+ pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
+
+
+ ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pPwrL, pVpdL,
+ AR5416_PD_GAIN_ICEPTS,
+ vpdTableL[i]);
+ ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
+ pPwrR, pVpdR,
+ AR5416_PD_GAIN_ICEPTS,
+ vpdTableR[i]);
+
+ for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
+ vpdTableI[i][j] =
+ (u8)(ath9k_hw_interpolate((u16)
+ FREQ2FBIN(centers.
+ synth_center,
+ IS_CHAN_2GHZ
+ (chan)),
+ bChans[idxL], bChans[idxR],
+ vpdTableL[i][j], vpdTableR[i][j]));
+ }
+ }
+ }
+
+ *pMinCalPower = (int16_t)(minPwrT4[0] / 2);
+
+ k = 0;
+
+ for (i = 0; i < numXpdGains; i++) {
+ if (i == (numXpdGains - 1))
+ pPdGainBoundaries[i] =
+ (u16)(maxPwrT4[i] / 2);
+ else
+ pPdGainBoundaries[i] =
+ (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
+
+ pPdGainBoundaries[i] =
+ min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]);
+
+ if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah)) {
+ minDelta = pPdGainBoundaries[0] - 23;
+ pPdGainBoundaries[0] = 23;
+ } else {
+ minDelta = 0;
+ }
+
+ if (i == 0) {
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ ss = (int16_t)(0 - (minPwrT4[i] / 2));
+ else
+ ss = 0;
+ } else {
+ ss = (int16_t)((pPdGainBoundaries[i - 1] -
+ (minPwrT4[i] / 2)) -
+ tPdGainOverlap + 1 + minDelta);
+ }
+ vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
+ vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+ while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+ tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
+ pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
+ ss++;
+ }
+
+ sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
+ tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
+ (minPwrT4[i] / 2));
+ maxIndex = (tgtIndex < sizeCurrVpdTable) ?
+ tgtIndex : sizeCurrVpdTable;
+
+ while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+ pPDADCValues[k++] = vpdTableI[i][ss++];
+ }
+
+ vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
+ vpdTableI[i][sizeCurrVpdTable - 2]);
+ vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
+
+ if (tgtIndex > maxIndex) {
+ while ((ss <= tgtIndex) &&
+ (k < (AR5416_NUM_PDADC_VALUES - 1))) {
+ tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
+ (ss - maxIndex + 1) * vpdStep));
+ pPDADCValues[k++] = (u8)((tmpVal > 255) ?
+ 255 : tmpVal);
+ ss++;
+ }
+ }
+ }
+
+ while (i < AR5416_PD_GAINS_IN_MASK) {
+ pPdGainBoundaries[i] = pPdGainBoundaries[i - 1];
+ i++;
+ }
+
+ while (k < AR5416_NUM_PDADC_VALUES) {
+ pPDADCValues[k] = pPDADCValues[k - 1];
+ k++;
+ }
+
+ return;
+}
+
+static void ath9k_hw_get_legacy_target_powers(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ struct cal_target_power_leg *powInfo,
+ u16 numChannels,
+ struct cal_target_power_leg *pNewPower,
+ u16 numRates, bool isExtTarget)
+{
+ struct chan_centers centers;
+ u16 clo, chi;
+ int i;
+ int matchIndex = -1, lowIndex = -1;
+ u16 freq;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+ freq = (isExtTarget) ? centers.ext_center : centers.ctl_center;
+
+ if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel,
+ IS_CHAN_2GHZ(chan))) {
+ matchIndex = 0;
+ } else {
+ for (i = 0; (i < numChannels) &&
+ (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+ if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
+ IS_CHAN_2GHZ(chan))) {
+ matchIndex = i;
+ break;
+ } else if ((freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
+ IS_CHAN_2GHZ(chan))) &&
+ (freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
+ IS_CHAN_2GHZ(chan)))) {
+ lowIndex = i - 1;
+ break;
+ }
+ }
+ if ((matchIndex == -1) && (lowIndex == -1))
+ matchIndex = i - 1;
+ }
+
+ if (matchIndex != -1) {
+ *pNewPower = powInfo[matchIndex];
+ } else {
+ clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
+ IS_CHAN_2GHZ(chan));
+ chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
+ IS_CHAN_2GHZ(chan));
+
+ for (i = 0; i < numRates; i++) {
+ pNewPower->tPow2x[i] =
+ (u8)ath9k_hw_interpolate(freq, clo, chi,
+ powInfo[lowIndex].tPow2x[i],
+ powInfo[lowIndex + 1].tPow2x[i]);
+ }
+ }
+}
+
+static void ath9k_hw_get_target_powers(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ struct cal_target_power_ht *powInfo,
+ u16 numChannels,
+ struct cal_target_power_ht *pNewPower,
+ u16 numRates, bool isHt40Target)
+{
+ struct chan_centers centers;
+ u16 clo, chi;
+ int i;
+ int matchIndex = -1, lowIndex = -1;
+ u16 freq;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+ freq = isHt40Target ? centers.synth_center : centers.ctl_center;
+
+ if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
+ matchIndex = 0;
+ } else {
+ for (i = 0; (i < numChannels) &&
+ (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+ if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
+ IS_CHAN_2GHZ(chan))) {
+ matchIndex = i;
+ break;
+ } else
+ if ((freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
+ IS_CHAN_2GHZ(chan))) &&
+ (freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
+ IS_CHAN_2GHZ(chan)))) {
+ lowIndex = i - 1;
+ break;
+ }
+ }
+ if ((matchIndex == -1) && (lowIndex == -1))
+ matchIndex = i - 1;
+ }
+
+ if (matchIndex != -1) {
+ *pNewPower = powInfo[matchIndex];
+ } else {
+ clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
+ IS_CHAN_2GHZ(chan));
+ chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
+ IS_CHAN_2GHZ(chan));
+
+ for (i = 0; i < numRates; i++) {
+ pNewPower->tPow2x[i] = (u8)ath9k_hw_interpolate(freq,
+ clo, chi,
+ powInfo[lowIndex].tPow2x[i],
+ powInfo[lowIndex + 1].tPow2x[i]);
+ }
+ }
+}
+
+static u16 ath9k_hw_get_max_edge_power(u16 freq,
+ struct cal_ctl_edges *pRdEdgesPower,
+ bool is2GHz, int num_band_edges)
+{
+ u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+ int i;
+
+ for (i = 0; (i < num_band_edges) &&
+ (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
+ if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) {
+ twiceMaxEdgePower = pRdEdgesPower[i].tPower;
+ break;
+ } else if ((i > 0) &&
+ (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
+ is2GHz))) {
+ if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel,
+ is2GHz) < freq &&
+ pRdEdgesPower[i - 1].flag) {
+ twiceMaxEdgePower =
+ pRdEdgesPower[i - 1].tPower;
+ }
+ break;
+ }
+ }
+
+ return twiceMaxEdgePower;
+}
+
+static bool ath9k_hw_set_def_power_cal_table(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ int16_t *pTxPowerIndexOffset)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_def *pEepData = &ahp->ah_eeprom.def;
+ struct cal_data_per_freq *pRawDataset;
+ u8 *pCalBChans = NULL;
+ u16 pdGainOverlap_t2;
+ static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
+ u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
+ u16 numPiers, i, j;
+ int16_t tMinCalPower;
+ u16 numXpdGain, xpdMask;
+ u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
+ u32 reg32, regOffset, regChainOffset;
+ int16_t modalIdx;
+
+ modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
+ xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
+
+ if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ pdGainOverlap_t2 =
+ pEepData->modalHeader[modalIdx].pdGainOverlap;
+ } else {
+ pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
+ }
+
+ if (IS_CHAN_2GHZ(chan)) {
+ pCalBChans = pEepData->calFreqPier2G;
+ numPiers = AR5416_NUM_2G_CAL_PIERS;
+ } else {
+ pCalBChans = pEepData->calFreqPier5G;
+ numPiers = AR5416_NUM_5G_CAL_PIERS;
+ }
+
+ numXpdGain = 0;
+
+ for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
+ if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
+ if (numXpdGain >= AR5416_NUM_PD_GAINS)
+ break;
+ xpdGainValues[numXpdGain] =
+ (u16)(AR5416_PD_GAINS_IN_MASK - i);
+ numXpdGain++;
+ }
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+ (numXpdGain - 1) & 0x3);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
+ xpdGainValues[0]);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
+ xpdGainValues[1]);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
+ xpdGainValues[2]);
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ if (AR_SREV_5416_V20_OR_LATER(ah) &&
+ (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5) &&
+ (i != 0)) {
+ regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+ } else
+ regChainOffset = i * 0x1000;
+
+ if (pEepData->baseEepHeader.txMask & (1 << i)) {
+ if (IS_CHAN_2GHZ(chan))
+ pRawDataset = pEepData->calPierData2G[i];
+ else
+ pRawDataset = pEepData->calPierData5G[i];
+
+ ath9k_hw_get_def_gain_boundaries_pdadcs(ah, chan,
+ pRawDataset, pCalBChans,
+ numPiers, pdGainOverlap_t2,
+ &tMinCalPower, gainBoundaries,
+ pdadcValues, numXpdGain);
+
+ if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
+ REG_WRITE(ah,
+ AR_PHY_TPCRG5 + regChainOffset,
+ SM(pdGainOverlap_t2,
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
+ | SM(gainBoundaries[0],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
+ | SM(gainBoundaries[1],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
+ | SM(gainBoundaries[2],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
+ | SM(gainBoundaries[3],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
+ }
+
+ regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
+ for (j = 0; j < 32; j++) {
+ reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
+ ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
+ ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
+ ((pdadcValues[4 * j + 3] & 0xFF) << 24);
+ REG_WRITE(ah, regOffset, reg32);
+
+ DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+ "PDADC (%d,%4x): %4.4x %8.8x\n",
+ i, regChainOffset, regOffset,
+ reg32);
+ DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+ "PDADC: Chain %d | PDADC %3d "
+ "Value %3d | PDADC %3d Value %3d | "
+ "PDADC %3d Value %3d | PDADC %3d "
+ "Value %3d |\n",
+ i, 4 * j, pdadcValues[4 * j],
+ 4 * j + 1, pdadcValues[4 * j + 1],
+ 4 * j + 2, pdadcValues[4 * j + 2],
+ 4 * j + 3,
+ pdadcValues[4 * j + 3]);
+
+ regOffset += 4;
+ }
+ }
+ }
+
+ *pTxPowerIndexOffset = 0;
+
+ return true;
+}
+
+static bool ath9k_hw_set_4k_power_cal_table(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ int16_t *pTxPowerIndexOffset)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_4k *pEepData = &ahp->ah_eeprom.map4k;
+ struct cal_data_per_freq_4k *pRawDataset;
+ u8 *pCalBChans = NULL;
+ u16 pdGainOverlap_t2;
+ static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
+ u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
+ u16 numPiers, i, j;
+ int16_t tMinCalPower;
+ u16 numXpdGain, xpdMask;
+ u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
+ u32 reg32, regOffset, regChainOffset;
+
+ xpdMask = pEepData->modalHeader.xpdGain;
+
+ if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ pdGainOverlap_t2 =
+ pEepData->modalHeader.pdGainOverlap;
+ } else {
+ pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5),
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
+ }
+
+ pCalBChans = pEepData->calFreqPier2G;
+ numPiers = AR5416_NUM_2G_CAL_PIERS;
+
+ numXpdGain = 0;
+
+ for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
+ if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
+ if (numXpdGain >= AR5416_NUM_PD_GAINS)
+ break;
+ xpdGainValues[numXpdGain] =
+ (u16)(AR5416_PD_GAINS_IN_MASK - i);
+ numXpdGain++;
+ }
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
+ (numXpdGain - 1) & 0x3);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
+ xpdGainValues[0]);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
+ xpdGainValues[1]);
+ REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
+ xpdGainValues[2]);
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ if (AR_SREV_5416_V20_OR_LATER(ah) &&
+ (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5) &&
+ (i != 0)) {
+ regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+ } else
+ regChainOffset = i * 0x1000;
+
+ if (pEepData->baseEepHeader.txMask & (1 << i)) {
+ pRawDataset = pEepData->calPierData2G[i];
+
+ ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan,
+ pRawDataset, pCalBChans,
+ numPiers, pdGainOverlap_t2,
+ &tMinCalPower, gainBoundaries,
+ pdadcValues, numXpdGain);
+
+ if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
+ REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset,
+ SM(pdGainOverlap_t2,
+ AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
+ | SM(gainBoundaries[0],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
+ | SM(gainBoundaries[1],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
+ | SM(gainBoundaries[2],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
+ | SM(gainBoundaries[3],
+ AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
+ }
+
+ regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset;
+ for (j = 0; j < 32; j++) {
+ reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) |
+ ((pdadcValues[4 * j + 1] & 0xFF) << 8) |
+ ((pdadcValues[4 * j + 2] & 0xFF) << 16)|
+ ((pdadcValues[4 * j + 3] & 0xFF) << 24);
+ REG_WRITE(ah, regOffset, reg32);
+
+ DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+ "PDADC (%d,%4x): %4.4x %8.8x\n",
+ i, regChainOffset, regOffset,
+ reg32);
+ DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+ "PDADC: Chain %d | "
+ "PDADC %3d Value %3d | "
+ "PDADC %3d Value %3d | "
+ "PDADC %3d Value %3d | "
+ "PDADC %3d Value %3d |\n",
+ i, 4 * j, pdadcValues[4 * j],
+ 4 * j + 1, pdadcValues[4 * j + 1],
+ 4 * j + 2, pdadcValues[4 * j + 2],
+ 4 * j + 3,
+ pdadcValues[4 * j + 3]);
+
+ regOffset += 4;
+ }
+ }
+ }
+
+ *pTxPowerIndexOffset = 0;
+
+ return true;
+}
+
+static bool ath9k_hw_set_def_power_per_rate_table(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ int16_t *ratesArray,
+ u16 cfgCtl,
+ u16 AntennaReduction,
+ u16 twiceMaxRegulatoryPower,
+ u16 powerLimit)
+{
+#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */
+#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */
+
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_def *pEepData = &ahp->ah_eeprom.def;
+ u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+ static const u16 tpScaleReductionTable[5] =
+ { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
+
+ int i;
+ int16_t twiceLargestAntenna;
+ struct cal_ctl_data *rep;
+ struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
+ 0, { 0, 0, 0, 0}
+ };
+ struct cal_target_power_leg targetPowerOfdmExt = {
+ 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
+ 0, { 0, 0, 0, 0 }
+ };
+ struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
+ 0, {0, 0, 0, 0}
+ };
+ u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+ u16 ctlModesFor11a[] =
+ { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 };
+ u16 ctlModesFor11g[] =
+ { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
+ CTL_2GHT40
+ };
+ u16 numCtlModes, *pCtlMode, ctlMode, freq;
+ struct chan_centers centers;
+ int tx_chainmask;
+ u16 twiceMinEdgePower;
+
+ tx_chainmask = ahp->ah_txchainmask;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ twiceLargestAntenna = max(
+ pEepData->modalHeader
+ [IS_CHAN_2GHZ(chan)].antennaGainCh[0],
+ pEepData->modalHeader
+ [IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
+
+ twiceLargestAntenna = max((u8)twiceLargestAntenna,
+ pEepData->modalHeader
+ [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
+
+ twiceLargestAntenna = (int16_t)min(AntennaReduction -
+ twiceLargestAntenna, 0);
+
+ maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+
+ if (ah->ah_tpScale != ATH9K_TP_SCALE_MAX) {
+ maxRegAllowedPower -=
+ (tpScaleReductionTable[(ah->ah_tpScale)] * 2);
+ }
+
+ scaledPower = min(powerLimit, maxRegAllowedPower);
+
+ switch (ar5416_get_ntxchains(tx_chainmask)) {
+ case 1:
+ break;
+ case 2:
+ scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
+ break;
+ case 3:
+ scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
+ break;
+ }
+
+ scaledPower = max((u16)0, scaledPower);
+
+ if (IS_CHAN_2GHZ(chan)) {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11g) -
+ SUB_NUM_CTL_MODES_AT_2G_40;
+ pCtlMode = ctlModesFor11g;
+
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPowerCck,
+ AR5416_NUM_2G_CCK_TARGET_POWERS,
+ &targetPowerCck, 4, false);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower2G,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerOfdm, 4, false);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower2GHT20,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerHt20, 8, false);
+
+ if (IS_CHAN_HT40(chan)) {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11g);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower2GHT40,
+ AR5416_NUM_2G_40_TARGET_POWERS,
+ &targetPowerHt40, 8, true);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPowerCck,
+ AR5416_NUM_2G_CCK_TARGET_POWERS,
+ &targetPowerCckExt, 4, true);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower2G,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerOfdmExt, 4, true);
+ }
+ } else {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11a) -
+ SUB_NUM_CTL_MODES_AT_5G_40;
+ pCtlMode = ctlModesFor11a;
+
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower5G,
+ AR5416_NUM_5G_20_TARGET_POWERS,
+ &targetPowerOfdm, 4, false);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower5GHT20,
+ AR5416_NUM_5G_20_TARGET_POWERS,
+ &targetPowerHt20, 8, false);
+
+ if (IS_CHAN_HT40(chan)) {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11a);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower5GHT40,
+ AR5416_NUM_5G_40_TARGET_POWERS,
+ &targetPowerHt40, 8, true);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower5G,
+ AR5416_NUM_5G_20_TARGET_POWERS,
+ &targetPowerOfdmExt, 4, true);
+ }
+ }
+
+ for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+ bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
+ (pCtlMode[ctlMode] == CTL_2GHT40);
+ if (isHt40CtlMode)
+ freq = centers.synth_center;
+ else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
+ freq = centers.ext_center;
+ else
+ freq = centers.ctl_center;
+
+ if (ar5416_get_eep_ver(ahp) == 14 && ar5416_get_eep_rev(ahp) <= 2)
+ twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+
+ DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+ "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
+ "EXT_ADDITIVE %d\n",
+ ctlMode, numCtlModes, isHt40CtlMode,
+ (pCtlMode[ctlMode] & EXT_ADDITIVE));
+
+ for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) {
+ DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+ " LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
+ "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
+ "chan %d\n",
+ i, cfgCtl, pCtlMode[ctlMode],
+ pEepData->ctlIndex[i], chan->channel);
+
+ if ((((cfgCtl & ~CTL_MODE_M) |
+ (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+ pEepData->ctlIndex[i]) ||
+ (((cfgCtl & ~CTL_MODE_M) |
+ (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+ ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {
+ rep = &(pEepData->ctlData[i]);
+
+ twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq,
+ rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1],
+ IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES);
+
+ DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+ " MATCH-EE_IDX %d: ch %d is2 %d "
+ "2xMinEdge %d chainmask %d chains %d\n",
+ i, freq, IS_CHAN_2GHZ(chan),
+ twiceMinEdgePower, tx_chainmask,
+ ar5416_get_ntxchains
+ (tx_chainmask));
+ if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
+ twiceMaxEdgePower = min(twiceMaxEdgePower,
+ twiceMinEdgePower);
+ } else {
+ twiceMaxEdgePower = twiceMinEdgePower;
+ break;
+ }
+ }
+ }
+
+ minCtlPower = min(twiceMaxEdgePower, scaledPower);
+
+ DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+ " SEL-Min ctlMode %d pCtlMode %d "
+ "2xMaxEdge %d sP %d minCtlPwr %d\n",
+ ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
+ scaledPower, minCtlPower);
+
+ switch (pCtlMode[ctlMode]) {
+ case CTL_11B:
+ for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) {
+ targetPowerCck.tPow2x[i] =
+ min((u16)targetPowerCck.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_11A:
+ case CTL_11G:
+ for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) {
+ targetPowerOfdm.tPow2x[i] =
+ min((u16)targetPowerOfdm.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_5GHT20:
+ case CTL_2GHT20:
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) {
+ targetPowerHt20.tPow2x[i] =
+ min((u16)targetPowerHt20.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_11B_EXT:
+ targetPowerCckExt.tPow2x[0] = min((u16)
+ targetPowerCckExt.tPow2x[0],
+ minCtlPower);
+ break;
+ case CTL_11A_EXT:
+ case CTL_11G_EXT:
+ targetPowerOfdmExt.tPow2x[0] = min((u16)
+ targetPowerOfdmExt.tPow2x[0],
+ minCtlPower);
+ break;
+ case CTL_5GHT40:
+ case CTL_2GHT40:
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+ targetPowerHt40.tPow2x[i] =
+ min((u16)targetPowerHt40.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
+ ratesArray[rate18mb] = ratesArray[rate24mb] =
+ targetPowerOfdm.tPow2x[0];
+ ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
+ ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
+ ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
+ ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
+
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
+ ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
+
+ if (IS_CHAN_2GHZ(chan)) {
+ ratesArray[rate1l] = targetPowerCck.tPow2x[0];
+ ratesArray[rate2s] = ratesArray[rate2l] =
+ targetPowerCck.tPow2x[1];
+ ratesArray[rate5_5s] = ratesArray[rate5_5l] =
+ targetPowerCck.tPow2x[2];
+ ;
+ ratesArray[rate11s] = ratesArray[rate11l] =
+ targetPowerCck.tPow2x[3];
+ ;
+ }
+ if (IS_CHAN_HT40(chan)) {
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+ ratesArray[rateHt40_0 + i] =
+ targetPowerHt40.tPow2x[i];
+ }
+ ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
+ ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
+ ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
+ if (IS_CHAN_2GHZ(chan)) {
+ ratesArray[rateExtCck] =
+ targetPowerCckExt.tPow2x[0];
+ }
+ }
+ return true;
+}
+
+static bool ath9k_hw_set_4k_power_per_rate_table(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ int16_t *ratesArray,
+ u16 cfgCtl,
+ u16 AntennaReduction,
+ u16 twiceMaxRegulatoryPower,
+ u16 powerLimit)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_4k *pEepData = &ahp->ah_eeprom.map4k;
+ u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+ static const u16 tpScaleReductionTable[5] =
+ { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
+
+ int i;
+ int16_t twiceLargestAntenna;
+ struct cal_ctl_data_4k *rep;
+ struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
+ 0, { 0, 0, 0, 0}
+ };
+ struct cal_target_power_leg targetPowerOfdmExt = {
+ 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
+ 0, { 0, 0, 0, 0 }
+ };
+ struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
+ 0, {0, 0, 0, 0}
+ };
+ u16 scaledPower = 0, minCtlPower, maxRegAllowedPower;
+ u16 ctlModesFor11g[] =
+ { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
+ CTL_2GHT40
+ };
+ u16 numCtlModes, *pCtlMode, ctlMode, freq;
+ struct chan_centers centers;
+ int tx_chainmask;
+ u16 twiceMinEdgePower;
+
+ tx_chainmask = ahp->ah_txchainmask;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0];
+
+ twiceLargestAntenna = (int16_t)min(AntennaReduction -
+ twiceLargestAntenna, 0);
+
+ maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+
+ if (ah->ah_tpScale != ATH9K_TP_SCALE_MAX) {
+ maxRegAllowedPower -=
+ (tpScaleReductionTable[(ah->ah_tpScale)] * 2);
+ }
+
+ scaledPower = min(powerLimit, maxRegAllowedPower);
+ scaledPower = max((u16)0, scaledPower);
+
+ numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40;
+ pCtlMode = ctlModesFor11g;
+
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPowerCck,
+ AR5416_NUM_2G_CCK_TARGET_POWERS,
+ &targetPowerCck, 4, false);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower2G,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerOfdm, 4, false);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower2GHT20,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerHt20, 8, false);
+
+ if (IS_CHAN_HT40(chan)) {
+ numCtlModes = ARRAY_SIZE(ctlModesFor11g);
+ ath9k_hw_get_target_powers(ah, chan,
+ pEepData->calTargetPower2GHT40,
+ AR5416_NUM_2G_40_TARGET_POWERS,
+ &targetPowerHt40, 8, true);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPowerCck,
+ AR5416_NUM_2G_CCK_TARGET_POWERS,
+ &targetPowerCckExt, 4, true);
+ ath9k_hw_get_legacy_target_powers(ah, chan,
+ pEepData->calTargetPower2G,
+ AR5416_NUM_2G_20_TARGET_POWERS,
+ &targetPowerOfdmExt, 4, true);
+ }
+
+ for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
+ bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) ||
+ (pCtlMode[ctlMode] == CTL_2GHT40);
+ if (isHt40CtlMode)
+ freq = centers.synth_center;
+ else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
+ freq = centers.ext_center;
+ else
+ freq = centers.ctl_center;
+
+ if (ar5416_get_eep_ver(ahp) == 14 &&
+ ar5416_get_eep_rev(ahp) <= 2)
+ twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+
+ DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+ "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
+ "EXT_ADDITIVE %d\n",
+ ctlMode, numCtlModes, isHt40CtlMode,
+ (pCtlMode[ctlMode] & EXT_ADDITIVE));
+
+ for (i = 0; (i < AR5416_NUM_CTLS) &&
+ pEepData->ctlIndex[i]; i++) {
+ DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+ " LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
+ "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
+ "chan %d\n",
+ i, cfgCtl, pCtlMode[ctlMode],
+ pEepData->ctlIndex[i], chan->channel);
+
+ if ((((cfgCtl & ~CTL_MODE_M) |
+ (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+ pEepData->ctlIndex[i]) ||
+ (((cfgCtl & ~CTL_MODE_M) |
+ (pCtlMode[ctlMode] & CTL_MODE_M)) ==
+ ((pEepData->ctlIndex[i] & CTL_MODE_M) |
+ SD_NO_CTL))) {
+ rep = &(pEepData->ctlData[i]);
+
+ twiceMinEdgePower =
+ ath9k_hw_get_max_edge_power(freq,
+ rep->ctlEdges[ar5416_get_ntxchains
+ (tx_chainmask) - 1],
+ IS_CHAN_2GHZ(chan),
+ AR5416_EEP4K_NUM_BAND_EDGES);
+
+ DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+ " MATCH-EE_IDX %d: ch %d is2 %d "
+ "2xMinEdge %d chainmask %d chains %d\n",
+ i, freq, IS_CHAN_2GHZ(chan),
+ twiceMinEdgePower, tx_chainmask,
+ ar5416_get_ntxchains
+ (tx_chainmask));
+ if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
+ twiceMaxEdgePower =
+ min(twiceMaxEdgePower,
+ twiceMinEdgePower);
+ } else {
+ twiceMaxEdgePower = twiceMinEdgePower;
+ break;
+ }
+ }
+ }
+
+ minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower);
+
+ DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+ " SEL-Min ctlMode %d pCtlMode %d "
+ "2xMaxEdge %d sP %d minCtlPwr %d\n",
+ ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
+ scaledPower, minCtlPower);
+
+ switch (pCtlMode[ctlMode]) {
+ case CTL_11B:
+ for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x);
+ i++) {
+ targetPowerCck.tPow2x[i] =
+ min((u16)targetPowerCck.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_11G:
+ for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x);
+ i++) {
+ targetPowerOfdm.tPow2x[i] =
+ min((u16)targetPowerOfdm.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_2GHT20:
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x);
+ i++) {
+ targetPowerHt20.tPow2x[i] =
+ min((u16)targetPowerHt20.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ case CTL_11B_EXT:
+ targetPowerCckExt.tPow2x[0] = min((u16)
+ targetPowerCckExt.tPow2x[0],
+ minCtlPower);
+ break;
+ case CTL_11G_EXT:
+ targetPowerOfdmExt.tPow2x[0] = min((u16)
+ targetPowerOfdmExt.tPow2x[0],
+ minCtlPower);
+ break;
+ case CTL_2GHT40:
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x);
+ i++) {
+ targetPowerHt40.tPow2x[i] =
+ min((u16)targetPowerHt40.tPow2x[i],
+ minCtlPower);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
+ ratesArray[rate18mb] = ratesArray[rate24mb] =
+ targetPowerOfdm.tPow2x[0];
+ ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
+ ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
+ ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
+ ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
+
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
+ ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
+
+ ratesArray[rate1l] = targetPowerCck.tPow2x[0];
+ ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1];
+ ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2];
+ ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3];
+
+ if (IS_CHAN_HT40(chan)) {
+ for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
+ ratesArray[rateHt40_0 + i] =
+ targetPowerHt40.tPow2x[i];
+ }
+ ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
+ ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
+ ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
+ ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0];
+ }
+ return true;
+}
+
+static int ath9k_hw_def_set_txpower(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ u16 cfgCtl,
+ u8 twiceAntennaReduction,
+ u8 twiceMaxRegulatoryPower,
+ u8 powerLimit)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_def *pEepData = &ahp->ah_eeprom.def;
+ struct modal_eep_header *pModal =
+ &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
+ int16_t ratesArray[Ar5416RateSize];
+ int16_t txPowerIndexOffset = 0;
+ u8 ht40PowerIncForPdadc = 2;
+ int i;
+
+ memset(ratesArray, 0, sizeof(ratesArray));
+
+ if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+ }
+
+ if (!ath9k_hw_set_def_power_per_rate_table(ah, chan,
+ &ratesArray[0], cfgCtl,
+ twiceAntennaReduction,
+ twiceMaxRegulatoryPower,
+ powerLimit)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "ath9k_hw_set_txpower: unable to set "
+ "tx power per rate table\n");
+ return -EIO;
+ }
+
+ if (!ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "ath9k_hw_set_txpower: unable to set power table\n");
+ return -EIO;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
+ ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
+ if (ratesArray[i] > AR5416_MAX_RATE_POWER)
+ ratesArray[i] = AR5416_MAX_RATE_POWER;
+ }
+
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ for (i = 0; i < Ar5416RateSize; i++)
+ ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
+ }
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
+ ATH9K_POW_SM(ratesArray[rate18mb], 24)
+ | ATH9K_POW_SM(ratesArray[rate12mb], 16)
+ | ATH9K_POW_SM(ratesArray[rate9mb], 8)
+ | ATH9K_POW_SM(ratesArray[rate6mb], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
+ ATH9K_POW_SM(ratesArray[rate54mb], 24)
+ | ATH9K_POW_SM(ratesArray[rate48mb], 16)
+ | ATH9K_POW_SM(ratesArray[rate36mb], 8)
+ | ATH9K_POW_SM(ratesArray[rate24mb], 0));
+
+ if (IS_CHAN_2GHZ(chan)) {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+ ATH9K_POW_SM(ratesArray[rate2s], 24)
+ | ATH9K_POW_SM(ratesArray[rate2l], 16)
+ | ATH9K_POW_SM(ratesArray[rateXr], 8)
+ | ATH9K_POW_SM(ratesArray[rate1l], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+ ATH9K_POW_SM(ratesArray[rate11s], 24)
+ | ATH9K_POW_SM(ratesArray[rate11l], 16)
+ | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
+ | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
+ }
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
+ ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
+ | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
+ | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
+ | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
+ ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
+ | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
+ | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
+ | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
+
+ if (IS_CHAN_HT40(chan)) {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+ ATH9K_POW_SM(ratesArray[rateHt40_3] +
+ ht40PowerIncForPdadc, 24)
+ | ATH9K_POW_SM(ratesArray[rateHt40_2] +
+ ht40PowerIncForPdadc, 16)
+ | ATH9K_POW_SM(ratesArray[rateHt40_1] +
+ ht40PowerIncForPdadc, 8)
+ | ATH9K_POW_SM(ratesArray[rateHt40_0] +
+ ht40PowerIncForPdadc, 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+ ATH9K_POW_SM(ratesArray[rateHt40_7] +
+ ht40PowerIncForPdadc, 24)
+ | ATH9K_POW_SM(ratesArray[rateHt40_6] +
+ ht40PowerIncForPdadc, 16)
+ | ATH9K_POW_SM(ratesArray[rateHt40_5] +
+ ht40PowerIncForPdadc, 8)
+ | ATH9K_POW_SM(ratesArray[rateHt40_4] +
+ ht40PowerIncForPdadc, 0));
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+ ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
+ | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
+ | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
+ | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
+ }
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
+ ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
+ | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
+
+ i = rate6mb;
+
+ if (IS_CHAN_HT40(chan))
+ i = rateHt40_0;
+ else if (IS_CHAN_HT20(chan))
+ i = rateHt20_0;
+
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ ah->ah_maxPowerLevel =
+ ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
+ else
+ ah->ah_maxPowerLevel = ratesArray[i];
+
+ return 0;
+}
+
+static int ath9k_hw_4k_set_txpower(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ u16 cfgCtl,
+ u8 twiceAntennaReduction,
+ u8 twiceMaxRegulatoryPower,
+ u8 powerLimit)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_4k *pEepData = &ahp->ah_eeprom.map4k;
+ struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
+ int16_t ratesArray[Ar5416RateSize];
+ int16_t txPowerIndexOffset = 0;
+ u8 ht40PowerIncForPdadc = 2;
+ int i;
+
+ memset(ratesArray, 0, sizeof(ratesArray));
+
+ if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
+ }
+
+ if (!ath9k_hw_set_4k_power_per_rate_table(ah, chan,
+ &ratesArray[0], cfgCtl,
+ twiceAntennaReduction,
+ twiceMaxRegulatoryPower,
+ powerLimit)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "ath9k_hw_set_txpower: unable to set "
+ "tx power per rate table\n");
+ return -EIO;
+ }
+
+ if (!ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "ath9k_hw_set_txpower: unable to set power table\n");
+ return -EIO;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
+ ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
+ if (ratesArray[i] > AR5416_MAX_RATE_POWER)
+ ratesArray[i] = AR5416_MAX_RATE_POWER;
+ }
+
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ for (i = 0; i < Ar5416RateSize; i++)
+ ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
+ }
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
+ ATH9K_POW_SM(ratesArray[rate18mb], 24)
+ | ATH9K_POW_SM(ratesArray[rate12mb], 16)
+ | ATH9K_POW_SM(ratesArray[rate9mb], 8)
+ | ATH9K_POW_SM(ratesArray[rate6mb], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
+ ATH9K_POW_SM(ratesArray[rate54mb], 24)
+ | ATH9K_POW_SM(ratesArray[rate48mb], 16)
+ | ATH9K_POW_SM(ratesArray[rate36mb], 8)
+ | ATH9K_POW_SM(ratesArray[rate24mb], 0));
+
+ if (IS_CHAN_2GHZ(chan)) {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
+ ATH9K_POW_SM(ratesArray[rate2s], 24)
+ | ATH9K_POW_SM(ratesArray[rate2l], 16)
+ | ATH9K_POW_SM(ratesArray[rateXr], 8)
+ | ATH9K_POW_SM(ratesArray[rate1l], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
+ ATH9K_POW_SM(ratesArray[rate11s], 24)
+ | ATH9K_POW_SM(ratesArray[rate11l], 16)
+ | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
+ | ATH9K_POW_SM(ratesArray[rate5_5l], 0));
+ }
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
+ ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
+ | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
+ | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
+ | ATH9K_POW_SM(ratesArray[rateHt20_0], 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
+ ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
+ | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
+ | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
+ | ATH9K_POW_SM(ratesArray[rateHt20_4], 0));
+
+ if (IS_CHAN_HT40(chan)) {
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
+ ATH9K_POW_SM(ratesArray[rateHt40_3] +
+ ht40PowerIncForPdadc, 24)
+ | ATH9K_POW_SM(ratesArray[rateHt40_2] +
+ ht40PowerIncForPdadc, 16)
+ | ATH9K_POW_SM(ratesArray[rateHt40_1] +
+ ht40PowerIncForPdadc, 8)
+ | ATH9K_POW_SM(ratesArray[rateHt40_0] +
+ ht40PowerIncForPdadc, 0));
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
+ ATH9K_POW_SM(ratesArray[rateHt40_7] +
+ ht40PowerIncForPdadc, 24)
+ | ATH9K_POW_SM(ratesArray[rateHt40_6] +
+ ht40PowerIncForPdadc, 16)
+ | ATH9K_POW_SM(ratesArray[rateHt40_5] +
+ ht40PowerIncForPdadc, 8)
+ | ATH9K_POW_SM(ratesArray[rateHt40_4] +
+ ht40PowerIncForPdadc, 0));
+
+ REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
+ ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
+ | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
+ | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
+ | ATH9K_POW_SM(ratesArray[rateDupCck], 0));
+ }
+
+ i = rate6mb;
+
+ if (IS_CHAN_HT40(chan))
+ i = rateHt40_0;
+ else if (IS_CHAN_HT20(chan))
+ i = rateHt20_0;
+
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ ah->ah_maxPowerLevel =
+ ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
+ else
+ ah->ah_maxPowerLevel = ratesArray[i];
+
+ return 0;
+}
+
+static int (*ath9k_set_txpower[]) (struct ath_hal *,
+ struct ath9k_channel *,
+ u16, u8, u8, u8) = {
+ ath9k_hw_def_set_txpower,
+ ath9k_hw_4k_set_txpower
+};
+
+int ath9k_hw_set_txpower(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ u16 cfgCtl,
+ u8 twiceAntennaReduction,
+ u8 twiceMaxRegulatoryPower,
+ u8 powerLimit)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ return ath9k_set_txpower[ahp->ah_eep_map](ah, chan, cfgCtl,
+ twiceAntennaReduction, twiceMaxRegulatoryPower,
+ powerLimit);
+}
+
+static void ath9k_hw_set_def_addac(struct ath_hal *ah,
+ struct ath9k_channel *chan)
+{
+#define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt])
+ struct modal_eep_header *pModal;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
+ u8 biaslevel;
+
+ if (ah->ah_macVersion != AR_SREV_VERSION_9160)
+ return;
+
+ if (ar5416_get_eep_rev(ahp) < AR5416_EEP_MINOR_VER_7)
+ return;
+
+ pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+
+ if (pModal->xpaBiasLvl != 0xff) {
+ biaslevel = pModal->xpaBiasLvl;
+ } else {
+ u16 resetFreqBin, freqBin, freqCount = 0;
+ struct chan_centers centers;
+
+ ath9k_hw_get_channel_centers(ah, chan, &centers);
+
+ resetFreqBin = FREQ2FBIN(centers.synth_center,
+ IS_CHAN_2GHZ(chan));
+ freqBin = XPA_LVL_FREQ(0) & 0xff;
+ biaslevel = (u8) (XPA_LVL_FREQ(0) >> 14);
+
+ freqCount++;
+
+ while (freqCount < 3) {
+ if (XPA_LVL_FREQ(freqCount) == 0x0)
+ break;
+
+ freqBin = XPA_LVL_FREQ(freqCount) & 0xff;
+ if (resetFreqBin >= freqBin)
+ biaslevel = (u8)(XPA_LVL_FREQ(freqCount) >> 14);
+ else
+ break;
+ freqCount++;
+ }
+ }
+
+ if (IS_CHAN_2GHZ(chan)) {
+ INI_RA(&ahp->ah_iniAddac, 7, 1) = (INI_RA(&ahp->ah_iniAddac,
+ 7, 1) & (~0x18)) | biaslevel << 3;
+ } else {
+ INI_RA(&ahp->ah_iniAddac, 6, 1) = (INI_RA(&ahp->ah_iniAddac,
+ 6, 1) & (~0xc0)) | biaslevel << 6;
+ }
+#undef XPA_LVL_FREQ
+}
+
+static void ath9k_hw_set_4k_addac(struct ath_hal *ah,
+ struct ath9k_channel *chan)
+{
+ struct modal_eep_4k_header *pModal;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
+ u8 biaslevel;
+
+ if (ah->ah_macVersion != AR_SREV_VERSION_9160)
+ return;
+
+ if (ar5416_get_eep_rev(ahp) < AR5416_EEP_MINOR_VER_7)
+ return;
+
+ pModal = &eep->modalHeader;
+
+ if (pModal->xpaBiasLvl != 0xff) {
+ biaslevel = pModal->xpaBiasLvl;
+ INI_RA(&ahp->ah_iniAddac, 7, 1) =
+ (INI_RA(&ahp->ah_iniAddac, 7, 1) & (~0x18)) | biaslevel << 3;
+ }
+}
+
+static void (*ath9k_set_addac[]) (struct ath_hal *, struct ath9k_channel *) = {
+ ath9k_hw_set_def_addac,
+ ath9k_hw_set_4k_addac
+};
+
+void ath9k_hw_set_addac(struct ath_hal *ah, struct ath9k_channel *chan)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ ath9k_set_addac[ahp->ah_eep_map](ah, chan);
+}
+
+
+
+/* XXX: Clean me up, make me more legible */
+static bool ath9k_hw_eeprom_set_def_board_values(struct ath_hal *ah,
+ struct ath9k_channel *chan)
+{
+ struct modal_eep_header *pModal;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
+ int i, regChainOffset;
+ u8 txRxAttenLocal;
+ u16 ant_config;
+
+ pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+
+ txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
+
+ ath9k_hw_get_eeprom_antenna_cfg(ah, chan, 0, &ant_config);
+ REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
+
+ for (i = 0; i < AR5416_MAX_CHAINS; i++) {
+ if (AR_SREV_9280(ah)) {
+ if (i >= 2)
+ break;
+ }
+
+ if (AR_SREV_5416_V20_OR_LATER(ah) &&
+ (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5)
+ && (i != 0))
+ regChainOffset = (i == 1) ? 0x2000 : 0x1000;
+ else
+ regChainOffset = i * 0x1000;
+
+ REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
+ pModal->antCtrlChain[i]);
+
+ REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
+ (REG_READ(ah,
+ AR_PHY_TIMING_CTRL4(0) +
+ regChainOffset) &
+ ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
+ SM(pModal->iqCalICh[i],
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
+ SM(pModal->iqCalQCh[i],
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
+
+ if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
+ if ((eep->baseEepHeader.version &
+ AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_3) {
+ txRxAttenLocal = pModal->txRxAttenCh[i];
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ REG_RMW_FIELD(ah,
+ AR_PHY_GAIN_2GHZ +
+ regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
+ pModal->
+ bswMargin[i]);
+ REG_RMW_FIELD(ah,
+ AR_PHY_GAIN_2GHZ +
+ regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN1_DB,
+ pModal->
+ bswAtten[i]);
+ REG_RMW_FIELD(ah,
+ AR_PHY_GAIN_2GHZ +
+ regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
+ pModal->
+ xatten2Margin[i]);
+ REG_RMW_FIELD(ah,
+ AR_PHY_GAIN_2GHZ +
+ regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN2_DB,
+ pModal->
+ xatten2Db[i]);
+ } else {
+ REG_WRITE(ah,
+ AR_PHY_GAIN_2GHZ +
+ regChainOffset,
+ (REG_READ(ah,
+ AR_PHY_GAIN_2GHZ +
+ regChainOffset) &
+ ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
+ | SM(pModal->
+ bswMargin[i],
+ AR_PHY_GAIN_2GHZ_BSW_MARGIN));
+ REG_WRITE(ah,
+ AR_PHY_GAIN_2GHZ +
+ regChainOffset,
+ (REG_READ(ah,
+ AR_PHY_GAIN_2GHZ +
+ regChainOffset) &
+ ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
+ | SM(pModal->bswAtten[i],
+ AR_PHY_GAIN_2GHZ_BSW_ATTEN));
+ }
+ }
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ REG_RMW_FIELD(ah,
+ AR_PHY_RXGAIN +
+ regChainOffset,
+ AR9280_PHY_RXGAIN_TXRX_ATTEN,
+ txRxAttenLocal);
+ REG_RMW_FIELD(ah,
+ AR_PHY_RXGAIN +
+ regChainOffset,
+ AR9280_PHY_RXGAIN_TXRX_MARGIN,
+ pModal->rxTxMarginCh[i]);
+ } else {
+ REG_WRITE(ah,
+ AR_PHY_RXGAIN + regChainOffset,
+ (REG_READ(ah,
+ AR_PHY_RXGAIN +
+ regChainOffset) &
+ ~AR_PHY_RXGAIN_TXRX_ATTEN) |
+ SM(txRxAttenLocal,
+ AR_PHY_RXGAIN_TXRX_ATTEN));
+ REG_WRITE(ah,
+ AR_PHY_GAIN_2GHZ +
+ regChainOffset,
+ (REG_READ(ah,
+ AR_PHY_GAIN_2GHZ +
+ regChainOffset) &
+ ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
+ SM(pModal->rxTxMarginCh[i],
+ AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
+ }
+ }
+ }
+
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ if (IS_CHAN_2GHZ(chan)) {
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
+ AR_AN_RF2G1_CH0_OB,
+ AR_AN_RF2G1_CH0_OB_S,
+ pModal->ob);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
+ AR_AN_RF2G1_CH0_DB,
+ AR_AN_RF2G1_CH0_DB_S,
+ pModal->db);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
+ AR_AN_RF2G1_CH1_OB,
+ AR_AN_RF2G1_CH1_OB_S,
+ pModal->ob_ch1);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
+ AR_AN_RF2G1_CH1_DB,
+ AR_AN_RF2G1_CH1_DB_S,
+ pModal->db_ch1);
+ } else {
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
+ AR_AN_RF5G1_CH0_OB5,
+ AR_AN_RF5G1_CH0_OB5_S,
+ pModal->ob);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
+ AR_AN_RF5G1_CH0_DB5,
+ AR_AN_RF5G1_CH0_DB5_S,
+ pModal->db);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
+ AR_AN_RF5G1_CH1_OB5,
+ AR_AN_RF5G1_CH1_OB5_S,
+ pModal->ob_ch1);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
+ AR_AN_RF5G1_CH1_DB5,
+ AR_AN_RF5G1_CH1_DB5_S,
+ pModal->db_ch1);
+ }
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
+ AR_AN_TOP2_XPABIAS_LVL,
+ AR_AN_TOP2_XPABIAS_LVL_S,
+ pModal->xpaBiasLvl);
+ ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
+ AR_AN_TOP2_LOCALBIAS,
+ AR_AN_TOP2_LOCALBIAS_S,
+ pModal->local_bias);
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "ForceXPAon: %d\n",
+ pModal->force_xpaon);
+ REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
+ pModal->force_xpaon);
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
+ pModal->switchSettling);
+ REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
+ pModal->adcDesiredSize);
+
+ if (!AR_SREV_9280_10_OR_LATER(ah))
+ REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
+ AR_PHY_DESIRED_SZ_PGA,
+ pModal->pgaDesiredSize);
+
+ REG_WRITE(ah, AR_PHY_RF_CTL4,
+ SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
+ | SM(pModal->txEndToXpaOff,
+ AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
+ | SM(pModal->txFrameToXpaOn,
+ AR_PHY_RF_CTL4_FRAME_XPAA_ON)
+ | SM(pModal->txFrameToXpaOn,
+ AR_PHY_RF_CTL4_FRAME_XPAB_ON));
+
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
+ pModal->txEndToRxOn);
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
+ pModal->thresh62);
+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
+ AR_PHY_EXT_CCA0_THRESH62,
+ pModal->thresh62);
+ } else {
+ REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
+ pModal->thresh62);
+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
+ AR_PHY_EXT_CCA_THRESH62,
+ pModal->thresh62);
+ }
+
+ if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
+ AR_PHY_TX_END_DATA_START,
+ pModal->txFrameToDataStart);
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
+ pModal->txFrameToPaOn);
+ }
+
+ if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_3) {
+ if (IS_CHAN_HT40(chan))
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+ AR_PHY_SETTLING_SWITCH,
+ pModal->swSettleHt40);
+ }
+
+ return true;
+}
+
+static bool ath9k_hw_eeprom_set_4k_board_values(struct ath_hal *ah,
+ struct ath9k_channel *chan)
+{
+ struct modal_eep_4k_header *pModal;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
+ int regChainOffset;
+ u8 txRxAttenLocal;
+ u16 ant_config = 0;
+ u8 ob[5], db1[5], db2[5];
+ u8 ant_div_control1, ant_div_control2;
+ u32 regVal;
+
+
+ pModal = &eep->modalHeader;
+
+ txRxAttenLocal = 23;
+
+ ath9k_hw_get_eeprom_antenna_cfg(ah, chan, 0, &ant_config);
+ REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
+
+ regChainOffset = 0;
+ REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
+ pModal->antCtrlChain[0]);
+
+ REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
+ (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) &
+ ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
+ AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
+ SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
+ SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
+
+ if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_3) {
+ txRxAttenLocal = pModal->txRxAttenCh[0];
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
+ pModal->xatten2Margin[0]);
+ REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset,
+ AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]);
+ }
+
+ REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
+ AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal);
+ REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset,
+ AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]);
+
+ if (AR_SREV_9285_11(ah))
+ REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14));
+
+ /* Initialize Ant Diversity settings from EEPROM */
+ if (pModal->version == 3) {
+ ant_div_control1 = ((pModal->ob_234 >> 12) & 0xf);
+ ant_div_control2 = ((pModal->db1_234 >> 12) & 0xf);
+ regVal = REG_READ(ah, 0x99ac);
+ regVal &= (~(0x7f000000));
+ regVal |= ((ant_div_control1 & 0x1) << 24);
+ regVal |= (((ant_div_control1 >> 1) & 0x1) << 29);
+ regVal |= (((ant_div_control1 >> 2) & 0x1) << 30);
+ regVal |= ((ant_div_control2 & 0x3) << 25);
+ regVal |= (((ant_div_control2 >> 2) & 0x3) << 27);
+ REG_WRITE(ah, 0x99ac, regVal);
+ regVal = REG_READ(ah, 0x99ac);
+ regVal = REG_READ(ah, 0xa208);
+ regVal &= (~(0x1 << 13));
+ regVal |= (((ant_div_control1 >> 3) & 0x1) << 13);
+ REG_WRITE(ah, 0xa208, regVal);
+ regVal = REG_READ(ah, 0xa208);
+ }
+
+ if (pModal->version >= 2) {
+ ob[0] = (pModal->ob_01 & 0xf);
+ ob[1] = (pModal->ob_01 >> 4) & 0xf;
+ ob[2] = (pModal->ob_234 & 0xf);
+ ob[3] = ((pModal->ob_234 >> 4) & 0xf);
+ ob[4] = ((pModal->ob_234 >> 8) & 0xf);
+
+ db1[0] = (pModal->db1_01 & 0xf);
+ db1[1] = ((pModal->db1_01 >> 4) & 0xf);
+ db1[2] = (pModal->db1_234 & 0xf);
+ db1[3] = ((pModal->db1_234 >> 4) & 0xf);
+ db1[4] = ((pModal->db1_234 >> 8) & 0xf);
+
+ db2[0] = (pModal->db2_01 & 0xf);
+ db2[1] = ((pModal->db2_01 >> 4) & 0xf);
+ db2[2] = (pModal->db2_234 & 0xf);
+ db2[3] = ((pModal->db2_234 >> 4) & 0xf);
+ db2[4] = ((pModal->db2_234 >> 8) & 0xf);
+
+ } else if (pModal->version == 1) {
+
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "EEPROM Model version is set to 1 \n");
+ ob[0] = (pModal->ob_01 & 0xf);
+ ob[1] = ob[2] = ob[3] = ob[4] = (pModal->ob_01 >> 4) & 0xf;
+ db1[0] = (pModal->db1_01 & 0xf);
+ db1[1] = db1[2] = db1[3] =
+ db1[4] = ((pModal->db1_01 >> 4) & 0xf);
+ db2[0] = (pModal->db2_01 & 0xf);
+ db2[1] = db2[2] = db2[3] =
+ db2[4] = ((pModal->db2_01 >> 4) & 0xf);
+ } else {
+ int i;
+ for (i = 0; i < 5; i++) {
+ ob[i] = pModal->ob_01;
+ db1[i] = pModal->db1_01;
+ db2[i] = pModal->db1_01;
+ }
+ }
+
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_OB_0, AR9285_AN_RF2G3_OB_0_S, ob[0]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_OB_1, AR9285_AN_RF2G3_OB_1_S, ob[1]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_OB_2, AR9285_AN_RF2G3_OB_2_S, ob[2]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_OB_3, AR9285_AN_RF2G3_OB_3_S, ob[3]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_OB_4, AR9285_AN_RF2G3_OB_4_S, ob[4]);
+
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_DB1_0, AR9285_AN_RF2G3_DB1_0_S, db1[0]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_DB1_1, AR9285_AN_RF2G3_DB1_1_S, db1[1]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G3,
+ AR9285_AN_RF2G3_DB1_2, AR9285_AN_RF2G3_DB1_2_S, db1[2]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB1_3, AR9285_AN_RF2G4_DB1_3_S, db1[3]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB1_4, AR9285_AN_RF2G4_DB1_4_S, db1[4]);
+
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB2_0, AR9285_AN_RF2G4_DB2_0_S, db2[0]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB2_1, AR9285_AN_RF2G4_DB2_1_S, db2[1]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB2_2, AR9285_AN_RF2G4_DB2_2_S, db2[2]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB2_3, AR9285_AN_RF2G4_DB2_3_S, db2[3]);
+ ath9k_hw_analog_shift_rmw(ah, AR9285_AN_RF2G4,
+ AR9285_AN_RF2G4_DB2_4, AR9285_AN_RF2G4_DB2_4_S, db2[4]);
+
+
+ if (AR_SREV_9285_11(ah))
+ REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT);
+
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
+ pModal->switchSettling);
+ REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
+ pModal->adcDesiredSize);
+
+ REG_WRITE(ah, AR_PHY_RF_CTL4,
+ SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) |
+ SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) |
+ SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) |
+ SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON));
+
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
+ pModal->txEndToRxOn);
+ REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
+ pModal->thresh62);
+ REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62,
+ pModal->thresh62);
+
+ if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_2) {
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START,
+ pModal->txFrameToDataStart);
+ REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
+ pModal->txFrameToPaOn);
+ }
+
+ if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
+ AR5416_EEP_MINOR_VER_3) {
+ if (IS_CHAN_HT40(chan))
+ REG_RMW_FIELD(ah, AR_PHY_SETTLING,
+ AR_PHY_SETTLING_SWITCH,
+ pModal->swSettleHt40);
+ }
+
+ return true;
+}
+
+static bool (*ath9k_eeprom_set_board_values[])(struct ath_hal *,
+ struct ath9k_channel *) = {
+ ath9k_hw_eeprom_set_def_board_values,
+ ath9k_hw_eeprom_set_4k_board_values
+};
+
+bool ath9k_hw_eeprom_set_board_values(struct ath_hal *ah,
+ struct ath9k_channel *chan)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ return ath9k_eeprom_set_board_values[ahp->ah_eep_map](ah, chan);
+}
+
+static int ath9k_hw_get_def_eeprom_antenna_cfg(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ u8 index, u16 *config)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
+ struct modal_eep_header *pModal =
+ &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+ struct base_eep_header *pBase = &eep->baseEepHeader;
+
+ switch (index) {
+ case 0:
+ *config = pModal->antCtrlCommon & 0xFFFF;
+ return 0;
+ case 1:
+ if (pBase->version >= 0x0E0D) {
+ if (pModal->useAnt1) {
+ *config =
+ ((pModal->antCtrlCommon & 0xFFFF0000) >> 16);
+ return 0;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static int ath9k_hw_get_4k_eeprom_antenna_cfg(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ u8 index, u16 *config)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
+ struct modal_eep_4k_header *pModal = &eep->modalHeader;
+
+ switch (index) {
+ case 0:
+ *config = pModal->antCtrlCommon & 0xFFFF;
+ return 0;
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static int (*ath9k_get_eeprom_antenna_cfg[])(struct ath_hal *,
+ struct ath9k_channel *,
+ u8, u16 *) = {
+ ath9k_hw_get_def_eeprom_antenna_cfg,
+ ath9k_hw_get_4k_eeprom_antenna_cfg
+};
+
+int ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ u8 index, u16 *config)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ return ath9k_get_eeprom_antenna_cfg[ahp->ah_eep_map](ah, chan,
+ index, config);
+}
+
+static u8 ath9k_hw_get_4k_num_ant_config(struct ath_hal *ah,
+ enum ieee80211_band freq_band)
+{
+ return 1;
+}
+
+static u8 ath9k_hw_get_def_num_ant_config(struct ath_hal *ah,
+ enum ieee80211_band freq_band)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
+ struct modal_eep_header *pModal =
+ &(eep->modalHeader[ATH9K_HAL_FREQ_BAND_2GHZ == freq_band]);
+ struct base_eep_header *pBase = &eep->baseEepHeader;
+ u8 num_ant_config;
+
+ num_ant_config = 1;
+
+ if (pBase->version >= 0x0E0D)
+ if (pModal->useAnt1)
+ num_ant_config += 1;
+
+ return num_ant_config;
+}
+
+static u8 (*ath9k_get_num_ant_config[])(struct ath_hal *,
+ enum ieee80211_band) = {
+ ath9k_hw_get_def_num_ant_config,
+ ath9k_hw_get_4k_num_ant_config
+};
+
+u8 ath9k_hw_get_num_ant_config(struct ath_hal *ah,
+ enum ieee80211_band freq_band)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ return ath9k_get_num_ant_config[ahp->ah_eep_map](ah, freq_band);
+}
+
+u16 ath9k_hw_eeprom_get_spur_chan(struct ath_hal *ah, u16 i, bool is2GHz)
+{
+#define EEP_MAP4K_SPURCHAN \
+ (ahp->ah_eeprom.map4k.modalHeader.spurChans[i].spurChan)
+#define EEP_DEF_SPURCHAN \
+ (ahp->ah_eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan)
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ u16 spur_val = AR_NO_SPUR;
+
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "Getting spur idx %d is2Ghz. %d val %x\n",
+ i, is2GHz, ah->ah_config.spurchans[i][is2GHz]);
+
+ switch (ah->ah_config.spurmode) {
+ case SPUR_DISABLE:
+ break;
+ case SPUR_ENABLE_IOCTL:
+ spur_val = ah->ah_config.spurchans[i][is2GHz];
+ DPRINTF(ah->ah_sc, ATH_DBG_ANI,
+ "Getting spur val from new loc. %d\n", spur_val);
+ break;
+ case SPUR_ENABLE_EEPROM:
+ if (ahp->ah_eep_map == EEP_MAP_4KBITS)
+ spur_val = EEP_MAP4K_SPURCHAN;
+ else
+ spur_val = EEP_DEF_SPURCHAN;
+ break;
+
+ }
+
+ return spur_val;
+#undef EEP_DEF_SPURCHAN
+#undef EEP_MAP4K_SPURCHAN
+}
+
+static u32 ath9k_hw_get_eeprom_4k(struct ath_hal *ah,
+ enum eeprom_param param)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_4k *eep = &ahp->ah_eeprom.map4k;
+ struct modal_eep_4k_header *pModal = &eep->modalHeader;
+ struct base_eep_header_4k *pBase = &eep->baseEepHeader;
+
+ switch (param) {
+ case EEP_NFTHRESH_2:
+ return pModal[1].noiseFloorThreshCh[0];
+ case AR_EEPROM_MAC(0):
+ return pBase->macAddr[0] << 8 | pBase->macAddr[1];
+ case AR_EEPROM_MAC(1):
+ return pBase->macAddr[2] << 8 | pBase->macAddr[3];
+ case AR_EEPROM_MAC(2):
+ return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+ case EEP_REG_0:
+ return pBase->regDmn[0];
+ case EEP_REG_1:
+ return pBase->regDmn[1];
+ case EEP_OP_CAP:
+ return pBase->deviceCap;
+ case EEP_OP_MODE:
+ return pBase->opCapFlags;
+ case EEP_RF_SILENT:
+ return pBase->rfSilent;
+ case EEP_OB_2:
+ return pModal->ob_01;
+ case EEP_DB_2:
+ return pModal->db1_01;
+ case EEP_MINOR_REV:
+ return pBase->version & AR5416_EEP_VER_MINOR_MASK;
+ case EEP_TX_MASK:
+ return pBase->txMask;
+ case EEP_RX_MASK:
+ return pBase->rxMask;
+ default:
+ return 0;
+ }
+}
+
+static u32 ath9k_hw_get_eeprom_def(struct ath_hal *ah,
+ enum eeprom_param param)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ar5416_eeprom_def *eep = &ahp->ah_eeprom.def;
+ struct modal_eep_header *pModal = eep->modalHeader;
+ struct base_eep_header *pBase = &eep->baseEepHeader;
+
+ switch (param) {
+ case EEP_NFTHRESH_5:
+ return pModal[0].noiseFloorThreshCh[0];
+ case EEP_NFTHRESH_2:
+ return pModal[1].noiseFloorThreshCh[0];
+ case AR_EEPROM_MAC(0):
+ return pBase->macAddr[0] << 8 | pBase->macAddr[1];
+ case AR_EEPROM_MAC(1):
+ return pBase->macAddr[2] << 8 | pBase->macAddr[3];
+ case AR_EEPROM_MAC(2):
+ return pBase->macAddr[4] << 8 | pBase->macAddr[5];
+ case EEP_REG_0:
+ return pBase->regDmn[0];
+ case EEP_REG_1:
+ return pBase->regDmn[1];
+ case EEP_OP_CAP:
+ return pBase->deviceCap;
+ case EEP_OP_MODE:
+ return pBase->opCapFlags;
+ case EEP_RF_SILENT:
+ return pBase->rfSilent;
+ case EEP_OB_5:
+ return pModal[0].ob;
+ case EEP_DB_5:
+ return pModal[0].db;
+ case EEP_OB_2:
+ return pModal[1].ob;
+ case EEP_DB_2:
+ return pModal[1].db;
+ case EEP_MINOR_REV:
+ return pBase->version & AR5416_EEP_VER_MINOR_MASK;
+ case EEP_TX_MASK:
+ return pBase->txMask;
+ case EEP_RX_MASK:
+ return pBase->rxMask;
+ case EEP_RXGAIN_TYPE:
+ return pBase->rxGainType;
+ case EEP_TXGAIN_TYPE:
+ return pBase->txGainType;
+
+ default:
+ return 0;
+ }
+}
+
+static u32 (*ath9k_get_eeprom[])(struct ath_hal *, enum eeprom_param) = {
+ ath9k_hw_get_eeprom_def,
+ ath9k_hw_get_eeprom_4k
+};
+
+u32 ath9k_hw_get_eeprom(struct ath_hal *ah,
+ enum eeprom_param param)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ return ath9k_get_eeprom[ahp->ah_eep_map](ah, param);
+}
+
+int ath9k_hw_eeprom_attach(struct ath_hal *ah)
+{
+ int status;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ if (ath9k_hw_use_flash(ah))
+ ath9k_hw_flash_map(ah);
+
+ if (AR_SREV_9285(ah))
+ ahp->ah_eep_map = EEP_MAP_4KBITS;
+ else
+ ahp->ah_eep_map = EEP_MAP_DEFAULT;
+
+ if (!ath9k_hw_fill_eeprom(ah))
+ return -EIO;
+
+ status = ath9k_hw_check_eeprom(ah);
+
+ return status;
+}
diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c
index 98bc25c9b3cf..34474edefc97 100644
--- a/drivers/net/wireless/ath9k/hw.c
+++ b/drivers/net/wireless/ath9k/hw.c
@@ -23,277 +23,93 @@
#include "phy.h"
#include "initvals.h"
-static void ath9k_hw_iqcal_collect(struct ath_hal *ah);
-static void ath9k_hw_iqcalibrate(struct ath_hal *ah, u8 numChains);
-static void ath9k_hw_adc_gaincal_collect(struct ath_hal *ah);
-static void ath9k_hw_adc_gaincal_calibrate(struct ath_hal *ah,
- u8 numChains);
-static void ath9k_hw_adc_dccal_collect(struct ath_hal *ah);
-static void ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah,
- u8 numChains);
-
static const u8 CLOCK_RATE[] = { 40, 80, 22, 44, 88, 40 };
-static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93, -96 };
-
-static const struct hal_percal_data iq_cal_multi_sample = {
- IQ_MISMATCH_CAL,
- MAX_CAL_SAMPLES,
- PER_MIN_LOG_COUNT,
- ath9k_hw_iqcal_collect,
- ath9k_hw_iqcalibrate
-};
-static const struct hal_percal_data iq_cal_single_sample = {
- IQ_MISMATCH_CAL,
- MIN_CAL_SAMPLES,
- PER_MAX_LOG_COUNT,
- ath9k_hw_iqcal_collect,
- ath9k_hw_iqcalibrate
-};
-static const struct hal_percal_data adc_gain_cal_multi_sample = {
- ADC_GAIN_CAL,
- MAX_CAL_SAMPLES,
- PER_MIN_LOG_COUNT,
- ath9k_hw_adc_gaincal_collect,
- ath9k_hw_adc_gaincal_calibrate
-};
-static const struct hal_percal_data adc_gain_cal_single_sample = {
- ADC_GAIN_CAL,
- MIN_CAL_SAMPLES,
- PER_MAX_LOG_COUNT,
- ath9k_hw_adc_gaincal_collect,
- ath9k_hw_adc_gaincal_calibrate
-};
-static const struct hal_percal_data adc_dc_cal_multi_sample = {
- ADC_DC_CAL,
- MAX_CAL_SAMPLES,
- PER_MIN_LOG_COUNT,
- ath9k_hw_adc_dccal_collect,
- ath9k_hw_adc_dccal_calibrate
-};
-static const struct hal_percal_data adc_dc_cal_single_sample = {
- ADC_DC_CAL,
- MIN_CAL_SAMPLES,
- PER_MAX_LOG_COUNT,
- ath9k_hw_adc_dccal_collect,
- ath9k_hw_adc_dccal_calibrate
-};
-static const struct hal_percal_data adc_init_dc_cal = {
- ADC_DC_INIT_CAL,
- MIN_CAL_SAMPLES,
- INIT_LOG_COUNT,
- ath9k_hw_adc_dccal_collect,
- ath9k_hw_adc_dccal_calibrate
-};
-
-static struct ath9k_rate_table ar5416_11a_table = {
- 8,
- {0},
- {
- {true, PHY_OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 0},
- {true, PHY_OFDM, 9000, 0x0f, 0x00, 18, 0},
- {true, PHY_OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 2},
- {true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 2},
- {true, PHY_OFDM, 24000, 0x09, 0x00, (0x80 | 48), 4},
- {true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 4},
- {true, PHY_OFDM, 48000, 0x08, 0x00, 96, 4},
- {true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 4}
- },
-};
-
-static struct ath9k_rate_table ar5416_11b_table = {
- 4,
- {0},
- {
- {true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0},
- {true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1},
- {true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 1},
- {true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 1}
- },
-};
-
-static struct ath9k_rate_table ar5416_11g_table = {
- 12,
- {0},
- {
- {true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0},
- {true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1},
- {true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 2},
- {true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 3},
-
- {false, PHY_OFDM, 6000, 0x0b, 0x00, 12, 4},
- {false, PHY_OFDM, 9000, 0x0f, 0x00, 18, 4},
- {true, PHY_OFDM, 12000, 0x0a, 0x00, 24, 6},
- {true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 6},
- {true, PHY_OFDM, 24000, 0x09, 0x00, 48, 8},
- {true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 8},
- {true, PHY_OFDM, 48000, 0x08, 0x00, 96, 8},
- {true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 8}
- },
-};
-
-static struct ath9k_rate_table ar5416_11ng_table = {
- 28,
- {0},
- {
- {true, PHY_CCK, 1000, 0x1b, 0x00, (0x80 | 2), 0},
- {true, PHY_CCK, 2000, 0x1a, 0x04, (0x80 | 4), 1},
- {true, PHY_CCK, 5500, 0x19, 0x04, (0x80 | 11), 2},
- {true, PHY_CCK, 11000, 0x18, 0x04, (0x80 | 22), 3},
-
- {false, PHY_OFDM, 6000, 0x0b, 0x00, 12, 4},
- {false, PHY_OFDM, 9000, 0x0f, 0x00, 18, 4},
- {true, PHY_OFDM, 12000, 0x0a, 0x00, 24, 6},
- {true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 6},
- {true, PHY_OFDM, 24000, 0x09, 0x00, 48, 8},
- {true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 8},
- {true, PHY_OFDM, 48000, 0x08, 0x00, 96, 8},
- {true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 8},
- {true, PHY_HT, 6500, 0x80, 0x00, 0, 4},
- {true, PHY_HT, 13000, 0x81, 0x00, 1, 6},
- {true, PHY_HT, 19500, 0x82, 0x00, 2, 6},
- {true, PHY_HT, 26000, 0x83, 0x00, 3, 8},
- {true, PHY_HT, 39000, 0x84, 0x00, 4, 8},
- {true, PHY_HT, 52000, 0x85, 0x00, 5, 8},
- {true, PHY_HT, 58500, 0x86, 0x00, 6, 8},
- {true, PHY_HT, 65000, 0x87, 0x00, 7, 8},
- {true, PHY_HT, 13000, 0x88, 0x00, 8, 4},
- {true, PHY_HT, 26000, 0x89, 0x00, 9, 6},
- {true, PHY_HT, 39000, 0x8a, 0x00, 10, 6},
- {true, PHY_HT, 52000, 0x8b, 0x00, 11, 8},
- {true, PHY_HT, 78000, 0x8c, 0x00, 12, 8},
- {true, PHY_HT, 104000, 0x8d, 0x00, 13, 8},
- {true, PHY_HT, 117000, 0x8e, 0x00, 14, 8},
- {true, PHY_HT, 130000, 0x8f, 0x00, 15, 8},
- },
-};
-
-static struct ath9k_rate_table ar5416_11na_table = {
- 24,
- {0},
- {
- {true, PHY_OFDM, 6000, 0x0b, 0x00, (0x80 | 12), 0},
- {true, PHY_OFDM, 9000, 0x0f, 0x00, 18, 0},
- {true, PHY_OFDM, 12000, 0x0a, 0x00, (0x80 | 24), 2},
- {true, PHY_OFDM, 18000, 0x0e, 0x00, 36, 2},
- {true, PHY_OFDM, 24000, 0x09, 0x00, (0x80 | 48), 4},
- {true, PHY_OFDM, 36000, 0x0d, 0x00, 72, 4},
- {true, PHY_OFDM, 48000, 0x08, 0x00, 96, 4},
- {true, PHY_OFDM, 54000, 0x0c, 0x00, 108, 4},
- {true, PHY_HT, 6500, 0x80, 0x00, 0, 0},
- {true, PHY_HT, 13000, 0x81, 0x00, 1, 2},
- {true, PHY_HT, 19500, 0x82, 0x00, 2, 2},
- {true, PHY_HT, 26000, 0x83, 0x00, 3, 4},
- {true, PHY_HT, 39000, 0x84, 0x00, 4, 4},
- {true, PHY_HT, 52000, 0x85, 0x00, 5, 4},
- {true, PHY_HT, 58500, 0x86, 0x00, 6, 4},
- {true, PHY_HT, 65000, 0x87, 0x00, 7, 4},
- {true, PHY_HT, 13000, 0x88, 0x00, 8, 0},
- {true, PHY_HT, 26000, 0x89, 0x00, 9, 2},
- {true, PHY_HT, 39000, 0x8a, 0x00, 10, 2},
- {true, PHY_HT, 52000, 0x8b, 0x00, 11, 4},
- {true, PHY_HT, 78000, 0x8c, 0x00, 12, 4},
- {true, PHY_HT, 104000, 0x8d, 0x00, 13, 4},
- {true, PHY_HT, 117000, 0x8e, 0x00, 14, 4},
- {true, PHY_HT, 130000, 0x8f, 0x00, 15, 4},
- },
-};
-
-static enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah,
- const struct ath9k_channel *chan)
-{
- if (IS_CHAN_CCK(chan))
- return ATH9K_MODE_11A;
- if (IS_CHAN_G(chan))
- return ATH9K_MODE_11G;
- return ATH9K_MODE_11A;
-}
-static bool ath9k_hw_wait(struct ath_hal *ah,
- u32 reg,
- u32 mask,
- u32 val)
-{
- int i;
+extern struct hal_percal_data iq_cal_multi_sample;
+extern struct hal_percal_data iq_cal_single_sample;
+extern struct hal_percal_data adc_gain_cal_multi_sample;
+extern struct hal_percal_data adc_gain_cal_single_sample;
+extern struct hal_percal_data adc_dc_cal_multi_sample;
+extern struct hal_percal_data adc_dc_cal_single_sample;
+extern struct hal_percal_data adc_init_dc_cal;
- for (i = 0; i < (AH_TIMEOUT / AH_TIME_QUANTUM); i++) {
- if ((REG_READ(ah, reg) & mask) == val)
- return true;
+static bool ath9k_hw_set_reset_reg(struct ath_hal *ah, u32 type);
+static void ath9k_hw_set_regs(struct ath_hal *ah, struct ath9k_channel *chan,
+ enum ath9k_ht_macmode macmode);
+static u32 ath9k_hw_ini_fixup(struct ath_hal *ah,
+ struct ar5416_eeprom_def *pEepData,
+ u32 reg, u32 value);
+static void ath9k_hw_9280_spur_mitigate(struct ath_hal *ah, struct ath9k_channel *chan);
+static void ath9k_hw_spur_mitigate(struct ath_hal *ah, struct ath9k_channel *chan);
- udelay(AH_TIME_QUANTUM);
- }
- DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO,
- "%s: timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
- __func__, reg, REG_READ(ah, reg), mask, val);
- return false;
-}
+/********************/
+/* Helper Functions */
+/********************/
-static bool ath9k_hw_eeprom_read(struct ath_hal *ah, u32 off,
- u16 *data)
+static u32 ath9k_hw_mac_usec(struct ath_hal *ah, u32 clks)
{
- (void) REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S));
-
- if (!ath9k_hw_wait(ah,
- AR_EEPROM_STATUS_DATA,
- AR_EEPROM_STATUS_DATA_BUSY |
- AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0)) {
- return false;
- }
-
- *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA),
- AR_EEPROM_STATUS_DATA_VAL);
-
- return true;
+ if (ah->ah_curchan != NULL)
+ return clks / CLOCK_RATE[ath9k_hw_chan2wmode(ah, ah->ah_curchan)];
+ else
+ return clks / CLOCK_RATE[ATH9K_MODE_11B];
}
-static int ath9k_hw_flash_map(struct ath_hal *ah)
+static u32 ath9k_hw_mac_to_usec(struct ath_hal *ah, u32 clks)
{
- struct ath_hal_5416 *ahp = AH5416(ah);
-
- ahp->ah_cal_mem = ioremap(AR5416_EEPROM_START_ADDR, AR5416_EEPROM_MAX);
+ struct ath9k_channel *chan = ah->ah_curchan;
- if (!ahp->ah_cal_mem) {
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "%s: cannot remap eeprom region \n", __func__);
- return -EIO;
- }
+ if (chan && IS_CHAN_HT40(chan))
+ return ath9k_hw_mac_usec(ah, clks) / 2;
+ else
+ return ath9k_hw_mac_usec(ah, clks);
+}
- return 0;
+static u32 ath9k_hw_mac_clks(struct ath_hal *ah, u32 usecs)
+{
+ if (ah->ah_curchan != NULL)
+ return usecs * CLOCK_RATE[ath9k_hw_chan2wmode(ah,
+ ah->ah_curchan)];
+ else
+ return usecs * CLOCK_RATE[ATH9K_MODE_11B];
}
-static bool ath9k_hw_flash_read(struct ath_hal *ah, u32 off,
- u16 *data)
+static u32 ath9k_hw_mac_to_clks(struct ath_hal *ah, u32 usecs)
{
- struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_channel *chan = ah->ah_curchan;
- *data = ioread16(ahp->ah_cal_mem + off);
- return true;
+ if (chan && IS_CHAN_HT40(chan))
+ return ath9k_hw_mac_clks(ah, usecs) * 2;
+ else
+ return ath9k_hw_mac_clks(ah, usecs);
}
-static void ath9k_hw_read_revisions(struct ath_hal *ah)
+enum wireless_mode ath9k_hw_chan2wmode(struct ath_hal *ah,
+ const struct ath9k_channel *chan)
{
- u32 val;
-
- val = REG_READ(ah, AR_SREV) & AR_SREV_ID;
+ if (IS_CHAN_B(chan))
+ return ATH9K_MODE_11B;
+ if (IS_CHAN_G(chan))
+ return ATH9K_MODE_11G;
- if (val == 0xFF) {
- val = REG_READ(ah, AR_SREV);
+ return ATH9K_MODE_11A;
+}
- ah->ah_macVersion =
- (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S;
+bool ath9k_hw_wait(struct ath_hal *ah, u32 reg, u32 mask, u32 val)
+{
+ int i;
- ah->ah_macRev = MS(val, AR_SREV_REVISION2);
- ah->ah_isPciExpress =
- (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1;
+ for (i = 0; i < (AH_TIMEOUT / AH_TIME_QUANTUM); i++) {
+ if ((REG_READ(ah, reg) & mask) == val)
+ return true;
- } else {
- if (!AR_SREV_9100(ah))
- ah->ah_macVersion = MS(val, AR_SREV_VERSION);
+ udelay(AH_TIME_QUANTUM);
+ }
- ah->ah_macRev = val & AR_SREV_REVISION;
+ DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+ "timeout on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n",
+ reg, REG_READ(ah, reg), mask, val);
- if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCIE)
- ah->ah_isPciExpress = true;
- }
+ return false;
}
u32 ath9k_hw_reverse_bits(u32 val, u32 n)
@@ -308,596 +124,215 @@ u32 ath9k_hw_reverse_bits(u32 val, u32 n)
return retval;
}
-static void ath9k_hw_set_defaults(struct ath_hal *ah)
+bool ath9k_get_channel_edges(struct ath_hal *ah,
+ u16 flags, u16 *low,
+ u16 *high)
{
- int i;
-
- ah->ah_config.dma_beacon_response_time = 2;
- ah->ah_config.sw_beacon_response_time = 10;
- ah->ah_config.additional_swba_backoff = 0;
- ah->ah_config.ack_6mb = 0x0;
- ah->ah_config.cwm_ignore_extcca = 0;
- ah->ah_config.pcie_powersave_enable = 0;
- ah->ah_config.pcie_l1skp_enable = 0;
- ah->ah_config.pcie_clock_req = 0;
- ah->ah_config.pcie_power_reset = 0x100;
- ah->ah_config.pcie_restore = 0;
- ah->ah_config.pcie_waen = 0;
- ah->ah_config.analog_shiftreg = 1;
- ah->ah_config.ht_enable = 1;
- ah->ah_config.ofdm_trig_low = 200;
- ah->ah_config.ofdm_trig_high = 500;
- ah->ah_config.cck_trig_high = 200;
- ah->ah_config.cck_trig_low = 100;
- ah->ah_config.enable_ani = 1;
- ah->ah_config.noise_immunity_level = 4;
- ah->ah_config.ofdm_weaksignal_det = 1;
- ah->ah_config.cck_weaksignal_thr = 0;
- ah->ah_config.spur_immunity_level = 2;
- ah->ah_config.firstep_level = 0;
- ah->ah_config.rssi_thr_high = 40;
- ah->ah_config.rssi_thr_low = 7;
- ah->ah_config.diversity_control = 0;
- ah->ah_config.antenna_switch_swap = 0;
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
- for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
- ah->ah_config.spurchans[i][0] = AR_NO_SPUR;
- ah->ah_config.spurchans[i][1] = AR_NO_SPUR;
+ if (flags & CHANNEL_5GHZ) {
+ *low = pCap->low_5ghz_chan;
+ *high = pCap->high_5ghz_chan;
+ return true;
}
-
- ah->ah_config.intr_mitigation = 0;
-}
-
-static void ath9k_hw_override_ini(struct ath_hal *ah,
- struct ath9k_channel *chan)
-{
- if (!AR_SREV_5416_V20_OR_LATER(ah)
- || AR_SREV_9280_10_OR_LATER(ah))
- return;
-
- REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
-}
-
-static void ath9k_hw_init_bb(struct ath_hal *ah,
- struct ath9k_channel *chan)
-{
- u32 synthDelay;
-
- synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
- if (IS_CHAN_CCK(chan))
- synthDelay = (4 * synthDelay) / 22;
- else
- synthDelay /= 10;
-
- REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
-
- udelay(synthDelay + BASE_ACTIVATE_DELAY);
-}
-
-static void ath9k_hw_init_interrupt_masks(struct ath_hal *ah,
- enum ath9k_opmode opmode)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
-
- ahp->ah_maskReg = AR_IMR_TXERR |
- AR_IMR_TXURN |
- AR_IMR_RXERR |
- AR_IMR_RXORN |
- AR_IMR_BCNMISC;
-
- if (ahp->ah_intrMitigation)
- ahp->ah_maskReg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
- else
- ahp->ah_maskReg |= AR_IMR_RXOK;
-
- ahp->ah_maskReg |= AR_IMR_TXOK;
-
- if (opmode == ATH9K_M_HOSTAP)
- ahp->ah_maskReg |= AR_IMR_MIB;
-
- REG_WRITE(ah, AR_IMR, ahp->ah_maskReg);
- REG_WRITE(ah, AR_IMR_S2, REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT);
-
- if (!AR_SREV_9100(ah)) {
- REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF);
- REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT);
- REG_WRITE(ah, AR_INTR_SYNC_MASK, 0);
+ if ((flags & CHANNEL_2GHZ)) {
+ *low = pCap->low_2ghz_chan;
+ *high = pCap->high_2ghz_chan;
+ return true;
}
+ return false;
}
-static void ath9k_hw_init_qos(struct ath_hal *ah)
-{
- REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa);
- REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210);
-
- REG_WRITE(ah, AR_QOS_NO_ACK,
- SM(2, AR_QOS_NO_ACK_TWO_BIT) |
- SM(5, AR_QOS_NO_ACK_BIT_OFF) |
- SM(0, AR_QOS_NO_ACK_BYTE_OFF));
-
- REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL);
- REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF);
- REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF);
- REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF);
- REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
-}
-
-static void ath9k_hw_analog_shift_rmw(struct ath_hal *ah,
- u32 reg,
- u32 mask,
- u32 shift,
- u32 val)
-{
- u32 regVal;
-
- regVal = REG_READ(ah, reg) & ~mask;
- regVal |= (val << shift) & mask;
-
- REG_WRITE(ah, reg, regVal);
-
- if (ah->ah_config.analog_shiftreg)
- udelay(100);
-
- return;
-}
-
-static u8 ath9k_hw_get_num_ant_config(struct ath_hal_5416 *ahp,
- enum ieee80211_band freq_band)
+u16 ath9k_hw_computetxtime(struct ath_hal *ah,
+ struct ath_rate_table *rates,
+ u32 frameLen, u16 rateix,
+ bool shortPreamble)
{
- struct ar5416_eeprom *eep = &ahp->ah_eeprom;
- struct modal_eep_header *pModal =
- &(eep->modalHeader[IEEE80211_BAND_5GHZ == freq_band]);
- struct base_eep_header *pBase = &eep->baseEepHeader;
- u8 num_ant_config;
-
- num_ant_config = 1;
-
- if (pBase->version >= 0x0E0D)
- if (pModal->useAnt1)
- num_ant_config += 1;
-
- return num_ant_config;
-}
+ u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
+ u32 kbps;
-static int
-ath9k_hw_get_eeprom_antenna_cfg(struct ath_hal_5416 *ahp,
- struct ath9k_channel *chan,
- u8 index,
- u16 *config)
-{
- struct ar5416_eeprom *eep = &ahp->ah_eeprom;
- struct modal_eep_header *pModal =
- &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
- struct base_eep_header *pBase = &eep->baseEepHeader;
+ kbps = rates->info[rateix].ratekbps;
- switch (index) {
- case 0:
- *config = pModal->antCtrlCommon & 0xFFFF;
+ if (kbps == 0)
return 0;
- case 1:
- if (pBase->version >= 0x0E0D) {
- if (pModal->useAnt1) {
- *config =
- ((pModal->antCtrlCommon & 0xFFFF0000) >> 16);
- return 0;
- }
+
+ switch (rates->info[rateix].phy) {
+ case WLAN_RC_PHY_CCK:
+ phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
+ if (shortPreamble && rates->info[rateix].short_preamble)
+ phyTime >>= 1;
+ numBits = frameLen << 3;
+ txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps);
+ break;
+ case WLAN_RC_PHY_OFDM:
+ if (ah->ah_curchan && IS_CHAN_QUARTER_RATE(ah->ah_curchan)) {
+ bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000;
+ numBits = OFDM_PLCP_BITS + (frameLen << 3);
+ numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
+ txTime = OFDM_SIFS_TIME_QUARTER
+ + OFDM_PREAMBLE_TIME_QUARTER
+ + (numSymbols * OFDM_SYMBOL_TIME_QUARTER);
+ } else if (ah->ah_curchan &&
+ IS_CHAN_HALF_RATE(ah->ah_curchan)) {
+ bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_HALF) / 1000;
+ numBits = OFDM_PLCP_BITS + (frameLen << 3);
+ numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
+ txTime = OFDM_SIFS_TIME_HALF +
+ OFDM_PREAMBLE_TIME_HALF
+ + (numSymbols * OFDM_SYMBOL_TIME_HALF);
+ } else {
+ bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
+ numBits = OFDM_PLCP_BITS + (frameLen << 3);
+ numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
+ txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME
+ + (numSymbols * OFDM_SYMBOL_TIME);
}
break;
default:
+ DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+ "Unknown phy %u (rate ix %u)\n",
+ rates->info[rateix].phy, rateix);
+ txTime = 0;
break;
}
- return -EINVAL;
-}
-
-static inline bool ath9k_hw_nvram_read(struct ath_hal *ah,
- u32 off,
- u16 *data)
-{
- if (ath9k_hw_use_flash(ah))
- return ath9k_hw_flash_read(ah, off, data);
- else
- return ath9k_hw_eeprom_read(ah, off, data);
+ return txTime;
}
-static bool ath9k_hw_fill_eeprom(struct ath_hal *ah)
+u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags)
{
- struct ath_hal_5416 *ahp = AH5416(ah);
- struct ar5416_eeprom *eep = &ahp->ah_eeprom;
- u16 *eep_data;
- int addr, ar5416_eep_start_loc = 0;
-
- if (!ath9k_hw_use_flash(ah)) {
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "%s: Reading from EEPROM, not flash\n", __func__);
- ar5416_eep_start_loc = 256;
- }
- if (AR_SREV_9100(ah))
- ar5416_eep_start_loc = 256;
-
- eep_data = (u16 *) eep;
- for (addr = 0;
- addr < sizeof(struct ar5416_eeprom) / sizeof(u16);
- addr++) {
- if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc,
- eep_data)) {
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "%s: Unable to read eeprom region \n",
- __func__);
- return false;
+ if (flags & CHANNEL_2GHZ) {
+ if (freq == 2484)
+ return 14;
+ if (freq < 2484)
+ return (freq - 2407) / 5;
+ else
+ return 15 + ((freq - 2512) / 20);
+ } else if (flags & CHANNEL_5GHZ) {
+ if (ath9k_regd_is_public_safety_sku(ah) &&
+ IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
+ return ((freq * 10) +
+ (((freq % 5) == 2) ? 5 : 0) - 49400) / 5;
+ } else if ((flags & CHANNEL_A) && (freq <= 5000)) {
+ return (freq - 4000) / 5;
+ } else {
+ return (freq - 5000) / 5;
+ }
+ } else {
+ if (freq == 2484)
+ return 14;
+ if (freq < 2484)
+ return (freq - 2407) / 5;
+ if (freq < 5000) {
+ if (ath9k_regd_is_public_safety_sku(ah)
+ && IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
+ return ((freq * 10) +
+ (((freq % 5) ==
+ 2) ? 5 : 0) - 49400) / 5;
+ } else if (freq > 4900) {
+ return (freq - 4000) / 5;
+ } else {
+ return 15 + ((freq - 2512) / 20);
+ }
}
- eep_data++;
+ return (freq - 5000) / 5;
}
- return true;
}
-/* XXX: Clean me up, make me more legible */
-static bool
-ath9k_hw_eeprom_set_board_values(struct ath_hal *ah,
- struct ath9k_channel *chan)
+void ath9k_hw_get_channel_centers(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ struct chan_centers *centers)
{
- struct modal_eep_header *pModal;
- int i, regChainOffset;
+ int8_t extoff;
struct ath_hal_5416 *ahp = AH5416(ah);
- struct ar5416_eeprom *eep = &ahp->ah_eeprom;
- u8 txRxAttenLocal;
- u16 ant_config;
- pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
+ if (!IS_CHAN_HT40(chan)) {
+ centers->ctl_center = centers->ext_center =
+ centers->synth_center = chan->channel;
+ return;
+ }
- txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44;
+ if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
+ (chan->chanmode == CHANNEL_G_HT40PLUS)) {
+ centers->synth_center =
+ chan->channel + HT40_CHANNEL_CENTER_SHIFT;
+ extoff = 1;
+ } else {
+ centers->synth_center =
+ chan->channel - HT40_CHANNEL_CENTER_SHIFT;
+ extoff = -1;
+ }
- ath9k_hw_get_eeprom_antenna_cfg(ahp, chan, 1, &ant_config);
- REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
+ centers->ctl_center =
+ centers->synth_center - (extoff * HT40_CHANNEL_CENTER_SHIFT);
+ centers->ext_center =
+ centers->synth_center + (extoff *
+ ((ahp->ah_extprotspacing == ATH9K_HT_EXTPROTSPACING_20) ?
+ HT40_CHANNEL_CENTER_SHIFT : 15));
- for (i = 0; i < AR5416_MAX_CHAINS; i++) {
- if (AR_SREV_9280(ah)) {
- if (i >= 2)
- break;
- }
+}
- if (AR_SREV_5416_V20_OR_LATER(ah) &&
- (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5)
- && (i != 0))
- regChainOffset = (i == 1) ? 0x2000 : 0x1000;
- else
- regChainOffset = i * 0x1000;
-
- REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset,
- pModal->antCtrlChain[i]);
-
- REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset,
- (REG_READ(ah,
- AR_PHY_TIMING_CTRL4(0) +
- regChainOffset) &
- ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF |
- AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) |
- SM(pModal->iqCalICh[i],
- AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) |
- SM(pModal->iqCalQCh[i],
- AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF));
-
- if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
- if ((eep->baseEepHeader.version &
- AR5416_EEP_VER_MINOR_MASK) >=
- AR5416_EEP_MINOR_VER_3) {
- txRxAttenLocal = pModal->txRxAttenCh[i];
- if (AR_SREV_9280_10_OR_LATER(ah)) {
- REG_RMW_FIELD(ah,
- AR_PHY_GAIN_2GHZ +
- regChainOffset,
- AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN,
- pModal->
- bswMargin[i]);
- REG_RMW_FIELD(ah,
- AR_PHY_GAIN_2GHZ +
- regChainOffset,
- AR_PHY_GAIN_2GHZ_XATTEN1_DB,
- pModal->
- bswAtten[i]);
- REG_RMW_FIELD(ah,
- AR_PHY_GAIN_2GHZ +
- regChainOffset,
- AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN,
- pModal->
- xatten2Margin[i]);
- REG_RMW_FIELD(ah,
- AR_PHY_GAIN_2GHZ +
- regChainOffset,
- AR_PHY_GAIN_2GHZ_XATTEN2_DB,
- pModal->
- xatten2Db[i]);
- } else {
- REG_WRITE(ah,
- AR_PHY_GAIN_2GHZ +
- regChainOffset,
- (REG_READ(ah,
- AR_PHY_GAIN_2GHZ +
- regChainOffset) &
- ~AR_PHY_GAIN_2GHZ_BSW_MARGIN)
- | SM(pModal->
- bswMargin[i],
- AR_PHY_GAIN_2GHZ_BSW_MARGIN));
- REG_WRITE(ah,
- AR_PHY_GAIN_2GHZ +
- regChainOffset,
- (REG_READ(ah,
- AR_PHY_GAIN_2GHZ +
- regChainOffset) &
- ~AR_PHY_GAIN_2GHZ_BSW_ATTEN)
- | SM(pModal->bswAtten[i],
- AR_PHY_GAIN_2GHZ_BSW_ATTEN));
- }
- }
- if (AR_SREV_9280_10_OR_LATER(ah)) {
- REG_RMW_FIELD(ah,
- AR_PHY_RXGAIN +
- regChainOffset,
- AR9280_PHY_RXGAIN_TXRX_ATTEN,
- txRxAttenLocal);
- REG_RMW_FIELD(ah,
- AR_PHY_RXGAIN +
- regChainOffset,
- AR9280_PHY_RXGAIN_TXRX_MARGIN,
- pModal->rxTxMarginCh[i]);
- } else {
- REG_WRITE(ah,
- AR_PHY_RXGAIN + regChainOffset,
- (REG_READ(ah,
- AR_PHY_RXGAIN +
- regChainOffset) &
- ~AR_PHY_RXGAIN_TXRX_ATTEN) |
- SM(txRxAttenLocal,
- AR_PHY_RXGAIN_TXRX_ATTEN));
- REG_WRITE(ah,
- AR_PHY_GAIN_2GHZ +
- regChainOffset,
- (REG_READ(ah,
- AR_PHY_GAIN_2GHZ +
- regChainOffset) &
- ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) |
- SM(pModal->rxTxMarginCh[i],
- AR_PHY_GAIN_2GHZ_RXTX_MARGIN));
- }
- }
- }
+/******************/
+/* Chip Revisions */
+/******************/
- if (AR_SREV_9280_10_OR_LATER(ah)) {
- if (IS_CHAN_2GHZ(chan)) {
- ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
- AR_AN_RF2G1_CH0_OB,
- AR_AN_RF2G1_CH0_OB_S,
- pModal->ob);
- ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0,
- AR_AN_RF2G1_CH0_DB,
- AR_AN_RF2G1_CH0_DB_S,
- pModal->db);
- ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
- AR_AN_RF2G1_CH1_OB,
- AR_AN_RF2G1_CH1_OB_S,
- pModal->ob_ch1);
- ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1,
- AR_AN_RF2G1_CH1_DB,
- AR_AN_RF2G1_CH1_DB_S,
- pModal->db_ch1);
- } else {
- ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
- AR_AN_RF5G1_CH0_OB5,
- AR_AN_RF5G1_CH0_OB5_S,
- pModal->ob);
- ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0,
- AR_AN_RF5G1_CH0_DB5,
- AR_AN_RF5G1_CH0_DB5_S,
- pModal->db);
- ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
- AR_AN_RF5G1_CH1_OB5,
- AR_AN_RF5G1_CH1_OB5_S,
- pModal->ob_ch1);
- ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1,
- AR_AN_RF5G1_CH1_DB5,
- AR_AN_RF5G1_CH1_DB5_S,
- pModal->db_ch1);
- }
- ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
- AR_AN_TOP2_XPABIAS_LVL,
- AR_AN_TOP2_XPABIAS_LVL_S,
- pModal->xpaBiasLvl);
- ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2,
- AR_AN_TOP2_LOCALBIAS,
- AR_AN_TOP2_LOCALBIAS_S,
- pModal->local_bias);
- DPRINTF(ah->ah_sc, ATH_DBG_ANY, "ForceXPAon: %d\n",
- pModal->force_xpaon);
- REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG,
- pModal->force_xpaon);
- }
+static void ath9k_hw_read_revisions(struct ath_hal *ah)
+{
+ u32 val;
- REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH,
- pModal->switchSettling);
- REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC,
- pModal->adcDesiredSize);
+ val = REG_READ(ah, AR_SREV) & AR_SREV_ID;
- if (!AR_SREV_9280_10_OR_LATER(ah))
- REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
- AR_PHY_DESIRED_SZ_PGA,
- pModal->pgaDesiredSize);
-
- REG_WRITE(ah, AR_PHY_RF_CTL4,
- SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF)
- | SM(pModal->txEndToXpaOff,
- AR_PHY_RF_CTL4_TX_END_XPAB_OFF)
- | SM(pModal->txFrameToXpaOn,
- AR_PHY_RF_CTL4_FRAME_XPAA_ON)
- | SM(pModal->txFrameToXpaOn,
- AR_PHY_RF_CTL4_FRAME_XPAB_ON));
-
- REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON,
- pModal->txEndToRxOn);
- if (AR_SREV_9280_10_OR_LATER(ah)) {
- REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62,
- pModal->thresh62);
- REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0,
- AR_PHY_EXT_CCA0_THRESH62,
- pModal->thresh62);
+ if (val == 0xFF) {
+ val = REG_READ(ah, AR_SREV);
+ ah->ah_macVersion = (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S;
+ ah->ah_macRev = MS(val, AR_SREV_REVISION2);
+ ah->ah_isPciExpress = (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1;
} else {
- REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62,
- pModal->thresh62);
- REG_RMW_FIELD(ah, AR_PHY_EXT_CCA,
- AR_PHY_EXT_CCA_THRESH62,
- pModal->thresh62);
- }
+ if (!AR_SREV_9100(ah))
+ ah->ah_macVersion = MS(val, AR_SREV_VERSION);
- if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
- AR5416_EEP_MINOR_VER_2) {
- REG_RMW_FIELD(ah, AR_PHY_RF_CTL2,
- AR_PHY_TX_END_DATA_START,
- pModal->txFrameToDataStart);
- REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON,
- pModal->txFrameToPaOn);
- }
+ ah->ah_macRev = val & AR_SREV_REVISION;
- if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >=
- AR5416_EEP_MINOR_VER_3) {
- if (IS_CHAN_HT40(chan))
- REG_RMW_FIELD(ah, AR_PHY_SETTLING,
- AR_PHY_SETTLING_SWITCH,
- pModal->swSettleHt40);
+ if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCIE)
+ ah->ah_isPciExpress = true;
}
-
- return true;
}
-static int ath9k_hw_check_eeprom(struct ath_hal *ah)
+static int ath9k_hw_get_radiorev(struct ath_hal *ah)
{
- u32 sum = 0, el;
- u16 *eepdata;
+ u32 val;
int i;
- struct ath_hal_5416 *ahp = AH5416(ah);
- bool need_swap = false;
- struct ar5416_eeprom *eep =
- (struct ar5416_eeprom *) &ahp->ah_eeprom;
-
- if (!ath9k_hw_use_flash(ah)) {
- u16 magic, magic2;
- int addr;
-
- if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET,
- &magic)) {
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "%s: Reading Magic # failed\n", __func__);
- return false;
- }
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "%s: Read Magic = 0x%04X\n",
- __func__, magic);
-
- if (magic != AR5416_EEPROM_MAGIC) {
- magic2 = swab16(magic);
-
- if (magic2 == AR5416_EEPROM_MAGIC) {
- need_swap = true;
- eepdata = (u16 *) (&ahp->ah_eeprom);
-
- for (addr = 0;
- addr <
- sizeof(struct ar5416_eeprom) /
- sizeof(u16); addr++) {
- u16 temp;
-
- temp = swab16(*eepdata);
- *eepdata = temp;
- eepdata++;
-
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "0x%04X ", *eepdata);
- if (((addr + 1) % 6) == 0)
- DPRINTF(ah->ah_sc,
- ATH_DBG_EEPROM,
- "\n");
- }
- } else {
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "Invalid EEPROM Magic. "
- "endianness missmatch.\n");
- return -EINVAL;
- }
- }
- }
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n",
- need_swap ? "True" : "False");
-
- if (need_swap)
- el = swab16(ahp->ah_eeprom.baseEepHeader.length);
- else
- el = ahp->ah_eeprom.baseEepHeader.length;
-
- if (el > sizeof(struct ar5416_eeprom))
- el = sizeof(struct ar5416_eeprom) / sizeof(u16);
- else
- el = el / sizeof(u16);
-
- eepdata = (u16 *) (&ahp->ah_eeprom);
-
- for (i = 0; i < el; i++)
- sum ^= *eepdata++;
-
- if (need_swap) {
- u32 integer, j;
- u16 word;
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "EEPROM Endianness is not native.. Changing \n");
-
- word = swab16(eep->baseEepHeader.length);
- eep->baseEepHeader.length = word;
-
- word = swab16(eep->baseEepHeader.checksum);
- eep->baseEepHeader.checksum = word;
-
- word = swab16(eep->baseEepHeader.version);
- eep->baseEepHeader.version = word;
-
- word = swab16(eep->baseEepHeader.regDmn[0]);
- eep->baseEepHeader.regDmn[0] = word;
-
- word = swab16(eep->baseEepHeader.regDmn[1]);
- eep->baseEepHeader.regDmn[1] = word;
-
- word = swab16(eep->baseEepHeader.rfSilent);
- eep->baseEepHeader.rfSilent = word;
-
- word = swab16(eep->baseEepHeader.blueToothOptions);
- eep->baseEepHeader.blueToothOptions = word;
+ REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
- word = swab16(eep->baseEepHeader.deviceCap);
- eep->baseEepHeader.deviceCap = word;
+ for (i = 0; i < 8; i++)
+ REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
+ val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
+ val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
- for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) {
- struct modal_eep_header *pModal =
- &eep->modalHeader[j];
- integer = swab32(pModal->antCtrlCommon);
- pModal->antCtrlCommon = integer;
+ return ath9k_hw_reverse_bits(val, 8);
+}
- for (i = 0; i < AR5416_MAX_CHAINS; i++) {
- integer = swab32(pModal->antCtrlChain[i]);
- pModal->antCtrlChain[i] = integer;
- }
+/************************************/
+/* HW Attach, Detach, Init Routines */
+/************************************/
- for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) {
- word = swab16(pModal->spurChans[i].spurChan);
- pModal->spurChans[i].spurChan = word;
- }
- }
- }
+static void ath9k_hw_disablepcie(struct ath_hal *ah)
+{
+ if (!AR_SREV_9100(ah))
+ return;
- if (sum != 0xffff || ar5416_get_eep_ver(ahp) != AR5416_EEP_VER ||
- ar5416_get_eep_rev(ahp) < AR5416_EEP_NO_BACK_VER) {
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "Bad EEPROM checksum 0x%x or revision 0x%04x\n",
- sum, ar5416_get_eep_ver(ahp));
- return -EINVAL;
- }
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x57160824);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x25980579);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x00000000);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007);
- return 0;
+ REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
}
static bool ath9k_hw_chip_test(struct ath_hal *ah)
@@ -905,9 +340,9 @@ static bool ath9k_hw_chip_test(struct ath_hal *ah)
u32 regAddr[2] = { AR_STA_ID0, AR_PHY_BASE + (8 << 2) };
u32 regHold[2];
u32 patternData[4] = { 0x55555555,
- 0xaaaaaaaa,
- 0x66666666,
- 0x99999999 };
+ 0xaaaaaaaa,
+ 0x66666666,
+ 0x99999999 };
int i, j;
for (i = 0; i < 2; i++) {
@@ -921,9 +356,9 @@ static bool ath9k_hw_chip_test(struct ath_hal *ah)
rdData = REG_READ(ah, addr);
if (rdData != wrData) {
DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
- "%s: address test failed "
- "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
- __func__, addr, wrData, rdData);
+ "address test failed "
+ "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
+ addr, wrData, rdData);
return false;
}
}
@@ -933,9 +368,9 @@ static bool ath9k_hw_chip_test(struct ath_hal *ah)
rdData = REG_READ(ah, addr);
if (wrData != rdData) {
DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
- "%s: address test failed "
- "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
- __func__, addr, wrData, rdData);
+ "address test failed "
+ "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n",
+ addr, wrData, rdData);
return false;
}
}
@@ -945,213 +380,65 @@ static bool ath9k_hw_chip_test(struct ath_hal *ah)
return true;
}
-u32 ath9k_hw_getrxfilter(struct ath_hal *ah)
-{
- u32 bits = REG_READ(ah, AR_RX_FILTER);
- u32 phybits = REG_READ(ah, AR_PHY_ERR);
-
- if (phybits & AR_PHY_ERR_RADAR)
- bits |= ATH9K_RX_FILTER_PHYRADAR;
- if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING))
- bits |= ATH9K_RX_FILTER_PHYERR;
- return bits;
-}
-
-void ath9k_hw_setrxfilter(struct ath_hal *ah, u32 bits)
-{
- u32 phybits;
-
- REG_WRITE(ah, AR_RX_FILTER, (bits & 0xffff) | AR_RX_COMPR_BAR);
- phybits = 0;
- if (bits & ATH9K_RX_FILTER_PHYRADAR)
- phybits |= AR_PHY_ERR_RADAR;
- if (bits & ATH9K_RX_FILTER_PHYERR)
- phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING;
- REG_WRITE(ah, AR_PHY_ERR, phybits);
-
- if (phybits)
- REG_WRITE(ah, AR_RXCFG,
- REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA);
- else
- REG_WRITE(ah, AR_RXCFG,
- REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA);
-}
-
-bool ath9k_hw_setcapability(struct ath_hal *ah,
- enum ath9k_capability_type type,
- u32 capability,
- u32 setting,
- int *status)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- u32 v;
-
- switch (type) {
- case ATH9K_CAP_TKIP_MIC:
- if (setting)
- ahp->ah_staId1Defaults |=
- AR_STA_ID1_CRPT_MIC_ENABLE;
- else
- ahp->ah_staId1Defaults &=
- ~AR_STA_ID1_CRPT_MIC_ENABLE;
- return true;
- case ATH9K_CAP_DIVERSITY:
- v = REG_READ(ah, AR_PHY_CCK_DETECT);
- if (setting)
- v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
- else
- v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
- REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
- return true;
- case ATH9K_CAP_MCAST_KEYSRCH:
- if (setting)
- ahp->ah_staId1Defaults |= AR_STA_ID1_MCAST_KSRCH;
- else
- ahp->ah_staId1Defaults &= ~AR_STA_ID1_MCAST_KSRCH;
- return true;
- case ATH9K_CAP_TSF_ADJUST:
- if (setting)
- ahp->ah_miscMode |= AR_PCU_TX_ADD_TSF;
- else
- ahp->ah_miscMode &= ~AR_PCU_TX_ADD_TSF;
- return true;
- default:
- return false;
- }
-}
-
-void ath9k_hw_dmaRegDump(struct ath_hal *ah)
+static const char *ath9k_hw_devname(u16 devid)
{
- u32 val[ATH9K_NUM_DMA_DEBUG_REGS];
- int qcuOffset = 0, dcuOffset = 0;
- u32 *qcuBase = &val[0], *dcuBase = &val[4];
- int i;
-
- REG_WRITE(ah, AR_MACMISC,
- ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
- (AR_MACMISC_MISC_OBS_BUS_1 <<
- AR_MACMISC_MISC_OBS_BUS_MSB_S)));
-
- DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "Raw DMA Debug values:\n");
- for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) {
- if (i % 4 == 0)
- DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "\n");
-
- val[i] = REG_READ(ah, AR_DMADBG_0 + (i * sizeof(u32)));
- DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "%d: %08x ", i, val[i]);
- }
-
- DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "\n\n");
- DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
- "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
-
- for (i = 0; i < ATH9K_NUM_QUEUES;
- i++, qcuOffset += 4, dcuOffset += 5) {
- if (i == 8) {
- qcuOffset = 0;
- qcuBase++;
- }
-
- if (i == 6) {
- dcuOffset = 0;
- dcuBase++;
- }
-
- DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
- "%2d %2x %1x %2x %2x\n",
- i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
- (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset +
- 3),
- val[2] & (0x7 << (i * 3)) >> (i * 3),
- (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
+ switch (devid) {
+ case AR5416_DEVID_PCI:
+ return "Atheros 5416";
+ case AR5416_DEVID_PCIE:
+ return "Atheros 5418";
+ case AR9160_DEVID_PCI:
+ return "Atheros 9160";
+ case AR9280_DEVID_PCI:
+ case AR9280_DEVID_PCIE:
+ return "Atheros 9280";
+ case AR9285_DEVID_PCIE:
+ return "Atheros 9285";
}
- DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "\n");
- DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
- "qcu_stitch state: %2x qcu_fetch state: %2x\n",
- (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22);
- DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
- "qcu_complete state: %2x dcu_complete state: %2x\n",
- (val[3] & 0x1c000000) >> 26, (val[6] & 0x3));
- DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
- "dcu_arb state: %2x dcu_fp state: %2x\n",
- (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27);
- DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
- "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n",
- (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10);
- DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
- "txfifo_valid_0: %1d txfifo_valid_1: %1d\n",
- (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12);
- DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
- "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n",
- (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
-
- DPRINTF(ah->ah_sc, ATH_DBG_REG_IO, "pcu observe 0x%x \n",
- REG_READ(ah, AR_OBS_BUS_1));
- DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
- "AR_CR 0x%x \n", REG_READ(ah, AR_CR));
+ return NULL;
}
-u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hal *ah,
- u32 *rxc_pcnt,
- u32 *rxf_pcnt,
- u32 *txf_pcnt)
+static void ath9k_hw_set_defaults(struct ath_hal *ah)
{
- static u32 cycles, rx_clear, rx_frame, tx_frame;
- u32 good = 1;
+ int i;
- u32 rc = REG_READ(ah, AR_RCCNT);
- u32 rf = REG_READ(ah, AR_RFCNT);
- u32 tf = REG_READ(ah, AR_TFCNT);
- u32 cc = REG_READ(ah, AR_CCCNT);
+ ah->ah_config.dma_beacon_response_time = 2;
+ ah->ah_config.sw_beacon_response_time = 10;
+ ah->ah_config.additional_swba_backoff = 0;
+ ah->ah_config.ack_6mb = 0x0;
+ ah->ah_config.cwm_ignore_extcca = 0;
+ ah->ah_config.pcie_powersave_enable = 0;
+ ah->ah_config.pcie_l1skp_enable = 0;
+ ah->ah_config.pcie_clock_req = 0;
+ ah->ah_config.pcie_power_reset = 0x100;
+ ah->ah_config.pcie_restore = 0;
+ ah->ah_config.pcie_waen = 0;
+ ah->ah_config.analog_shiftreg = 1;
+ ah->ah_config.ht_enable = 1;
+ ah->ah_config.ofdm_trig_low = 200;
+ ah->ah_config.ofdm_trig_high = 500;
+ ah->ah_config.cck_trig_high = 200;
+ ah->ah_config.cck_trig_low = 100;
+ ah->ah_config.enable_ani = 1;
+ ah->ah_config.noise_immunity_level = 4;
+ ah->ah_config.ofdm_weaksignal_det = 1;
+ ah->ah_config.cck_weaksignal_thr = 0;
+ ah->ah_config.spur_immunity_level = 2;
+ ah->ah_config.firstep_level = 0;
+ ah->ah_config.rssi_thr_high = 40;
+ ah->ah_config.rssi_thr_low = 7;
+ ah->ah_config.diversity_control = 0;
+ ah->ah_config.antenna_switch_swap = 0;
- if (cycles == 0 || cycles > cc) {
- DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
- "%s: cycle counter wrap. ExtBusy = 0\n",
- __func__);
- good = 0;
- } else {
- u32 cc_d = cc - cycles;
- u32 rc_d = rc - rx_clear;
- u32 rf_d = rf - rx_frame;
- u32 tf_d = tf - tx_frame;
-
- if (cc_d != 0) {
- *rxc_pcnt = rc_d * 100 / cc_d;
- *rxf_pcnt = rf_d * 100 / cc_d;
- *txf_pcnt = tf_d * 100 / cc_d;
- } else {
- good = 0;
- }
+ for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) {
+ ah->ah_config.spurchans[i][0] = AR_NO_SPUR;
+ ah->ah_config.spurchans[i][1] = AR_NO_SPUR;
}
- cycles = cc;
- rx_frame = rf;
- rx_clear = rc;
- tx_frame = tf;
-
- return good;
+ ah->ah_config.intr_mitigation = 1;
}
-void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode)
-{
- u32 macmode;
-
- if (mode == ATH9K_HT_MACMODE_2040 &&
- !ah->ah_config.cwm_ignore_extcca)
- macmode = AR_2040_JOINED_RX_CLEAR;
- else
- macmode = 0;
-
- REG_WRITE(ah, AR_2040_MODE, macmode);
-}
-
-static void ath9k_hw_mark_phy_inactive(struct ath_hal *ah)
-{
- REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
-}
-
-
static struct ath_hal_5416 *ath9k_hw_newstate(u16 devid,
struct ath_softc *sc,
void __iomem *mem,
@@ -1165,20 +452,16 @@ static struct ath_hal_5416 *ath9k_hw_newstate(u16 devid,
ahp = kzalloc(sizeof(struct ath_hal_5416), GFP_KERNEL);
if (ahp == NULL) {
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: cannot allocate memory for state block\n",
- __func__);
+ "Cannot allocate memory for state block\n");
*status = -ENOMEM;
return NULL;
}
ah = &ahp->ah;
-
ah->ah_sc = sc;
ah->ah_sh = mem;
-
ah->ah_magic = AR5416_MAGIC;
ah->ah_countryCode = CTRY_DEFAULT;
-
ah->ah_devid = devid;
ah->ah_subvendorid = 0;
@@ -1190,12 +473,10 @@ static struct ath_hal_5416 *ath9k_hw_newstate(u16 devid,
ah->ah_powerLimit = MAX_RATE_POWER;
ah->ah_tpScale = ATH9K_TP_SCALE_MAX;
-
ahp->ah_atimWindow = 0;
ahp->ah_diversityControl = ah->ah_config.diversity_control;
ahp->ah_antennaSwitchSwap =
ah->ah_config.antenna_switch_swap;
-
ahp->ah_staId1Defaults = AR_STA_ID1_CRPT_MIC_ENABLE;
ahp->ah_beaconInterval = 100;
ahp->ah_enable32kHzClock = DONT_USE_32KHZ;
@@ -1210,163 +491,6 @@ static struct ath_hal_5416 *ath9k_hw_newstate(u16 devid,
return ahp;
}
-static int ath9k_hw_eeprom_attach(struct ath_hal *ah)
-{
- int status;
-
- if (ath9k_hw_use_flash(ah))
- ath9k_hw_flash_map(ah);
-
- if (!ath9k_hw_fill_eeprom(ah))
- return -EIO;
-
- status = ath9k_hw_check_eeprom(ah);
-
- return status;
-}
-
-u32 ath9k_hw_get_eeprom(struct ath_hal_5416 *ahp,
- enum eeprom_param param)
-{
- struct ar5416_eeprom *eep = &ahp->ah_eeprom;
- struct modal_eep_header *pModal = eep->modalHeader;
- struct base_eep_header *pBase = &eep->baseEepHeader;
-
- switch (param) {
- case EEP_NFTHRESH_5:
- return -pModal[0].noiseFloorThreshCh[0];
- case EEP_NFTHRESH_2:
- return -pModal[1].noiseFloorThreshCh[0];
- case AR_EEPROM_MAC(0):
- return pBase->macAddr[0] << 8 | pBase->macAddr[1];
- case AR_EEPROM_MAC(1):
- return pBase->macAddr[2] << 8 | pBase->macAddr[3];
- case AR_EEPROM_MAC(2):
- return pBase->macAddr[4] << 8 | pBase->macAddr[5];
- case EEP_REG_0:
- return pBase->regDmn[0];
- case EEP_REG_1:
- return pBase->regDmn[1];
- case EEP_OP_CAP:
- return pBase->deviceCap;
- case EEP_OP_MODE:
- return pBase->opCapFlags;
- case EEP_RF_SILENT:
- return pBase->rfSilent;
- case EEP_OB_5:
- return pModal[0].ob;
- case EEP_DB_5:
- return pModal[0].db;
- case EEP_OB_2:
- return pModal[1].ob;
- case EEP_DB_2:
- return pModal[1].db;
- case EEP_MINOR_REV:
- return pBase->version & AR5416_EEP_VER_MINOR_MASK;
- case EEP_TX_MASK:
- return pBase->txMask;
- case EEP_RX_MASK:
- return pBase->rxMask;
- default:
- return 0;
- }
-}
-
-static int ath9k_hw_get_radiorev(struct ath_hal *ah)
-{
- u32 val;
- int i;
-
- REG_WRITE(ah, AR_PHY(0x36), 0x00007058);
- for (i = 0; i < 8; i++)
- REG_WRITE(ah, AR_PHY(0x20), 0x00010000);
- val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff;
- val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4);
- return ath9k_hw_reverse_bits(val, 8);
-}
-
-static int ath9k_hw_init_macaddr(struct ath_hal *ah)
-{
- u32 sum;
- int i;
- u16 eeval;
- struct ath_hal_5416 *ahp = AH5416(ah);
- DECLARE_MAC_BUF(mac);
-
- sum = 0;
- for (i = 0; i < 3; i++) {
- eeval = ath9k_hw_get_eeprom(ahp, AR_EEPROM_MAC(i));
- sum += eeval;
- ahp->ah_macaddr[2 * i] = eeval >> 8;
- ahp->ah_macaddr[2 * i + 1] = eeval & 0xff;
- }
- if (sum == 0 || sum == 0xffff * 3) {
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "%s: mac address read failed: %s\n", __func__,
- print_mac(mac, ahp->ah_macaddr));
- return -EADDRNOTAVAIL;
- }
-
- return 0;
-}
-
-static inline int16_t ath9k_hw_interpolate(u16 target,
- u16 srcLeft,
- u16 srcRight,
- int16_t targetLeft,
- int16_t targetRight)
-{
- int16_t rv;
-
- if (srcRight == srcLeft) {
- rv = targetLeft;
- } else {
- rv = (int16_t) (((target - srcLeft) * targetRight +
- (srcRight - target) * targetLeft) /
- (srcRight - srcLeft));
- }
- return rv;
-}
-
-static inline u16 ath9k_hw_fbin2freq(u8 fbin,
- bool is2GHz)
-{
-
- if (fbin == AR5416_BCHAN_UNUSED)
- return fbin;
-
- return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin));
-}
-
-static u16 ath9k_hw_eeprom_get_spur_chan(struct ath_hal *ah,
- u16 i,
- bool is2GHz)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- struct ar5416_eeprom *eep =
- (struct ar5416_eeprom *) &ahp->ah_eeprom;
- u16 spur_val = AR_NO_SPUR;
-
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "Getting spur idx %d is2Ghz. %d val %x\n",
- i, is2GHz, ah->ah_config.spurchans[i][is2GHz]);
-
- switch (ah->ah_config.spurmode) {
- case SPUR_DISABLE:
- break;
- case SPUR_ENABLE_IOCTL:
- spur_val = ah->ah_config.spurchans[i][is2GHz];
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "Getting spur val from new loc. %d\n", spur_val);
- break;
- case SPUR_ENABLE_EEPROM:
- spur_val = eep->modalHeader[is2GHz].spurChans[i].spurChan;
- break;
-
- }
- return spur_val;
-}
-
static int ath9k_hw_rfattach(struct ath_hal *ah)
{
bool rfStatus = false;
@@ -1375,8 +499,7 @@ static int ath9k_hw_rfattach(struct ath_hal *ah)
rfStatus = ath9k_hw_init_rf(ah, &ecode);
if (!rfStatus) {
DPRINTF(ah->ah_sc, ATH_DBG_RESET,
- "%s: RF setup failed, status %u\n", __func__,
- ecode);
+ "RF setup failed, status %u\n", ecode);
return ecode;
}
@@ -1401,9 +524,9 @@ static int ath9k_hw_rf_claim(struct ath_hal *ah)
break;
default:
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
- "%s: 5G Radio Chip Rev 0x%02X is not "
+ "5G Radio Chip Rev 0x%02X is not "
"supported by this driver\n",
- __func__, ah->ah_analog5GhzRev);
+ ah->ah_analog5GhzRev);
return -EOPNOTSUPP;
}
@@ -1412,1473 +535,76 @@ static int ath9k_hw_rf_claim(struct ath_hal *ah)
return 0;
}
-static void ath9k_hw_init_pll(struct ath_hal *ah,
- struct ath9k_channel *chan)
-{
- u32 pll;
-
- if (AR_SREV_9100(ah)) {
- if (chan && IS_CHAN_5GHZ(chan))
- pll = 0x1450;
- else
- pll = 0x1458;
- } else {
- if (AR_SREV_9280_10_OR_LATER(ah)) {
- pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
-
- if (chan && IS_CHAN_HALF_RATE(chan))
- pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
- else if (chan && IS_CHAN_QUARTER_RATE(chan))
- pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
-
- if (chan && IS_CHAN_5GHZ(chan)) {
- pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
-
-
- if (AR_SREV_9280_20(ah)) {
- if (((chan->channel % 20) == 0)
- || ((chan->channel % 10) == 0))
- pll = 0x2850;
- else
- pll = 0x142c;
- }
- } else {
- pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
- }
-
- } else if (AR_SREV_9160_10_OR_LATER(ah)) {
-
- pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
-
- if (chan && IS_CHAN_HALF_RATE(chan))
- pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
- else if (chan && IS_CHAN_QUARTER_RATE(chan))
- pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
-
- if (chan && IS_CHAN_5GHZ(chan))
- pll |= SM(0x50, AR_RTC_9160_PLL_DIV);
- else
- pll |= SM(0x58, AR_RTC_9160_PLL_DIV);
- } else {
- pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
-
- if (chan && IS_CHAN_HALF_RATE(chan))
- pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
- else if (chan && IS_CHAN_QUARTER_RATE(chan))
- pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
-
- if (chan && IS_CHAN_5GHZ(chan))
- pll |= SM(0xa, AR_RTC_PLL_DIV);
- else
- pll |= SM(0xb, AR_RTC_PLL_DIV);
- }
- }
- REG_WRITE(ah, (u16) (AR_RTC_PLL_CONTROL), pll);
-
- udelay(RTC_PLL_SETTLE_DELAY);
-
- REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
-}
-
-static void ath9k_hw_set_regs(struct ath_hal *ah, struct ath9k_channel *chan,
- enum ath9k_ht_macmode macmode)
-{
- u32 phymode;
- struct ath_hal_5416 *ahp = AH5416(ah);
-
- phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40
- | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH;
-
- if (IS_CHAN_HT40(chan)) {
- phymode |= AR_PHY_FC_DYN2040_EN;
-
- if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
- (chan->chanmode == CHANNEL_G_HT40PLUS))
- phymode |= AR_PHY_FC_DYN2040_PRI_CH;
-
- if (ahp->ah_extprotspacing == ATH9K_HT_EXTPROTSPACING_25)
- phymode |= AR_PHY_FC_DYN2040_EXT_CH;
- }
- REG_WRITE(ah, AR_PHY_TURBO, phymode);
-
- ath9k_hw_set11nmac2040(ah, macmode);
-
- REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S);
- REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
-}
-
-static void ath9k_hw_set_operating_mode(struct ath_hal *ah, int opmode)
-{
- u32 val;
-
- val = REG_READ(ah, AR_STA_ID1);
- val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC);
- switch (opmode) {
- case ATH9K_M_HOSTAP:
- REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP
- | AR_STA_ID1_KSRCH_MODE);
- REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
- break;
- case ATH9K_M_IBSS:
- REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC
- | AR_STA_ID1_KSRCH_MODE);
- REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
- break;
- case ATH9K_M_STA:
- case ATH9K_M_MONITOR:
- REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE);
- break;
- }
-}
-
-static void
-ath9k_hw_set_rfmode(struct ath_hal *ah, struct ath9k_channel *chan)
-{
- u32 rfMode = 0;
-
- if (chan == NULL)
- return;
-
- rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
- ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
-
- if (!AR_SREV_9280_10_OR_LATER(ah))
- rfMode |= (IS_CHAN_5GHZ(chan)) ? AR_PHY_MODE_RF5GHZ :
- AR_PHY_MODE_RF2GHZ;
-
- if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan))
- rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
-
- REG_WRITE(ah, AR_PHY_MODE, rfMode);
-}
-
-static bool ath9k_hw_set_reset(struct ath_hal *ah, int type)
-{
- u32 rst_flags;
- u32 tmpReg;
-
- REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
- AR_RTC_FORCE_WAKE_ON_INT);
-
- if (AR_SREV_9100(ah)) {
- rst_flags = AR_RTC_RC_MAC_WARM | AR_RTC_RC_MAC_COLD |
- AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET;
- } else {
- tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE);
- if (tmpReg &
- (AR_INTR_SYNC_LOCAL_TIMEOUT |
- AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
- REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
- REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
- } else {
- REG_WRITE(ah, AR_RC, AR_RC_AHB);
- }
-
- rst_flags = AR_RTC_RC_MAC_WARM;
- if (type == ATH9K_RESET_COLD)
- rst_flags |= AR_RTC_RC_MAC_COLD;
- }
-
- REG_WRITE(ah, (u16) (AR_RTC_RC), rst_flags);
- udelay(50);
-
- REG_WRITE(ah, (u16) (AR_RTC_RC), 0);
- if (!ath9k_hw_wait(ah, (u16) (AR_RTC_RC), AR_RTC_RC_M, 0)) {
- DPRINTF(ah->ah_sc, ATH_DBG_RESET,
- "%s: RTC stuck in MAC reset\n",
- __func__);
- return false;
- }
-
- if (!AR_SREV_9100(ah))
- REG_WRITE(ah, AR_RC, 0);
-
- ath9k_hw_init_pll(ah, NULL);
-
- if (AR_SREV_9100(ah))
- udelay(50);
-
- return true;
-}
-
-static bool ath9k_hw_set_reset_power_on(struct ath_hal *ah)
-{
- REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
- AR_RTC_FORCE_WAKE_ON_INT);
-
- REG_WRITE(ah, (u16) (AR_RTC_RESET), 0);
- REG_WRITE(ah, (u16) (AR_RTC_RESET), 1);
-
- if (!ath9k_hw_wait(ah,
- AR_RTC_STATUS,
- AR_RTC_STATUS_M,
- AR_RTC_STATUS_ON)) {
- DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: RTC not waking up\n",
- __func__);
- return false;
- }
-
- ath9k_hw_read_revisions(ah);
-
- return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM);
-}
-
-static bool ath9k_hw_set_reset_reg(struct ath_hal *ah,
- u32 type)
-{
- REG_WRITE(ah, AR_RTC_FORCE_WAKE,
- AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
-
- switch (type) {
- case ATH9K_RESET_POWER_ON:
- return ath9k_hw_set_reset_power_on(ah);
- break;
- case ATH9K_RESET_WARM:
- case ATH9K_RESET_COLD:
- return ath9k_hw_set_reset(ah, type);
- break;
- default:
- return false;
- }
-}
-
-static
-struct ath9k_channel *ath9k_hw_check_chan(struct ath_hal *ah,
- struct ath9k_channel *chan)
-{
- if (!(IS_CHAN_2GHZ(chan) ^ IS_CHAN_5GHZ(chan))) {
- DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
- "%s: invalid channel %u/0x%x; not marked as "
- "2GHz or 5GHz\n", __func__, chan->channel,
- chan->channelFlags);
- return NULL;
- }
-
- if (!IS_CHAN_OFDM(chan) &&
- !IS_CHAN_CCK(chan) &&
- !IS_CHAN_HT20(chan) &&
- !IS_CHAN_HT40(chan)) {
- DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
- "%s: invalid channel %u/0x%x; not marked as "
- "OFDM or CCK or HT20 or HT40PLUS or HT40MINUS\n",
- __func__, chan->channel, chan->channelFlags);
- return NULL;
- }
-
- return ath9k_regd_check_channel(ah, chan);
-}
-
-static inline bool
-ath9k_hw_get_lower_upper_index(u8 target,
- u8 *pList,
- u16 listSize,
- u16 *indexL,
- u16 *indexR)
-{
- u16 i;
-
- if (target <= pList[0]) {
- *indexL = *indexR = 0;
- return true;
- }
- if (target >= pList[listSize - 1]) {
- *indexL = *indexR = (u16) (listSize - 1);
- return true;
- }
-
- for (i = 0; i < listSize - 1; i++) {
- if (pList[i] == target) {
- *indexL = *indexR = i;
- return true;
- }
- if (target < pList[i + 1]) {
- *indexL = i;
- *indexR = (u16) (i + 1);
- return false;
- }
- }
- return false;
-}
-
-static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
-{
- int16_t nfval;
- int16_t sort[ATH9K_NF_CAL_HIST_MAX];
- int i, j;
-
- for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
- sort[i] = nfCalBuffer[i];
-
- for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
- for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
- if (sort[j] > sort[j - 1]) {
- nfval = sort[j];
- sort[j] = sort[j - 1];
- sort[j - 1] = nfval;
- }
- }
- }
- nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];
-
- return nfval;
-}
-
-static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
- int16_t *nfarray)
+static int ath9k_hw_init_macaddr(struct ath_hal *ah)
{
+ u32 sum;
int i;
-
- for (i = 0; i < NUM_NF_READINGS; i++) {
- h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
-
- if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
- h[i].currIndex = 0;
-
- if (h[i].invalidNFcount > 0) {
- if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE
- || nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) {
- h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX;
- } else {
- h[i].invalidNFcount--;
- h[i].privNF = nfarray[i];
- }
- } else {
- h[i].privNF =
- ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
- }
- }
- return;
-}
-
-static void ar5416GetNoiseFloor(struct ath_hal *ah,
- int16_t nfarray[NUM_NF_READINGS])
-{
- int16_t nf;
-
- if (AR_SREV_9280_10_OR_LATER(ah))
- nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR);
- else
- nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR);
-
- if (nf & 0x100)
- nf = 0 - ((nf ^ 0x1ff) + 1);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "NF calibrated [ctl] [chain 0] is %d\n", nf);
- nfarray[0] = nf;
-
- if (AR_SREV_9280_10_OR_LATER(ah))
- nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
- AR9280_PHY_CH1_MINCCA_PWR);
- else
- nf = MS(REG_READ(ah, AR_PHY_CH1_CCA),
- AR_PHY_CH1_MINCCA_PWR);
-
- if (nf & 0x100)
- nf = 0 - ((nf ^ 0x1ff) + 1);
- DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
- "NF calibrated [ctl] [chain 1] is %d\n", nf);
- nfarray[1] = nf;
-
- if (!AR_SREV_9280(ah)) {
- nf = MS(REG_READ(ah, AR_PHY_CH2_CCA),
- AR_PHY_CH2_MINCCA_PWR);
- if (nf & 0x100)
- nf = 0 - ((nf ^ 0x1ff) + 1);
- DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
- "NF calibrated [ctl] [chain 2] is %d\n", nf);
- nfarray[2] = nf;
- }
-
- if (AR_SREV_9280_10_OR_LATER(ah))
- nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
- AR9280_PHY_EXT_MINCCA_PWR);
- else
- nf = MS(REG_READ(ah, AR_PHY_EXT_CCA),
- AR_PHY_EXT_MINCCA_PWR);
-
- if (nf & 0x100)
- nf = 0 - ((nf ^ 0x1ff) + 1);
- DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
- "NF calibrated [ext] [chain 0] is %d\n", nf);
- nfarray[3] = nf;
-
- if (AR_SREV_9280_10_OR_LATER(ah))
- nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
- AR9280_PHY_CH1_EXT_MINCCA_PWR);
- else
- nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA),
- AR_PHY_CH1_EXT_MINCCA_PWR);
-
- if (nf & 0x100)
- nf = 0 - ((nf ^ 0x1ff) + 1);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "NF calibrated [ext] [chain 1] is %d\n", nf);
- nfarray[4] = nf;
-
- if (!AR_SREV_9280(ah)) {
- nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA),
- AR_PHY_CH2_EXT_MINCCA_PWR);
- if (nf & 0x100)
- nf = 0 - ((nf ^ 0x1ff) + 1);
- DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
- "NF calibrated [ext] [chain 2] is %d\n", nf);
- nfarray[5] = nf;
- }
-}
-
-static bool
-getNoiseFloorThresh(struct ath_hal *ah,
- const struct ath9k_channel *chan,
- int16_t *nft)
-{
+ u16 eeval;
struct ath_hal_5416 *ahp = AH5416(ah);
- switch (chan->chanmode) {
- case CHANNEL_A:
- case CHANNEL_A_HT20:
- case CHANNEL_A_HT40PLUS:
- case CHANNEL_A_HT40MINUS:
- *nft = (int16_t) ath9k_hw_get_eeprom(ahp, EEP_NFTHRESH_5);
- break;
- case CHANNEL_B:
- case CHANNEL_G:
- case CHANNEL_G_HT20:
- case CHANNEL_G_HT40PLUS:
- case CHANNEL_G_HT40MINUS:
- *nft = (int16_t) ath9k_hw_get_eeprom(ahp, EEP_NFTHRESH_2);
- break;
- default:
- DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
- "%s: invalid channel flags 0x%x\n", __func__,
- chan->channelFlags);
- return false;
- }
- return true;
-}
-
-static void ath9k_hw_start_nfcal(struct ath_hal *ah)
-{
- REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
- AR_PHY_AGC_CONTROL_ENABLE_NF);
- REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
- AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
- REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
-}
-
-static void
-ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan)
-{
- struct ath9k_nfcal_hist *h;
- int i, j;
- int32_t val;
- const u32 ar5416_cca_regs[6] = {
- AR_PHY_CCA,
- AR_PHY_CH1_CCA,
- AR_PHY_CH2_CCA,
- AR_PHY_EXT_CCA,
- AR_PHY_CH1_EXT_CCA,
- AR_PHY_CH2_EXT_CCA
- };
- u8 chainmask;
-
- if (AR_SREV_9280(ah))
- chainmask = 0x1B;
- else
- chainmask = 0x3F;
-
-#ifdef ATH_NF_PER_CHAN
- h = chan->nfCalHist;
-#else
- h = ah->nfCalHist;
-#endif
-
- for (i = 0; i < NUM_NF_READINGS; i++) {
- if (chainmask & (1 << i)) {
- val = REG_READ(ah, ar5416_cca_regs[i]);
- val &= 0xFFFFFE00;
- val |= (((u32) (h[i].privNF) << 1) & 0x1ff);
- REG_WRITE(ah, ar5416_cca_regs[i], val);
- }
- }
-
- REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
- AR_PHY_AGC_CONTROL_ENABLE_NF);
- REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
- AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
- REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
-
- for (j = 0; j < 1000; j++) {
- if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
- AR_PHY_AGC_CONTROL_NF) == 0)
- break;
- udelay(10);
- }
-
- for (i = 0; i < NUM_NF_READINGS; i++) {
- if (chainmask & (1 << i)) {
- val = REG_READ(ah, ar5416_cca_regs[i]);
- val &= 0xFFFFFE00;
- val |= (((u32) (-50) << 1) & 0x1ff);
- REG_WRITE(ah, ar5416_cca_regs[i], val);
- }
- }
-}
-
-static int16_t ath9k_hw_getnf(struct ath_hal *ah,
- struct ath9k_channel *chan)
-{
- int16_t nf, nfThresh;
- int16_t nfarray[NUM_NF_READINGS] = { 0 };
- struct ath9k_nfcal_hist *h;
- u8 chainmask;
-
- if (AR_SREV_9280(ah))
- chainmask = 0x1B;
- else
- chainmask = 0x3F;
-
- chan->channelFlags &= (~CHANNEL_CW_INT);
- if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "%s: NF did not complete in calibration window\n",
- __func__);
- nf = 0;
- chan->rawNoiseFloor = nf;
- return chan->rawNoiseFloor;
- } else {
- ar5416GetNoiseFloor(ah, nfarray);
- nf = nfarray[0];
- if (getNoiseFloorThresh(ah, chan, &nfThresh)
- && nf > nfThresh) {
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "%s: noise floor failed detected; "
- "detected %d, threshold %d\n", __func__,
- nf, nfThresh);
- chan->channelFlags |= CHANNEL_CW_INT;
- }
+ sum = 0;
+ for (i = 0; i < 3; i++) {
+ eeval = ath9k_hw_get_eeprom(ah, AR_EEPROM_MAC(i));
+ sum += eeval;
+ ahp->ah_macaddr[2 * i] = eeval >> 8;
+ ahp->ah_macaddr[2 * i + 1] = eeval & 0xff;
}
-
-#ifdef ATH_NF_PER_CHAN
- h = chan->nfCalHist;
-#else
- h = ah->nfCalHist;
-#endif
-
- ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
- chan->rawNoiseFloor = h[0].privNF;
-
- return chan->rawNoiseFloor;
-}
-
-static void ath9k_hw_update_mibstats(struct ath_hal *ah,
- struct ath9k_mib_stats *stats)
-{
- stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL);
- stats->rts_bad += REG_READ(ah, AR_RTS_FAIL);
- stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL);
- stats->rts_good += REG_READ(ah, AR_RTS_OK);
- stats->beacons += REG_READ(ah, AR_BEACON_CNT);
-}
-
-static void ath9k_enable_mib_counters(struct ath_hal *ah)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
-
- DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable mib counters\n");
-
- ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
-
- REG_WRITE(ah, AR_FILT_OFDM, 0);
- REG_WRITE(ah, AR_FILT_CCK, 0);
- REG_WRITE(ah, AR_MIBC,
- ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS)
- & 0x0f);
- REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
- REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
-}
-
-static void ath9k_hw_disable_mib_counters(struct ath_hal *ah)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
-
- DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disabling MIB counters\n");
-
- REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC | AR_MIBC_CMC);
-
- ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
-
- REG_WRITE(ah, AR_FILT_OFDM, 0);
- REG_WRITE(ah, AR_FILT_CCK, 0);
-}
-
-static int ath9k_hw_get_ani_channel_idx(struct ath_hal *ah,
- struct ath9k_channel *chan)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- int i;
-
- for (i = 0; i < ARRAY_SIZE(ahp->ah_ani); i++) {
- if (ahp->ah_ani[i].c.channel == chan->channel)
- return i;
- if (ahp->ah_ani[i].c.channel == 0) {
- ahp->ah_ani[i].c.channel = chan->channel;
- ahp->ah_ani[i].c.channelFlags = chan->channelFlags;
- return i;
- }
+ if (sum == 0 || sum == 0xffff * 3) {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "mac address read failed: %pM\n",
+ ahp->ah_macaddr);
+ return -EADDRNOTAVAIL;
}
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "No more channel states left. Using channel 0\n");
return 0;
}
-static void ath9k_hw_ani_attach(struct ath_hal *ah)
+static void ath9k_hw_init_rxgain_ini(struct ath_hal *ah)
{
+ u32 rxgain_type;
struct ath_hal_5416 *ahp = AH5416(ah);
- int i;
- ahp->ah_hasHwPhyCounters = 1;
-
- memset(ahp->ah_ani, 0, sizeof(ahp->ah_ani));
- for (i = 0; i < ARRAY_SIZE(ahp->ah_ani); i++) {
- ahp->ah_ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH;
- ahp->ah_ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW;
- ahp->ah_ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH;
- ahp->ah_ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW;
- ahp->ah_ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH;
- ahp->ah_ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW;
- ahp->ah_ani[i].ofdmWeakSigDetectOff =
- !ATH9K_ANI_USE_OFDM_WEAK_SIG;
- ahp->ah_ani[i].cckWeakSigThreshold =
- ATH9K_ANI_CCK_WEAK_SIG_THR;
- ahp->ah_ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL;
- ahp->ah_ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL;
- if (ahp->ah_hasHwPhyCounters) {
- ahp->ah_ani[i].ofdmPhyErrBase =
- AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH;
- ahp->ah_ani[i].cckPhyErrBase =
- AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH;
- }
- }
- if (ahp->ah_hasHwPhyCounters) {
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "Setting OfdmErrBase = 0x%08x\n",
- ahp->ah_ani[0].ofdmPhyErrBase);
- DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n",
- ahp->ah_ani[0].cckPhyErrBase);
-
- REG_WRITE(ah, AR_PHY_ERR_1, ahp->ah_ani[0].ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_2, ahp->ah_ani[0].cckPhyErrBase);
- ath9k_enable_mib_counters(ah);
- }
- ahp->ah_aniPeriod = ATH9K_ANI_PERIOD;
- if (ah->ah_config.enable_ani)
- ahp->ah_procPhyErr |= HAL_PROCESS_ANI;
-}
-
-static void ath9k_hw_ani_setup(struct ath_hal *ah)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- int i;
+ if (ath9k_hw_get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_17) {
+ rxgain_type = ath9k_hw_get_eeprom(ah, EEP_RXGAIN_TYPE);
- const int totalSizeDesired[] = { -55, -55, -55, -55, -62 };
- const int coarseHigh[] = { -14, -14, -14, -14, -12 };
- const int coarseLow[] = { -64, -64, -64, -64, -70 };
- const int firpwr[] = { -78, -78, -78, -78, -80 };
-
- for (i = 0; i < 5; i++) {
- ahp->ah_totalSizeDesired[i] = totalSizeDesired[i];
- ahp->ah_coarseHigh[i] = coarseHigh[i];
- ahp->ah_coarseLow[i] = coarseLow[i];
- ahp->ah_firpwr[i] = firpwr[i];
- }
-}
-
-static void ath9k_hw_ani_detach(struct ath_hal *ah)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
-
- DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Detaching Ani\n");
- if (ahp->ah_hasHwPhyCounters) {
- ath9k_hw_disable_mib_counters(ah);
- REG_WRITE(ah, AR_PHY_ERR_1, 0);
- REG_WRITE(ah, AR_PHY_ERR_2, 0);
- }
-}
-
-
-static bool ath9k_hw_ani_control(struct ath_hal *ah,
- enum ath9k_ani_cmd cmd, int param)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- struct ar5416AniState *aniState = ahp->ah_curani;
-
- switch (cmd & ahp->ah_ani_function) {
- case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{
- u32 level = param;
-
- if (level >= ARRAY_SIZE(ahp->ah_totalSizeDesired)) {
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "%s: level out of range (%u > %u)\n",
- __func__, level,
- (unsigned) ARRAY_SIZE(ahp->
- ah_totalSizeDesired));
- return false;
- }
-
- REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ,
- AR_PHY_DESIRED_SZ_TOT_DES,
- ahp->ah_totalSizeDesired[level]);
- REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
- AR_PHY_AGC_CTL1_COARSE_LOW,
- ahp->ah_coarseLow[level]);
- REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1,
- AR_PHY_AGC_CTL1_COARSE_HIGH,
- ahp->ah_coarseHigh[level]);
- REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
- AR_PHY_FIND_SIG_FIRPWR,
- ahp->ah_firpwr[level]);
-
- if (level > aniState->noiseImmunityLevel)
- ahp->ah_stats.ast_ani_niup++;
- else if (level < aniState->noiseImmunityLevel)
- ahp->ah_stats.ast_ani_nidown++;
- aniState->noiseImmunityLevel = level;
- break;
- }
- case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{
- const int m1ThreshLow[] = { 127, 50 };
- const int m2ThreshLow[] = { 127, 40 };
- const int m1Thresh[] = { 127, 0x4d };
- const int m2Thresh[] = { 127, 0x40 };
- const int m2CountThr[] = { 31, 16 };
- const int m2CountThrLow[] = { 63, 48 };
- u32 on = param ? 1 : 0;
-
- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
- AR_PHY_SFCORR_LOW_M1_THRESH_LOW,
- m1ThreshLow[on]);
- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
- AR_PHY_SFCORR_LOW_M2_THRESH_LOW,
- m2ThreshLow[on]);
- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
- AR_PHY_SFCORR_M1_THRESH,
- m1Thresh[on]);
- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
- AR_PHY_SFCORR_M2_THRESH,
- m2Thresh[on]);
- REG_RMW_FIELD(ah, AR_PHY_SFCORR,
- AR_PHY_SFCORR_M2COUNT_THR,
- m2CountThr[on]);
- REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW,
- AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW,
- m2CountThrLow[on]);
-
- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
- AR_PHY_SFCORR_EXT_M1_THRESH_LOW,
- m1ThreshLow[on]);
- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
- AR_PHY_SFCORR_EXT_M2_THRESH_LOW,
- m2ThreshLow[on]);
- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
- AR_PHY_SFCORR_EXT_M1_THRESH,
- m1Thresh[on]);
- REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT,
- AR_PHY_SFCORR_EXT_M2_THRESH,
- m2Thresh[on]);
-
- if (on)
- REG_SET_BIT(ah, AR_PHY_SFCORR_LOW,
- AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
+ if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF)
+ INIT_INI_ARRAY(&ahp->ah_iniModesRxGain,
+ ar9280Modes_backoff_13db_rxgain_9280_2,
+ ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6);
+ else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF)
+ INIT_INI_ARRAY(&ahp->ah_iniModesRxGain,
+ ar9280Modes_backoff_23db_rxgain_9280_2,
+ ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6);
else
- REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW,
- AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW);
-
- if (!on != aniState->ofdmWeakSigDetectOff) {
- if (on)
- ahp->ah_stats.ast_ani_ofdmon++;
- else
- ahp->ah_stats.ast_ani_ofdmoff++;
- aniState->ofdmWeakSigDetectOff = !on;
- }
- break;
- }
- case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{
- const int weakSigThrCck[] = { 8, 6 };
- u32 high = param ? 1 : 0;
-
- REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT,
- AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK,
- weakSigThrCck[high]);
- if (high != aniState->cckWeakSigThreshold) {
- if (high)
- ahp->ah_stats.ast_ani_cckhigh++;
- else
- ahp->ah_stats.ast_ani_ccklow++;
- aniState->cckWeakSigThreshold = high;
- }
- break;
- }
- case ATH9K_ANI_FIRSTEP_LEVEL:{
- const int firstep[] = { 0, 4, 8 };
- u32 level = param;
-
- if (level >= ARRAY_SIZE(firstep)) {
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "%s: level out of range (%u > %u)\n",
- __func__, level,
- (unsigned) ARRAY_SIZE(firstep));
- return false;
- }
- REG_RMW_FIELD(ah, AR_PHY_FIND_SIG,
- AR_PHY_FIND_SIG_FIRSTEP,
- firstep[level]);
- if (level > aniState->firstepLevel)
- ahp->ah_stats.ast_ani_stepup++;
- else if (level < aniState->firstepLevel)
- ahp->ah_stats.ast_ani_stepdown++;
- aniState->firstepLevel = level;
- break;
- }
- case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{
- const int cycpwrThr1[] =
- { 2, 4, 6, 8, 10, 12, 14, 16 };
- u32 level = param;
-
- if (level >= ARRAY_SIZE(cycpwrThr1)) {
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "%s: level out of range (%u > %u)\n",
- __func__, level,
- (unsigned)
- ARRAY_SIZE(cycpwrThr1));
- return false;
- }
- REG_RMW_FIELD(ah, AR_PHY_TIMING5,
- AR_PHY_TIMING5_CYCPWR_THR1,
- cycpwrThr1[level]);
- if (level > aniState->spurImmunityLevel)
- ahp->ah_stats.ast_ani_spurup++;
- else if (level < aniState->spurImmunityLevel)
- ahp->ah_stats.ast_ani_spurdown++;
- aniState->spurImmunityLevel = level;
- break;
- }
- case ATH9K_ANI_PRESENT:
- break;
- default:
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "%s: invalid cmd %u\n", __func__, cmd);
- return false;
- }
-
- DPRINTF(ah->ah_sc, ATH_DBG_ANI, "%s: ANI parameters:\n", __func__);
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "noiseImmunityLevel=%d, spurImmunityLevel=%d, "
- "ofdmWeakSigDetectOff=%d\n",
- aniState->noiseImmunityLevel, aniState->spurImmunityLevel,
- !aniState->ofdmWeakSigDetectOff);
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "cckWeakSigThreshold=%d, "
- "firstepLevel=%d, listenTime=%d\n",
- aniState->cckWeakSigThreshold, aniState->firstepLevel,
- aniState->listenTime);
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n",
- aniState->cycleCount, aniState->ofdmPhyErrCount,
- aniState->cckPhyErrCount);
- return true;
-}
-
-static void ath9k_ani_restart(struct ath_hal *ah)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- struct ar5416AniState *aniState;
-
- if (!DO_ANI(ah))
- return;
-
- aniState = ahp->ah_curani;
-
- aniState->listenTime = 0;
- if (ahp->ah_hasHwPhyCounters) {
- if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) {
- aniState->ofdmPhyErrBase = 0;
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "OFDM Trigger is too high for hw counters\n");
- } else {
- aniState->ofdmPhyErrBase =
- AR_PHY_COUNTMAX - aniState->ofdmTrigHigh;
- }
- if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) {
- aniState->cckPhyErrBase = 0;
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "CCK Trigger is too high for hw counters\n");
- } else {
- aniState->cckPhyErrBase =
- AR_PHY_COUNTMAX - aniState->cckTrigHigh;
- }
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "%s: Writing ofdmbase=%u cckbase=%u\n",
- __func__, aniState->ofdmPhyErrBase,
- aniState->cckPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
- REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
-
- ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
- }
- aniState->ofdmPhyErrCount = 0;
- aniState->cckPhyErrCount = 0;
-}
-
-static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hal *ah)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- struct ath9k_channel *chan = ah->ah_curchan;
- struct ar5416AniState *aniState;
- enum wireless_mode mode;
- int32_t rssi;
-
- if (!DO_ANI(ah))
- return;
-
- aniState = ahp->ah_curani;
-
- if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
- if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
- aniState->noiseImmunityLevel + 1)) {
- return;
- }
- }
-
- if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) {
- if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
- aniState->spurImmunityLevel + 1)) {
- return;
- }
- }
-
- if (ah->ah_opmode == ATH9K_M_HOSTAP) {
- if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
- ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
- aniState->firstepLevel + 1);
- }
- return;
- }
- rssi = BEACON_RSSI(ahp);
- if (rssi > aniState->rssiThrHigh) {
- if (!aniState->ofdmWeakSigDetectOff) {
- if (ath9k_hw_ani_control(ah,
- ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
- false)) {
- ath9k_hw_ani_control(ah,
- ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
- 0);
- return;
- }
- }
- if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
- ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
- aniState->firstepLevel + 1);
- return;
- }
- } else if (rssi > aniState->rssiThrLow) {
- if (aniState->ofdmWeakSigDetectOff)
- ath9k_hw_ani_control(ah,
- ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
- true);
- if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
- ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
- aniState->firstepLevel + 1);
- return;
- } else {
- mode = ath9k_hw_chan2wmode(ah, chan);
- if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
- if (!aniState->ofdmWeakSigDetectOff)
- ath9k_hw_ani_control(ah,
- ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
- false);
- if (aniState->firstepLevel > 0)
- ath9k_hw_ani_control(ah,
- ATH9K_ANI_FIRSTEP_LEVEL,
- 0);
- return;
- }
- }
-}
-
-static void ath9k_hw_ani_cck_err_trigger(struct ath_hal *ah)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- struct ath9k_channel *chan = ah->ah_curchan;
- struct ar5416AniState *aniState;
- enum wireless_mode mode;
- int32_t rssi;
-
- if (!DO_ANI(ah))
- return;
-
- aniState = ahp->ah_curani;
- if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) {
- if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
- aniState->noiseImmunityLevel + 1)) {
- return;
- }
- }
- if (ah->ah_opmode == ATH9K_M_HOSTAP) {
- if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) {
- ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
- aniState->firstepLevel + 1);
- }
- return;
- }
- rssi = BEACON_RSSI(ahp);
- if (rssi > aniState->rssiThrLow) {
- if (aniState->firstepLevel < HAL_FIRST_STEP_MAX)
- ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
- aniState->firstepLevel + 1);
- } else {
- mode = ath9k_hw_chan2wmode(ah, chan);
- if (mode == ATH9K_MODE_11G || mode == ATH9K_MODE_11B) {
- if (aniState->firstepLevel > 0)
- ath9k_hw_ani_control(ah,
- ATH9K_ANI_FIRSTEP_LEVEL,
- 0);
- }
- }
-}
-
-static void ath9k_ani_reset(struct ath_hal *ah)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- struct ar5416AniState *aniState;
- struct ath9k_channel *chan = ah->ah_curchan;
- int index;
-
- if (!DO_ANI(ah))
- return;
-
- index = ath9k_hw_get_ani_channel_idx(ah, chan);
- aniState = &ahp->ah_ani[index];
- ahp->ah_curani = aniState;
-
- if (DO_ANI(ah) && ah->ah_opmode != ATH9K_M_STA
- && ah->ah_opmode != ATH9K_M_IBSS) {
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "%s: Reset ANI state opmode %u\n", __func__,
- ah->ah_opmode);
- ahp->ah_stats.ast_ani_reset++;
- ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0);
- ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0);
- ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0);
- ath9k_hw_ani_control(ah,
- ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
- !ATH9K_ANI_USE_OFDM_WEAK_SIG);
- ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
- ATH9K_ANI_CCK_WEAK_SIG_THR);
- ath9k_hw_setrxfilter(ah,
- ath9k_hw_getrxfilter(ah) |
- ATH9K_RX_FILTER_PHYERR);
- if (ah->ah_opmode == ATH9K_M_HOSTAP) {
- ahp->ah_curani->ofdmTrigHigh =
- ah->ah_config.ofdm_trig_high;
- ahp->ah_curani->ofdmTrigLow =
- ah->ah_config.ofdm_trig_low;
- ahp->ah_curani->cckTrigHigh =
- ah->ah_config.cck_trig_high;
- ahp->ah_curani->cckTrigLow =
- ah->ah_config.cck_trig_low;
- }
- ath9k_ani_restart(ah);
- return;
- }
-
- if (aniState->noiseImmunityLevel != 0)
- ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
- aniState->noiseImmunityLevel);
- if (aniState->spurImmunityLevel != 0)
- ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
- aniState->spurImmunityLevel);
- if (aniState->ofdmWeakSigDetectOff)
- ath9k_hw_ani_control(ah,
- ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
- !aniState->ofdmWeakSigDetectOff);
- if (aniState->cckWeakSigThreshold)
- ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR,
- aniState->cckWeakSigThreshold);
- if (aniState->firstepLevel != 0)
- ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
- aniState->firstepLevel);
- if (ahp->ah_hasHwPhyCounters) {
- ath9k_hw_setrxfilter(ah,
- ath9k_hw_getrxfilter(ah) &
- ~ATH9K_RX_FILTER_PHYERR);
- ath9k_ani_restart(ah);
- REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING);
- REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING);
-
- } else {
- ath9k_ani_restart(ah);
- ath9k_hw_setrxfilter(ah,
- ath9k_hw_getrxfilter(ah) |
- ATH9K_RX_FILTER_PHYERR);
- }
-}
-
-/*
- * Process a MIB interrupt. We may potentially be invoked because
- * any of the MIB counters overflow/trigger so don't assume we're
- * here because a PHY error counter triggered.
- */
-void ath9k_hw_procmibevent(struct ath_hal *ah,
- const struct ath9k_node_stats *stats)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- u32 phyCnt1, phyCnt2;
-
- DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Processing Mib Intr\n");
- /* Reset these counters regardless */
- REG_WRITE(ah, AR_FILT_OFDM, 0);
- REG_WRITE(ah, AR_FILT_CCK, 0);
- if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING))
- REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR);
-
- /* Clear the mib counters and save them in the stats */
- ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
- ahp->ah_stats.ast_nodestats = *stats;
-
- if (!DO_ANI(ah))
- return;
-
- /* NB: these are not reset-on-read */
- phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
- phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
- if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) ||
- ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) {
- struct ar5416AniState *aniState = ahp->ah_curani;
- u32 ofdmPhyErrCnt, cckPhyErrCnt;
-
- /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */
- ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
- ahp->ah_stats.ast_ani_ofdmerrs +=
- ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
- aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
-
- cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
- ahp->ah_stats.ast_ani_cckerrs +=
- cckPhyErrCnt - aniState->cckPhyErrCount;
- aniState->cckPhyErrCount = cckPhyErrCnt;
-
- /*
- * NB: figure out which counter triggered. If both
- * trigger we'll only deal with one as the processing
- * clobbers the error counter so the trigger threshold
- * check will never be true.
- */
- if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh)
- ath9k_hw_ani_ofdm_err_trigger(ah);
- if (aniState->cckPhyErrCount > aniState->cckTrigHigh)
- ath9k_hw_ani_cck_err_trigger(ah);
- /* NB: always restart to insure the h/w counters are reset */
- ath9k_ani_restart(ah);
- }
-}
-
-static void ath9k_hw_ani_lower_immunity(struct ath_hal *ah)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- struct ar5416AniState *aniState;
- int32_t rssi;
-
- aniState = ahp->ah_curani;
-
- if (ah->ah_opmode == ATH9K_M_HOSTAP) {
- if (aniState->firstepLevel > 0) {
- if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL,
- aniState->firstepLevel - 1)) {
- return;
- }
- }
- } else {
- rssi = BEACON_RSSI(ahp);
- if (rssi > aniState->rssiThrHigh) {
- /* XXX: Handle me */
- } else if (rssi > aniState->rssiThrLow) {
- if (aniState->ofdmWeakSigDetectOff) {
- if (ath9k_hw_ani_control(ah,
- ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION,
- true) ==
- true) {
- return;
- }
- }
- if (aniState->firstepLevel > 0) {
- if (ath9k_hw_ani_control
- (ah, ATH9K_ANI_FIRSTEP_LEVEL,
- aniState->firstepLevel - 1) ==
- true) {
- return;
- }
- }
- } else {
- if (aniState->firstepLevel > 0) {
- if (ath9k_hw_ani_control
- (ah, ATH9K_ANI_FIRSTEP_LEVEL,
- aniState->firstepLevel - 1) ==
- true) {
- return;
- }
- }
- }
- }
-
- if (aniState->spurImmunityLevel > 0) {
- if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL,
- aniState->spurImmunityLevel - 1)) {
- return;
- }
- }
-
- if (aniState->noiseImmunityLevel > 0) {
- ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL,
- aniState->noiseImmunityLevel - 1);
- return;
- }
-}
-
-static int32_t ath9k_hw_ani_get_listen_time(struct ath_hal *ah)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- struct ar5416AniState *aniState;
- u32 txFrameCount, rxFrameCount, cycleCount;
- int32_t listenTime;
-
- txFrameCount = REG_READ(ah, AR_TFCNT);
- rxFrameCount = REG_READ(ah, AR_RFCNT);
- cycleCount = REG_READ(ah, AR_CCCNT);
-
- aniState = ahp->ah_curani;
- if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) {
-
- listenTime = 0;
- ahp->ah_stats.ast_ani_lzero++;
- } else {
- int32_t ccdelta = cycleCount - aniState->cycleCount;
- int32_t rfdelta = rxFrameCount - aniState->rxFrameCount;
- int32_t tfdelta = txFrameCount - aniState->txFrameCount;
- listenTime = (ccdelta - rfdelta - tfdelta) / 44000;
- }
- aniState->cycleCount = cycleCount;
- aniState->txFrameCount = txFrameCount;
- aniState->rxFrameCount = rxFrameCount;
-
- return listenTime;
+ INIT_INI_ARRAY(&ahp->ah_iniModesRxGain,
+ ar9280Modes_original_rxgain_9280_2,
+ ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
+ } else
+ INIT_INI_ARRAY(&ahp->ah_iniModesRxGain,
+ ar9280Modes_original_rxgain_9280_2,
+ ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6);
}
-void ath9k_hw_ani_monitor(struct ath_hal *ah,
- const struct ath9k_node_stats *stats,
- struct ath9k_channel *chan)
+static void ath9k_hw_init_txgain_ini(struct ath_hal *ah)
{
+ u32 txgain_type;
struct ath_hal_5416 *ahp = AH5416(ah);
- struct ar5416AniState *aniState;
- int32_t listenTime;
-
- aniState = ahp->ah_curani;
- ahp->ah_stats.ast_nodestats = *stats;
-
- listenTime = ath9k_hw_ani_get_listen_time(ah);
- if (listenTime < 0) {
- ahp->ah_stats.ast_ani_lneg++;
- ath9k_ani_restart(ah);
- return;
- }
-
- aniState->listenTime += listenTime;
-
- if (ahp->ah_hasHwPhyCounters) {
- u32 phyCnt1, phyCnt2;
- u32 ofdmPhyErrCnt, cckPhyErrCnt;
-
- ath9k_hw_update_mibstats(ah, &ahp->ah_mibStats);
-
- phyCnt1 = REG_READ(ah, AR_PHY_ERR_1);
- phyCnt2 = REG_READ(ah, AR_PHY_ERR_2);
-
- if (phyCnt1 < aniState->ofdmPhyErrBase ||
- phyCnt2 < aniState->cckPhyErrBase) {
- if (phyCnt1 < aniState->ofdmPhyErrBase) {
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "%s: phyCnt1 0x%x, resetting "
- "counter value to 0x%x\n",
- __func__, phyCnt1,
- aniState->ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_1,
- aniState->ofdmPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_MASK_1,
- AR_PHY_ERR_OFDM_TIMING);
- }
- if (phyCnt2 < aniState->cckPhyErrBase) {
- DPRINTF(ah->ah_sc, ATH_DBG_ANI,
- "%s: phyCnt2 0x%x, resetting "
- "counter value to 0x%x\n",
- __func__, phyCnt2,
- aniState->cckPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_2,
- aniState->cckPhyErrBase);
- REG_WRITE(ah, AR_PHY_ERR_MASK_2,
- AR_PHY_ERR_CCK_TIMING);
- }
- return;
- }
-
- ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase;
- ahp->ah_stats.ast_ani_ofdmerrs +=
- ofdmPhyErrCnt - aniState->ofdmPhyErrCount;
- aniState->ofdmPhyErrCount = ofdmPhyErrCnt;
-
- cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase;
- ahp->ah_stats.ast_ani_cckerrs +=
- cckPhyErrCnt - aniState->cckPhyErrCount;
- aniState->cckPhyErrCount = cckPhyErrCnt;
- }
-
- if (!DO_ANI(ah))
- return;
-
- if (aniState->listenTime > 5 * ahp->ah_aniPeriod) {
- if (aniState->ofdmPhyErrCount <= aniState->listenTime *
- aniState->ofdmTrigLow / 1000 &&
- aniState->cckPhyErrCount <= aniState->listenTime *
- aniState->cckTrigLow / 1000)
- ath9k_hw_ani_lower_immunity(ah);
- ath9k_ani_restart(ah);
- } else if (aniState->listenTime > ahp->ah_aniPeriod) {
- if (aniState->ofdmPhyErrCount > aniState->listenTime *
- aniState->ofdmTrigHigh / 1000) {
- ath9k_hw_ani_ofdm_err_trigger(ah);
- ath9k_ani_restart(ah);
- } else if (aniState->cckPhyErrCount >
- aniState->listenTime * aniState->cckTrigHigh /
- 1000) {
- ath9k_hw_ani_cck_err_trigger(ah);
- ath9k_ani_restart(ah);
- }
- }
-}
-
-#ifndef ATH_NF_PER_CHAN
-static void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah)
-{
- int i, j;
-
- for (i = 0; i < NUM_NF_READINGS; i++) {
- ah->nfCalHist[i].currIndex = 0;
- ah->nfCalHist[i].privNF = AR_PHY_CCA_MAX_GOOD_VALUE;
- ah->nfCalHist[i].invalidNFcount =
- AR_PHY_CCA_FILTERWINDOW_LENGTH;
- for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
- ah->nfCalHist[i].nfCalBuffer[j] =
- AR_PHY_CCA_MAX_GOOD_VALUE;
- }
- }
- return;
-}
-#endif
-
-static void ath9k_hw_gpio_cfg_output_mux(struct ath_hal *ah,
- u32 gpio, u32 type)
-{
- int addr;
- u32 gpio_shift, tmp;
-
- if (gpio > 11)
- addr = AR_GPIO_OUTPUT_MUX3;
- else if (gpio > 5)
- addr = AR_GPIO_OUTPUT_MUX2;
- else
- addr = AR_GPIO_OUTPUT_MUX1;
-
- gpio_shift = (gpio % 6) * 5;
-
- if (AR_SREV_9280_20_OR_LATER(ah)
- || (addr != AR_GPIO_OUTPUT_MUX1)) {
- REG_RMW(ah, addr, (type << gpio_shift),
- (0x1f << gpio_shift));
- } else {
- tmp = REG_READ(ah, addr);
- tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0);
- tmp &= ~(0x1f << gpio_shift);
- tmp |= (type << gpio_shift);
- REG_WRITE(ah, addr, tmp);
- }
-}
-
-void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
- u32 ah_signal_type)
-{
- u32 gpio_shift;
-
- ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
-
- gpio_shift = 2 * gpio;
-
- REG_RMW(ah,
- AR_GPIO_OE_OUT,
- (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
- (AR_GPIO_OE_OUT_DRV << gpio_shift));
-}
-
-void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val)
-{
- REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio),
- AR_GPIO_BIT(gpio));
-}
-
-/*
- * Configure GPIO Input lines
- */
-void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio)
-{
- u32 gpio_shift;
-
- ASSERT(gpio < ah->ah_caps.num_gpio_pins);
-
- gpio_shift = gpio << 1;
-
- REG_RMW(ah,
- AR_GPIO_OE_OUT,
- (AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
- (AR_GPIO_OE_OUT_DRV << gpio_shift));
-}
-
-#ifdef CONFIG_RFKILL
-static void ath9k_enable_rfkill(struct ath_hal *ah)
-{
- REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
- AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
-
- REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
- AR_GPIO_INPUT_MUX2_RFSILENT);
- ath9k_hw_cfg_gpio_input(ah, ah->ah_rfkill_gpio);
- REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
-}
-#endif
-
-u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio)
-{
- if (gpio >= ah->ah_caps.num_gpio_pins)
- return 0xffffffff;
+ if (ath9k_hw_get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_19) {
+ txgain_type = ath9k_hw_get_eeprom(ah, EEP_TXGAIN_TYPE);
- if (AR_SREV_9280_10_OR_LATER(ah)) {
- return (MS
- (REG_READ(ah, AR_GPIO_IN_OUT),
- AR928X_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) != 0;
- } else {
- return (MS(REG_READ(ah, AR_GPIO_IN_OUT), AR_GPIO_IN_VAL) &
- AR_GPIO_BIT(gpio)) != 0;
- }
+ if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER)
+ INIT_INI_ARRAY(&ahp->ah_iniModesTxGain,
+ ar9280Modes_high_power_tx_gain_9280_2,
+ ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6);
+ else
+ INIT_INI_ARRAY(&ahp->ah_iniModesTxGain,
+ ar9280Modes_original_tx_gain_9280_2,
+ ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
+ } else
+ INIT_INI_ARRAY(&ahp->ah_iniModesTxGain,
+ ar9280Modes_original_tx_gain_9280_2,
+ ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6);
}
static int ath9k_hw_post_attach(struct ath_hal *ah)
@@ -2887,7 +613,7 @@ static int ath9k_hw_post_attach(struct ath_hal *ah)
if (!ath9k_hw_chip_test(ah)) {
DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
- "%s: hardware self-test failed\n", __func__);
+ "hardware self-test failed\n");
return -ENODEV;
}
@@ -2906,365 +632,17 @@ static int ath9k_hw_post_attach(struct ath_hal *ah)
ath9k_hw_ani_setup(ah);
ath9k_hw_ani_attach(ah);
}
- return 0;
-}
-
-static u32 ath9k_hw_ini_fixup(struct ath_hal *ah,
- struct ar5416_eeprom *pEepData,
- u32 reg, u32 value)
-{
- struct base_eep_header *pBase = &(pEepData->baseEepHeader);
-
- switch (ah->ah_devid) {
- case AR9280_DEVID_PCI:
- if (reg == 0x7894) {
- DPRINTF(ah->ah_sc, ATH_DBG_ANY,
- "ini VAL: %x EEPROM: %x\n", value,
- (pBase->version & 0xff));
-
- if ((pBase->version & 0xff) > 0x0a) {
- DPRINTF(ah->ah_sc, ATH_DBG_ANY,
- "PWDCLKIND: %d\n",
- pBase->pwdclkind);
- value &= ~AR_AN_TOP2_PWDCLKIND;
- value |= AR_AN_TOP2_PWDCLKIND & (pBase->
- pwdclkind << AR_AN_TOP2_PWDCLKIND_S);
- } else {
- DPRINTF(ah->ah_sc, ATH_DBG_ANY,
- "PWDCLKIND Earlier Rev\n");
- }
-
- DPRINTF(ah->ah_sc, ATH_DBG_ANY,
- "final ini VAL: %x\n", value);
- }
- break;
- }
- return value;
-}
-
-static bool ath9k_hw_fill_cap_info(struct ath_hal *ah)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
- u16 capField = 0, eeval;
-
- eeval = ath9k_hw_get_eeprom(ahp, EEP_REG_0);
-
- ah->ah_currentRD = eeval;
-
- eeval = ath9k_hw_get_eeprom(ahp, EEP_REG_1);
- ah->ah_currentRDExt = eeval;
-
- capField = ath9k_hw_get_eeprom(ahp, EEP_OP_CAP);
-
- if (ah->ah_opmode != ATH9K_M_HOSTAP &&
- ah->ah_subvendorid == AR_SUBVENDOR_ID_NEW_A) {
- if (ah->ah_currentRD == 0x64 || ah->ah_currentRD == 0x65)
- ah->ah_currentRD += 5;
- else if (ah->ah_currentRD == 0x41)
- ah->ah_currentRD = 0x43;
- DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: regdomain mapped to 0x%x\n", __func__,
- ah->ah_currentRD);
- }
-
- eeval = ath9k_hw_get_eeprom(ahp, EEP_OP_MODE);
- bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX);
-
- if (eeval & AR5416_OPFLAGS_11A) {
- set_bit(ATH9K_MODE_11A, pCap->wireless_modes);
- if (ah->ah_config.ht_enable) {
- if (!(eeval & AR5416_OPFLAGS_N_5G_HT20))
- set_bit(ATH9K_MODE_11NA_HT20,
- pCap->wireless_modes);
- if (!(eeval & AR5416_OPFLAGS_N_5G_HT40)) {
- set_bit(ATH9K_MODE_11NA_HT40PLUS,
- pCap->wireless_modes);
- set_bit(ATH9K_MODE_11NA_HT40MINUS,
- pCap->wireless_modes);
- }
- }
- }
-
- if (eeval & AR5416_OPFLAGS_11G) {
- set_bit(ATH9K_MODE_11B, pCap->wireless_modes);
- set_bit(ATH9K_MODE_11G, pCap->wireless_modes);
- if (ah->ah_config.ht_enable) {
- if (!(eeval & AR5416_OPFLAGS_N_2G_HT20))
- set_bit(ATH9K_MODE_11NG_HT20,
- pCap->wireless_modes);
- if (!(eeval & AR5416_OPFLAGS_N_2G_HT40)) {
- set_bit(ATH9K_MODE_11NG_HT40PLUS,
- pCap->wireless_modes);
- set_bit(ATH9K_MODE_11NG_HT40MINUS,
- pCap->wireless_modes);
- }
- }
- }
-
- pCap->tx_chainmask = ath9k_hw_get_eeprom(ahp, EEP_TX_MASK);
- if ((ah->ah_isPciExpress)
- || (eeval & AR5416_OPFLAGS_11A)) {
- pCap->rx_chainmask =
- ath9k_hw_get_eeprom(ahp, EEP_RX_MASK);
- } else {
- pCap->rx_chainmask =
- (ath9k_hw_gpio_get(ah, 0)) ? 0x5 : 0x7;
- }
-
- if (!(AR_SREV_9280(ah) && (ah->ah_macRev == 0)))
- ahp->ah_miscMode |= AR_PCU_MIC_NEW_LOC_ENA;
-
- pCap->low_2ghz_chan = 2312;
- pCap->high_2ghz_chan = 2732;
-
- pCap->low_5ghz_chan = 4920;
- pCap->high_5ghz_chan = 6100;
-
- pCap->hw_caps &= ~ATH9K_HW_CAP_CIPHER_CKIP;
- pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_TKIP;
- pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_AESCCM;
-
- pCap->hw_caps &= ~ATH9K_HW_CAP_MIC_CKIP;
- pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP;
- pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM;
-
- pCap->hw_caps |= ATH9K_HW_CAP_CHAN_SPREAD;
-
- if (ah->ah_config.ht_enable)
- pCap->hw_caps |= ATH9K_HW_CAP_HT;
- else
- pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
-
- pCap->hw_caps |= ATH9K_HW_CAP_GTT;
- pCap->hw_caps |= ATH9K_HW_CAP_VEOL;
- pCap->hw_caps |= ATH9K_HW_CAP_BSSIDMASK;
- pCap->hw_caps &= ~ATH9K_HW_CAP_MCAST_KEYSEARCH;
-
- if (capField & AR_EEPROM_EEPCAP_MAXQCU)
- pCap->total_queues =
- MS(capField, AR_EEPROM_EEPCAP_MAXQCU);
- else
- pCap->total_queues = ATH9K_NUM_TX_QUEUES;
-
- if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES)
- pCap->keycache_size =
- 1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES);
- else
- pCap->keycache_size = AR_KEYTABLE_SIZE;
-
- pCap->hw_caps |= ATH9K_HW_CAP_FASTCC;
- pCap->num_mr_retries = 4;
- pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD;
-
- if (AR_SREV_9280_10_OR_LATER(ah))
- pCap->num_gpio_pins = AR928X_NUM_GPIO;
- else
- pCap->num_gpio_pins = AR_NUM_GPIO;
-
- if (AR_SREV_9280_10_OR_LATER(ah)) {
- pCap->hw_caps |= ATH9K_HW_CAP_WOW;
- pCap->hw_caps |= ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT;
- } else {
- pCap->hw_caps &= ~ATH9K_HW_CAP_WOW;
- pCap->hw_caps &= ~ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT;
- }
-
- if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) {
- pCap->hw_caps |= ATH9K_HW_CAP_CST;
- pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX;
- } else {
- pCap->rts_aggr_limit = (8 * 1024);
- }
-
- pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM;
-
-#ifdef CONFIG_RFKILL
- ah->ah_rfsilent = ath9k_hw_get_eeprom(ahp, EEP_RF_SILENT);
- if (ah->ah_rfsilent & EEP_RFSILENT_ENABLED) {
- ah->ah_rfkill_gpio =
- MS(ah->ah_rfsilent, EEP_RFSILENT_GPIO_SEL);
- ah->ah_rfkill_polarity =
- MS(ah->ah_rfsilent, EEP_RFSILENT_POLARITY);
-
- pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT;
- }
-#endif
-
- if ((ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) ||
- (ah->ah_macVersion == AR_SREV_VERSION_5416_PCIE) ||
- (ah->ah_macVersion == AR_SREV_VERSION_9160) ||
- (ah->ah_macVersion == AR_SREV_VERSION_9100) ||
- (ah->ah_macVersion == AR_SREV_VERSION_9280))
- pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
- else
- pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
-
- if (AR_SREV_9280(ah))
- pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;
- else
- pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS;
-
- if (ah->ah_currentRDExt & (1 << REG_EXT_JAPAN_MIDBAND)) {
- pCap->reg_cap =
- AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
- AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN |
- AR_EEPROM_EEREGCAP_EN_KK_U2 |
- AR_EEPROM_EEREGCAP_EN_KK_MIDBAND;
- } else {
- pCap->reg_cap =
- AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
- AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN;
- }
-
- pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND;
-
- pCap->num_antcfg_5ghz =
- ath9k_hw_get_num_ant_config(ahp, IEEE80211_BAND_5GHZ);
- pCap->num_antcfg_2ghz =
- ath9k_hw_get_num_ant_config(ahp, IEEE80211_BAND_2GHZ);
-
- return true;
-}
-
-static void ar5416DisablePciePhy(struct ath_hal *ah)
-{
- if (!AR_SREV_9100(ah))
- return;
-
- REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
- REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
- REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029);
- REG_WRITE(ah, AR_PCIE_SERDES, 0x57160824);
- REG_WRITE(ah, AR_PCIE_SERDES, 0x25980579);
- REG_WRITE(ah, AR_PCIE_SERDES, 0x00000000);
- REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
- REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
- REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007);
-
- REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
-}
-
-static void ath9k_set_power_sleep(struct ath_hal *ah, int setChip)
-{
- REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
- if (setChip) {
- REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
- AR_RTC_FORCE_WAKE_EN);
- if (!AR_SREV_9100(ah))
- REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
-
- REG_CLR_BIT(ah, (u16) (AR_RTC_RESET),
- AR_RTC_RESET_EN);
- }
-}
-
-static void ath9k_set_power_network_sleep(struct ath_hal *ah, int setChip)
-{
- REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
- if (setChip) {
- struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
-
- if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
- REG_WRITE(ah, AR_RTC_FORCE_WAKE,
- AR_RTC_FORCE_WAKE_ON_INT);
- } else {
- REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
- AR_RTC_FORCE_WAKE_EN);
- }
- }
-}
-
-static bool ath9k_hw_set_power_awake(struct ath_hal *ah,
- int setChip)
-{
- u32 val;
- int i;
-
- if (setChip) {
- if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) ==
- AR_RTC_STATUS_SHUTDOWN) {
- if (ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)
- != true) {
- return false;
- }
- }
- if (AR_SREV_9100(ah))
- REG_SET_BIT(ah, AR_RTC_RESET,
- AR_RTC_RESET_EN);
-
- REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
- AR_RTC_FORCE_WAKE_EN);
- udelay(50);
-
- for (i = POWER_UP_TIME / 50; i > 0; i--) {
- val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
- if (val == AR_RTC_STATUS_ON)
- break;
- udelay(50);
- REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
- AR_RTC_FORCE_WAKE_EN);
- }
- if (i == 0) {
- DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
- "%s: Failed to wakeup in %uus\n",
- __func__, POWER_UP_TIME / 20);
- return false;
- }
- }
-
- REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
- return true;
-}
-
-bool ath9k_hw_setpower(struct ath_hal *ah,
- enum ath9k_power_mode mode)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- static const char *modes[] = {
- "AWAKE",
- "FULL-SLEEP",
- "NETWORK SLEEP",
- "UNDEFINED"
- };
- int status = true, setChip = true;
- DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, "%s: %s -> %s (%s)\n", __func__,
- modes[ahp->ah_powerMode], modes[mode],
- setChip ? "set chip " : "");
-
- switch (mode) {
- case ATH9K_PM_AWAKE:
- status = ath9k_hw_set_power_awake(ah, setChip);
- break;
- case ATH9K_PM_FULL_SLEEP:
- ath9k_set_power_sleep(ah, setChip);
- ahp->ah_chipFullSleep = true;
- break;
- case ATH9K_PM_NETWORK_SLEEP:
- ath9k_set_power_network_sleep(ah, setChip);
- break;
- default:
- DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
- "%s: unknown power mode %u\n", __func__, mode);
- return false;
- }
- ahp->ah_powerMode = mode;
- return status;
+ return 0;
}
-static struct ath_hal *ath9k_hw_do_attach(u16 devid,
- struct ath_softc *sc,
- void __iomem *mem,
- int *status)
+static struct ath_hal *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc,
+ void __iomem *mem, int *status)
{
struct ath_hal_5416 *ahp;
struct ath_hal *ah;
int ecode;
-#ifndef CONFIG_SLOW_ANT_DIV
- u32 i;
- u32 j;
-#endif
+ u32 i, j;
ahp = ath9k_hw_newstate(devid, sc, mem, status);
if (ahp == NULL)
@@ -3278,15 +656,13 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid,
ahp->ah_intrMitigation = true;
if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
- DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: couldn't reset chip\n",
- __func__);
+ DPRINTF(ah->ah_sc, ATH_DBG_RESET, "Couldn't reset chip\n");
ecode = -EIO;
goto bad;
}
if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) {
- DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: couldn't wakeup chip\n",
- __func__);
+ DPRINTF(ah->ah_sc, ATH_DBG_RESET, "Couldn't wakeup chip\n");
ecode = -EIO;
goto bad;
}
@@ -3300,18 +676,18 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid,
SER_REG_MODE_OFF;
}
}
+
DPRINTF(ah->ah_sc, ATH_DBG_RESET,
- "%s: serialize_regmode is %d\n",
- __func__, ah->ah_config.serialize_regmode);
+ "serialize_regmode is %d\n",
+ ah->ah_config.serialize_regmode);
if ((ah->ah_macVersion != AR_SREV_VERSION_5416_PCI) &&
(ah->ah_macVersion != AR_SREV_VERSION_5416_PCIE) &&
(ah->ah_macVersion != AR_SREV_VERSION_9160) &&
- (!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah))) {
+ (!AR_SREV_9100(ah)) && (!AR_SREV_9280(ah)) && (!AR_SREV_9285(ah))) {
DPRINTF(ah->ah_sc, ATH_DBG_RESET,
- "%s: Mac Chip Rev 0x%02x.%x is not supported by "
- "this driver\n", __func__,
- ah->ah_macVersion, ah->ah_macRev);
+ "Mac Chip Rev 0x%02x.%x is not supported by "
+ "this driver\n", ah->ah_macVersion, ah->ah_macRev);
ecode = -EOPNOTSUPP;
goto bad;
}
@@ -3341,8 +717,7 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid,
ahp->ah_adcDcCalInitData.calData =
&adc_init_dc_cal;
}
- ahp->ah_suppCals =
- ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
+ ahp->ah_suppCals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL;
}
if (AR_SREV_9160(ah)) {
@@ -3352,16 +727,46 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid,
} else {
ahp->ah_ani_function = ATH9K_ANI_ALL;
if (AR_SREV_9280_10_OR_LATER(ah)) {
- ahp->ah_ani_function &=
- ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
+ ahp->ah_ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL;
}
}
DPRINTF(ah->ah_sc, ATH_DBG_RESET,
- "%s: This Mac Chip Rev 0x%02x.%x is \n", __func__,
- ah->ah_macVersion, ah->ah_macRev);
+ "This Mac Chip Rev 0x%02x.%x is \n",
+ ah->ah_macVersion, ah->ah_macRev);
- if (AR_SREV_9280_20_OR_LATER(ah)) {
+ if (AR_SREV_9285_12_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_iniModes, ar9285Modes_9285_1_2,
+ ARRAY_SIZE(ar9285Modes_9285_1_2), 6);
+ INIT_INI_ARRAY(&ahp->ah_iniCommon, ar9285Common_9285_1_2,
+ ARRAY_SIZE(ar9285Common_9285_1_2), 2);
+
+ if (ah->ah_config.pcie_clock_req) {
+ INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes,
+ ar9285PciePhy_clkreq_off_L1_9285_1_2,
+ ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285_1_2), 2);
+ } else {
+ INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes,
+ ar9285PciePhy_clkreq_always_on_L1_9285_1_2,
+ ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2),
+ 2);
+ }
+ } else if (AR_SREV_9285_10_OR_LATER(ah)) {
+ INIT_INI_ARRAY(&ahp->ah_iniModes, ar9285Modes_9285,
+ ARRAY_SIZE(ar9285Modes_9285), 6);
+ INIT_INI_ARRAY(&ahp->ah_iniCommon, ar9285Common_9285,
+ ARRAY_SIZE(ar9285Common_9285), 2);
+
+ if (ah->ah_config.pcie_clock_req) {
+ INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes,
+ ar9285PciePhy_clkreq_off_L1_9285,
+ ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285), 2);
+ } else {
+ INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes,
+ ar9285PciePhy_clkreq_always_on_L1_9285,
+ ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285), 2);
+ }
+ } else if (AR_SREV_9280_20_OR_LATER(ah)) {
INIT_INI_ARRAY(&ahp->ah_iniModes, ar9280Modes_9280_2,
ARRAY_SIZE(ar9280Modes_9280_2), 6);
INIT_INI_ARRAY(&ahp->ah_iniCommon, ar9280Common_9280_2,
@@ -3369,21 +774,16 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid,
if (ah->ah_config.pcie_clock_req) {
INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes,
- ar9280PciePhy_clkreq_off_L1_9280,
- ARRAY_SIZE
- (ar9280PciePhy_clkreq_off_L1_9280),
- 2);
+ ar9280PciePhy_clkreq_off_L1_9280,
+ ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280),2);
} else {
INIT_INI_ARRAY(&ahp->ah_iniPcieSerdes,
- ar9280PciePhy_clkreq_always_on_L1_9280,
- ARRAY_SIZE
- (ar9280PciePhy_clkreq_always_on_L1_9280),
- 2);
+ ar9280PciePhy_clkreq_always_on_L1_9280,
+ ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2);
}
INIT_INI_ARRAY(&ahp->ah_iniModesAdditional,
ar9280Modes_fast_clock_9280_2,
- ARRAY_SIZE(ar9280Modes_fast_clock_9280_2),
- 3);
+ ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3);
} else if (AR_SREV_9280_10_OR_LATER(ah)) {
INIT_INI_ARRAY(&ahp->ah_iniModes, ar9280Modes_9280,
ARRAY_SIZE(ar9280Modes_9280), 6);
@@ -3469,13 +869,20 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid,
if (ah->ah_isPciExpress)
ath9k_hw_configpcipowersave(ah, 0);
else
- ar5416DisablePciePhy(ah);
+ ath9k_hw_disablepcie(ah);
ecode = ath9k_hw_post_attach(ah);
if (ecode != 0)
goto bad;
-#ifndef CONFIG_SLOW_ANT_DIV
+ /* rxgain table */
+ if (AR_SREV_9280_20(ah))
+ ath9k_hw_init_rxgain_ini(ah);
+
+ /* txgain table */
+ if (AR_SREV_9280_20(ah))
+ ath9k_hw_init_txgain_ini(ah);
+
if (ah->ah_devid == AR9280_DEVID_PCI) {
for (i = 0; i < ahp->ah_iniModes.ia_rows; i++) {
u32 reg = INI_RA(&ahp->ah_iniModes, i, 0);
@@ -3484,16 +891,16 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid,
u32 val = INI_RA(&ahp->ah_iniModes, i, j);
INI_RA(&ahp->ah_iniModes, i, j) =
- ath9k_hw_ini_fixup(ah, &ahp->ah_eeprom,
+ ath9k_hw_ini_fixup(ah,
+ &ahp->ah_eeprom.def,
reg, val);
}
}
}
-#endif
if (!ath9k_hw_fill_cap_info(ah)) {
DPRINTF(ah->ah_sc, ATH_DBG_RESET,
- "%s:failed ath9k_hw_fill_cap_info\n", __func__);
+ "failed ath9k_hw_fill_cap_info\n");
ecode = -EINVAL;
goto bad;
}
@@ -3501,8 +908,7 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid,
ecode = ath9k_hw_init_macaddr(ah);
if (ecode != 0) {
DPRINTF(ah->ah_sc, ATH_DBG_RESET,
- "%s: failed initializing mac address\n",
- __func__);
+ "failed initializing mac address\n");
goto bad;
}
@@ -3511,1106 +917,569 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid,
else
ah->ah_txTrigLevel = (AR_FTRIG_512B >> AR_FTRIG_S);
-#ifndef ATH_NF_PER_CHAN
-
ath9k_init_nfcal_hist_buffer(ah);
-#endif
return ah;
-
bad:
if (ahp)
ath9k_hw_detach((struct ath_hal *) ahp);
if (status)
*status = ecode;
+
return NULL;
}
-void ath9k_hw_detach(struct ath_hal *ah)
+static void ath9k_hw_init_bb(struct ath_hal *ah,
+ struct ath9k_channel *chan)
{
- if (!AR_SREV_9100(ah))
- ath9k_hw_ani_detach(ah);
- ath9k_hw_rfdetach(ah);
+ u32 synthDelay;
- ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
- kfree(ah);
+ synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+ if (IS_CHAN_B(chan))
+ synthDelay = (4 * synthDelay) / 22;
+ else
+ synthDelay /= 10;
+
+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN);
+
+ udelay(synthDelay + BASE_ACTIVATE_DELAY);
}
-bool ath9k_get_channel_edges(struct ath_hal *ah,
- u16 flags, u16 *low,
- u16 *high)
+static void ath9k_hw_init_qos(struct ath_hal *ah)
{
- struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+ REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa);
+ REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210);
- if (flags & CHANNEL_5GHZ) {
- *low = pCap->low_5ghz_chan;
- *high = pCap->high_5ghz_chan;
- return true;
- }
- if ((flags & CHANNEL_2GHZ)) {
- *low = pCap->low_2ghz_chan;
- *high = pCap->high_2ghz_chan;
+ REG_WRITE(ah, AR_QOS_NO_ACK,
+ SM(2, AR_QOS_NO_ACK_TWO_BIT) |
+ SM(5, AR_QOS_NO_ACK_BIT_OFF) |
+ SM(0, AR_QOS_NO_ACK_BYTE_OFF));
- return true;
- }
- return false;
+ REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL);
+ REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF);
+ REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF);
+ REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF);
+ REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF);
}
-static inline bool ath9k_hw_fill_vpd_table(u8 pwrMin,
- u8 pwrMax,
- u8 *pPwrList,
- u8 *pVpdList,
- u16
- numIntercepts,
- u8 *pRetVpdList)
+static void ath9k_hw_init_pll(struct ath_hal *ah,
+ struct ath9k_channel *chan)
{
- u16 i, k;
- u8 currPwr = pwrMin;
- u16 idxL = 0, idxR = 0;
-
- for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
- ath9k_hw_get_lower_upper_index(currPwr, pPwrList,
- numIntercepts, &(idxL),
- &(idxR));
- if (idxR < 1)
- idxR = 1;
- if (idxL == numIntercepts - 1)
- idxL = (u16) (numIntercepts - 2);
- if (pPwrList[idxL] == pPwrList[idxR])
- k = pVpdList[idxL];
- else
- k = (u16) (((currPwr -
- pPwrList[idxL]) *
- pVpdList[idxR] +
- (pPwrList[idxR] -
- currPwr) * pVpdList[idxL]) /
- (pPwrList[idxR] -
- pPwrList[idxL]));
- pRetVpdList[i] = (u8) k;
- currPwr += 2;
- }
+ u32 pll;
- return true;
-}
+ if (AR_SREV_9100(ah)) {
+ if (chan && IS_CHAN_5GHZ(chan))
+ pll = 0x1450;
+ else
+ pll = 0x1458;
+ } else {
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
-static void
-ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hal *ah,
- struct ath9k_channel *chan,
- struct cal_data_per_freq *pRawDataSet,
- u8 *bChans,
- u16 availPiers,
- u16 tPdGainOverlap,
- int16_t *pMinCalPower,
- u16 *pPdGainBoundaries,
- u8 *pPDADCValues,
- u16 numXpdGains)
-{
- int i, j, k;
- int16_t ss;
- u16 idxL = 0, idxR = 0, numPiers;
- static u8 vpdTableL[AR5416_NUM_PD_GAINS]
- [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
- static u8 vpdTableR[AR5416_NUM_PD_GAINS]
- [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
- static u8 vpdTableI[AR5416_NUM_PD_GAINS]
- [AR5416_MAX_PWR_RANGE_IN_HALF_DB];
-
- u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
- u8 minPwrT4[AR5416_NUM_PD_GAINS];
- u8 maxPwrT4[AR5416_NUM_PD_GAINS];
- int16_t vpdStep;
- int16_t tmpVal;
- u16 sizeCurrVpdTable, maxIndex, tgtIndex;
- bool match;
- int16_t minDelta = 0;
- struct chan_centers centers;
+ if (chan && IS_CHAN_HALF_RATE(chan))
+ pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
+ else if (chan && IS_CHAN_QUARTER_RATE(chan))
+ pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
- ath9k_hw_get_channel_centers(ah, chan, &centers);
+ if (chan && IS_CHAN_5GHZ(chan)) {
+ pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
- for (numPiers = 0; numPiers < availPiers; numPiers++) {
- if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
- break;
- }
- match = ath9k_hw_get_lower_upper_index((u8)
- FREQ2FBIN(centers.
- synth_center,
- IS_CHAN_2GHZ
- (chan)), bChans,
- numPiers, &idxL, &idxR);
-
- if (match) {
- for (i = 0; i < numXpdGains; i++) {
- minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0];
- maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4];
- ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
- pRawDataSet[idxL].
- pwrPdg[i],
- pRawDataSet[idxL].
- vpdPdg[i],
- AR5416_PD_GAIN_ICEPTS,
- vpdTableI[i]);
- }
- } else {
- for (i = 0; i < numXpdGains; i++) {
- pVpdL = pRawDataSet[idxL].vpdPdg[i];
- pPwrL = pRawDataSet[idxL].pwrPdg[i];
- pVpdR = pRawDataSet[idxR].vpdPdg[i];
- pPwrR = pRawDataSet[idxR].pwrPdg[i];
-
- minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
-
- maxPwrT4[i] =
- min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1],
- pPwrR[AR5416_PD_GAIN_ICEPTS - 1]);
-
-
- ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
- pPwrL, pVpdL,
- AR5416_PD_GAIN_ICEPTS,
- vpdTableL[i]);
- ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
- pPwrR, pVpdR,
- AR5416_PD_GAIN_ICEPTS,
- vpdTableR[i]);
-
- for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
- vpdTableI[i][j] =
- (u8) (ath9k_hw_interpolate
- ((u16)
- FREQ2FBIN(centers.
- synth_center,
- IS_CHAN_2GHZ
- (chan)),
- bChans[idxL],
- bChans[idxR], vpdTableL[i]
- [j], vpdTableR[i]
- [j]));
+ if (AR_SREV_9280_20(ah)) {
+ if (((chan->channel % 20) == 0)
+ || ((chan->channel % 10) == 0))
+ pll = 0x2850;
+ else
+ pll = 0x142c;
+ }
+ } else {
+ pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
}
- }
- }
- *pMinCalPower = (int16_t) (minPwrT4[0] / 2);
-
- k = 0;
- for (i = 0; i < numXpdGains; i++) {
- if (i == (numXpdGains - 1))
- pPdGainBoundaries[i] =
- (u16) (maxPwrT4[i] / 2);
- else
- pPdGainBoundaries[i] =
- (u16) ((maxPwrT4[i] +
- minPwrT4[i + 1]) / 4);
+ } else if (AR_SREV_9160_10_OR_LATER(ah)) {
- pPdGainBoundaries[i] =
- min((u16) AR5416_MAX_RATE_POWER,
- pPdGainBoundaries[i]);
+ pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
- if ((i == 0) && !AR_SREV_5416_V20_OR_LATER(ah)) {
- minDelta = pPdGainBoundaries[0] - 23;
- pPdGainBoundaries[0] = 23;
- } else {
- minDelta = 0;
- }
+ if (chan && IS_CHAN_HALF_RATE(chan))
+ pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
+ else if (chan && IS_CHAN_QUARTER_RATE(chan))
+ pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
- if (i == 0) {
- if (AR_SREV_9280_10_OR_LATER(ah))
- ss = (int16_t) (0 - (minPwrT4[i] / 2));
+ if (chan && IS_CHAN_5GHZ(chan))
+ pll |= SM(0x50, AR_RTC_9160_PLL_DIV);
else
- ss = 0;
+ pll |= SM(0x58, AR_RTC_9160_PLL_DIV);
} else {
- ss = (int16_t) ((pPdGainBoundaries[i - 1] -
- (minPwrT4[i] / 2)) -
- tPdGainOverlap + 1 + minDelta);
- }
- vpdStep = (int16_t) (vpdTableI[i][1] - vpdTableI[i][0]);
- vpdStep = (int16_t) ((vpdStep < 1) ? 1 : vpdStep);
-
- while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
- tmpVal = (int16_t) (vpdTableI[i][0] + ss * vpdStep);
- pPDADCValues[k++] =
- (u8) ((tmpVal < 0) ? 0 : tmpVal);
- ss++;
- }
-
- sizeCurrVpdTable =
- (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
- tgtIndex = (u8) (pPdGainBoundaries[i] + tPdGainOverlap -
- (minPwrT4[i] / 2));
- maxIndex = (tgtIndex <
- sizeCurrVpdTable) ? tgtIndex : sizeCurrVpdTable;
+ pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
- while ((ss < maxIndex)
- && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
- pPDADCValues[k++] = vpdTableI[i][ss++];
- }
+ if (chan && IS_CHAN_HALF_RATE(chan))
+ pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
+ else if (chan && IS_CHAN_QUARTER_RATE(chan))
+ pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
- vpdStep = (int16_t) (vpdTableI[i][sizeCurrVpdTable - 1] -
- vpdTableI[i][sizeCurrVpdTable - 2]);
- vpdStep = (int16_t) ((vpdStep < 1) ? 1 : vpdStep);
-
- if (tgtIndex > maxIndex) {
- while ((ss <= tgtIndex)
- && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
- tmpVal = (int16_t) ((vpdTableI[i]
- [sizeCurrVpdTable -
- 1] + (ss - maxIndex +
- 1) * vpdStep));
- pPDADCValues[k++] = (u8) ((tmpVal >
- 255) ? 255 : tmpVal);
- ss++;
- }
+ if (chan && IS_CHAN_5GHZ(chan))
+ pll |= SM(0xa, AR_RTC_PLL_DIV);
+ else
+ pll |= SM(0xb, AR_RTC_PLL_DIV);
}
}
+ REG_WRITE(ah, (u16) (AR_RTC_PLL_CONTROL), pll);
- while (i < AR5416_PD_GAINS_IN_MASK) {
- pPdGainBoundaries[i] = pPdGainBoundaries[i - 1];
- i++;
- }
+ udelay(RTC_PLL_SETTLE_DELAY);
- while (k < AR5416_NUM_PDADC_VALUES) {
- pPDADCValues[k] = pPDADCValues[k - 1];
- k++;
- }
- return;
+ REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
}
-static bool
-ath9k_hw_set_power_cal_table(struct ath_hal *ah,
- struct ar5416_eeprom *pEepData,
- struct ath9k_channel *chan,
- int16_t *pTxPowerIndexOffset)
+static void ath9k_hw_init_chain_masks(struct ath_hal *ah)
{
- struct cal_data_per_freq *pRawDataset;
- u8 *pCalBChans = NULL;
- u16 pdGainOverlap_t2;
- static u8 pdadcValues[AR5416_NUM_PDADC_VALUES];
- u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK];
- u16 numPiers, i, j;
- int16_t tMinCalPower;
- u16 numXpdGain, xpdMask;
- u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 };
- u32 reg32, regOffset, regChainOffset;
- int16_t modalIdx;
struct ath_hal_5416 *ahp = AH5416(ah);
+ int rx_chainmask, tx_chainmask;
- modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0;
- xpdMask = pEepData->modalHeader[modalIdx].xpdGain;
-
- if ((pEepData->baseEepHeader.
- version & AR5416_EEP_VER_MINOR_MASK) >=
- AR5416_EEP_MINOR_VER_2) {
- pdGainOverlap_t2 =
- pEepData->modalHeader[modalIdx].pdGainOverlap;
- } else {
- pdGainOverlap_t2 =
- (u16) (MS
- (REG_READ(ah, AR_PHY_TPCRG5),
- AR_PHY_TPCRG5_PD_GAIN_OVERLAP));
- }
-
- if (IS_CHAN_2GHZ(chan)) {
- pCalBChans = pEepData->calFreqPier2G;
- numPiers = AR5416_NUM_2G_CAL_PIERS;
- } else {
- pCalBChans = pEepData->calFreqPier5G;
- numPiers = AR5416_NUM_5G_CAL_PIERS;
- }
-
- numXpdGain = 0;
+ rx_chainmask = ahp->ah_rxchainmask;
+ tx_chainmask = ahp->ah_txchainmask;
- for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) {
- if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) {
- if (numXpdGain >= AR5416_NUM_PD_GAINS)
- break;
- xpdGainValues[numXpdGain] =
- (u16) (AR5416_PD_GAINS_IN_MASK - i);
- numXpdGain++;
+ switch (rx_chainmask) {
+ case 0x5:
+ REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
+ AR_PHY_SWAP_ALT_CHAIN);
+ case 0x3:
+ if (((ah)->ah_macVersion <= AR_SREV_VERSION_9160)) {
+ REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7);
+ REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7);
+ break;
}
+ case 0x1:
+ case 0x2:
+ case 0x7:
+ REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
+ REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
+ break;
+ default:
+ break;
}
- REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN,
- (numXpdGain - 1) & 0x3);
- REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1,
- xpdGainValues[0]);
- REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2,
- xpdGainValues[1]);
- REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3,
- xpdGainValues[2]);
-
- for (i = 0; i < AR5416_MAX_CHAINS; i++) {
- if (AR_SREV_5416_V20_OR_LATER(ah) &&
- (ahp->ah_rxchainmask == 5 || ahp->ah_txchainmask == 5)
- && (i != 0)) {
- regChainOffset = (i == 1) ? 0x2000 : 0x1000;
- } else
- regChainOffset = i * 0x1000;
- if (pEepData->baseEepHeader.txMask & (1 << i)) {
- if (IS_CHAN_2GHZ(chan))
- pRawDataset = pEepData->calPierData2G[i];
- else
- pRawDataset = pEepData->calPierData5G[i];
-
- ath9k_hw_get_gain_boundaries_pdadcs(ah, chan,
- pRawDataset,
- pCalBChans,
- numPiers,
- pdGainOverlap_t2,
- &tMinCalPower,
- gainBoundaries,
- pdadcValues,
- numXpdGain);
-
- if ((i == 0) || AR_SREV_5416_V20_OR_LATER(ah)) {
-
- REG_WRITE(ah,
- AR_PHY_TPCRG5 + regChainOffset,
- SM(pdGainOverlap_t2,
- AR_PHY_TPCRG5_PD_GAIN_OVERLAP)
- | SM(gainBoundaries[0],
- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1)
- | SM(gainBoundaries[1],
- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2)
- | SM(gainBoundaries[2],
- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3)
- | SM(gainBoundaries[3],
- AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4));
- }
-
- regOffset =
- AR_PHY_BASE + (672 << 2) + regChainOffset;
- for (j = 0; j < 32; j++) {
- reg32 =
- ((pdadcValues[4 * j + 0] & 0xFF) << 0)
- | ((pdadcValues[4 * j + 1] & 0xFF) <<
- 8) | ((pdadcValues[4 * j + 2] &
- 0xFF) << 16) |
- ((pdadcValues[4 * j + 3] & 0xFF) <<
- 24);
- REG_WRITE(ah, regOffset, reg32);
-
- DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO,
- "PDADC (%d,%4x): %4.4x %8.8x\n",
- i, regChainOffset, regOffset,
- reg32);
- DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO,
- "PDADC: Chain %d | PDADC %3d Value %3d | "
- "PDADC %3d Value %3d | PDADC %3d Value %3d | "
- "PDADC %3d Value %3d |\n",
- i, 4 * j, pdadcValues[4 * j],
- 4 * j + 1, pdadcValues[4 * j + 1],
- 4 * j + 2, pdadcValues[4 * j + 2],
- 4 * j + 3,
- pdadcValues[4 * j + 3]);
-
- regOffset += 4;
- }
- }
+ REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask);
+ if (tx_chainmask == 0x5) {
+ REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
+ AR_PHY_SWAP_ALT_CHAIN);
}
- *pTxPowerIndexOffset = 0;
-
- return true;
+ if (AR_SREV_9100(ah))
+ REG_WRITE(ah, AR_PHY_ANALOG_SWAP,
+ REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001);
}
-void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore)
+static void ath9k_hw_init_interrupt_masks(struct ath_hal *ah,
+ enum nl80211_iftype opmode)
{
struct ath_hal_5416 *ahp = AH5416(ah);
- u8 i;
-
- if (ah->ah_isPciExpress != true)
- return;
- if (ah->ah_config.pcie_powersave_enable == 2)
- return;
+ ahp->ah_maskReg = AR_IMR_TXERR |
+ AR_IMR_TXURN |
+ AR_IMR_RXERR |
+ AR_IMR_RXORN |
+ AR_IMR_BCNMISC;
- if (restore)
- return;
+ if (ahp->ah_intrMitigation)
+ ahp->ah_maskReg |= AR_IMR_RXINTM | AR_IMR_RXMINTR;
+ else
+ ahp->ah_maskReg |= AR_IMR_RXOK;
- if (AR_SREV_9280_20_OR_LATER(ah)) {
- for (i = 0; i < ahp->ah_iniPcieSerdes.ia_rows; i++) {
- REG_WRITE(ah, INI_RA(&ahp->ah_iniPcieSerdes, i, 0),
- INI_RA(&ahp->ah_iniPcieSerdes, i, 1));
- }
- udelay(1000);
- } else if (AR_SREV_9280(ah)
- && (ah->ah_macRev == AR_SREV_REVISION_9280_10)) {
- REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00);
- REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
+ ahp->ah_maskReg |= AR_IMR_TXOK;
- REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019);
- REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820);
- REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560);
+ if (opmode == NL80211_IFTYPE_AP)
+ ahp->ah_maskReg |= AR_IMR_MIB;
- if (ah->ah_config.pcie_clock_req)
- REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc);
- else
- REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd);
+ REG_WRITE(ah, AR_IMR, ahp->ah_maskReg);
+ REG_WRITE(ah, AR_IMR_S2, REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT);
- REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
- REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
- REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007);
+ if (!AR_SREV_9100(ah)) {
+ REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF);
+ REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT);
+ REG_WRITE(ah, AR_INTR_SYNC_MASK, 0);
+ }
+}
- REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+static bool ath9k_hw_set_ack_timeout(struct ath_hal *ah, u32 us)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
- udelay(1000);
+ if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
+ DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad ack timeout %u\n", us);
+ ahp->ah_acktimeout = (u32) -1;
+ return false;
} else {
- REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
- REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
- REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
- REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
- REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
- REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
- REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
- REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
- REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
- REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+ REG_RMW_FIELD(ah, AR_TIME_OUT,
+ AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us));
+ ahp->ah_acktimeout = us;
+ return true;
}
+}
- REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
+static bool ath9k_hw_set_cts_timeout(struct ath_hal *ah, u32 us)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
- if (ah->ah_config.pcie_waen) {
- REG_WRITE(ah, AR_WA, ah->ah_config.pcie_waen);
+ if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
+ DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad cts timeout %u\n", us);
+ ahp->ah_ctstimeout = (u32) -1;
+ return false;
} else {
- if (AR_SREV_9280(ah))
- REG_WRITE(ah, AR_WA, 0x0040073f);
- else
- REG_WRITE(ah, AR_WA, 0x0000073f);
+ REG_RMW_FIELD(ah, AR_TIME_OUT,
+ AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us));
+ ahp->ah_ctstimeout = us;
+ return true;
}
}
-static void
-ath9k_hw_get_legacy_target_powers(struct ath_hal *ah,
- struct ath9k_channel *chan,
- struct cal_target_power_leg *powInfo,
- u16 numChannels,
- struct cal_target_power_leg *pNewPower,
- u16 numRates,
- bool isExtTarget)
+static bool ath9k_hw_set_global_txtimeout(struct ath_hal *ah, u32 tu)
{
- u16 clo, chi;
- int i;
- int matchIndex = -1, lowIndex = -1;
- u16 freq;
- struct chan_centers centers;
-
- ath9k_hw_get_channel_centers(ah, chan, &centers);
- freq = (isExtTarget) ? centers.ext_center : centers.ctl_center;
+ struct ath_hal_5416 *ahp = AH5416(ah);
- if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel,
- IS_CHAN_2GHZ(chan))) {
- matchIndex = 0;
+ if (tu > 0xFFFF) {
+ DPRINTF(ah->ah_sc, ATH_DBG_XMIT,
+ "bad global tx timeout %u\n", tu);
+ ahp->ah_globaltxtimeout = (u32) -1;
+ return false;
} else {
- for (i = 0; (i < numChannels)
- && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
- if (freq ==
- ath9k_hw_fbin2freq(powInfo[i].bChannel,
- IS_CHAN_2GHZ(chan))) {
- matchIndex = i;
- break;
- } else if ((freq <
- ath9k_hw_fbin2freq(powInfo[i].bChannel,
- IS_CHAN_2GHZ(chan)))
- && (freq >
- ath9k_hw_fbin2freq(powInfo[i - 1].
- bChannel,
- IS_CHAN_2GHZ
- (chan)))) {
- lowIndex = i - 1;
- break;
- }
- }
- if ((matchIndex == -1) && (lowIndex == -1))
- matchIndex = i - 1;
+ REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu);
+ ahp->ah_globaltxtimeout = tu;
+ return true;
}
+}
- if (matchIndex != -1) {
- *pNewPower = powInfo[matchIndex];
- } else {
- clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
- IS_CHAN_2GHZ(chan));
- chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
- IS_CHAN_2GHZ(chan));
-
- for (i = 0; i < numRates; i++) {
- pNewPower->tPow2x[i] =
- (u8) ath9k_hw_interpolate(freq, clo, chi,
- powInfo
- [lowIndex].
- tPow2x[i],
- powInfo
- [lowIndex +
- 1].tPow2x[i]);
- }
- }
+static void ath9k_hw_init_user_settings(struct ath_hal *ah)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ DPRINTF(ah->ah_sc, ATH_DBG_RESET, "ahp->ah_miscMode 0x%x\n",
+ ahp->ah_miscMode);
+
+ if (ahp->ah_miscMode != 0)
+ REG_WRITE(ah, AR_PCU_MISC,
+ REG_READ(ah, AR_PCU_MISC) | ahp->ah_miscMode);
+ if (ahp->ah_slottime != (u32) -1)
+ ath9k_hw_setslottime(ah, ahp->ah_slottime);
+ if (ahp->ah_acktimeout != (u32) -1)
+ ath9k_hw_set_ack_timeout(ah, ahp->ah_acktimeout);
+ if (ahp->ah_ctstimeout != (u32) -1)
+ ath9k_hw_set_cts_timeout(ah, ahp->ah_ctstimeout);
+ if (ahp->ah_globaltxtimeout != (u32) -1)
+ ath9k_hw_set_global_txtimeout(ah, ahp->ah_globaltxtimeout);
}
-static void
-ath9k_hw_get_target_powers(struct ath_hal *ah,
- struct ath9k_channel *chan,
- struct cal_target_power_ht *powInfo,
- u16 numChannels,
- struct cal_target_power_ht *pNewPower,
- u16 numRates,
- bool isHt40Target)
+const char *ath9k_hw_probe(u16 vendorid, u16 devid)
{
- u16 clo, chi;
- int i;
- int matchIndex = -1, lowIndex = -1;
- u16 freq;
- struct chan_centers centers;
+ return vendorid == ATHEROS_VENDOR_ID ?
+ ath9k_hw_devname(devid) : NULL;
+}
- ath9k_hw_get_channel_centers(ah, chan, &centers);
- freq = isHt40Target ? centers.synth_center : centers.ctl_center;
+void ath9k_hw_detach(struct ath_hal *ah)
+{
+ if (!AR_SREV_9100(ah))
+ ath9k_hw_ani_detach(ah);
- if (freq <=
- ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
- matchIndex = 0;
- } else {
- for (i = 0; (i < numChannels)
- && (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
- if (freq ==
- ath9k_hw_fbin2freq(powInfo[i].bChannel,
- IS_CHAN_2GHZ(chan))) {
- matchIndex = i;
- break;
- } else
- if ((freq <
- ath9k_hw_fbin2freq(powInfo[i].bChannel,
- IS_CHAN_2GHZ(chan)))
- && (freq >
- ath9k_hw_fbin2freq(powInfo[i - 1].
- bChannel,
- IS_CHAN_2GHZ
- (chan)))) {
- lowIndex = i - 1;
- break;
- }
- }
- if ((matchIndex == -1) && (lowIndex == -1))
- matchIndex = i - 1;
- }
+ ath9k_hw_rfdetach(ah);
+ ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP);
+ kfree(ah);
+}
- if (matchIndex != -1) {
- *pNewPower = powInfo[matchIndex];
- } else {
- clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
- IS_CHAN_2GHZ(chan));
- chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
- IS_CHAN_2GHZ(chan));
-
- for (i = 0; i < numRates; i++) {
- pNewPower->tPow2x[i] =
- (u8) ath9k_hw_interpolate(freq, clo, chi,
- powInfo
- [lowIndex].
- tPow2x[i],
- powInfo
- [lowIndex +
- 1].tPow2x[i]);
- }
+struct ath_hal *ath9k_hw_attach(u16 devid, struct ath_softc *sc,
+ void __iomem *mem, int *error)
+{
+ struct ath_hal *ah = NULL;
+
+ switch (devid) {
+ case AR5416_DEVID_PCI:
+ case AR5416_DEVID_PCIE:
+ case AR9160_DEVID_PCI:
+ case AR9280_DEVID_PCI:
+ case AR9280_DEVID_PCIE:
+ case AR9285_DEVID_PCIE:
+ ah = ath9k_hw_do_attach(devid, sc, mem, error);
+ break;
+ default:
+ *error = -ENXIO;
+ break;
}
+
+ return ah;
}
-static u16
-ath9k_hw_get_max_edge_power(u16 freq,
- struct cal_ctl_edges *pRdEdgesPower,
- bool is2GHz)
+/*******/
+/* INI */
+/*******/
+
+static void ath9k_hw_override_ini(struct ath_hal *ah,
+ struct ath9k_channel *chan)
{
- u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
- int i;
+ /*
+ * Set the RX_ABORT and RX_DIS and clear if off only after
+ * RXE is set for MAC. This prevents frames with corrupted
+ * descriptor status.
+ */
+ REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
- for (i = 0; (i < AR5416_NUM_BAND_EDGES)
- && (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
- if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
- is2GHz)) {
- twiceMaxEdgePower = pRdEdgesPower[i].tPower;
- break;
- } else if ((i > 0)
- && (freq <
- ath9k_hw_fbin2freq(pRdEdgesPower[i].
- bChannel, is2GHz))) {
- if (ath9k_hw_fbin2freq
- (pRdEdgesPower[i - 1].bChannel, is2GHz) < freq
- && pRdEdgesPower[i - 1].flag) {
- twiceMaxEdgePower =
- pRdEdgesPower[i - 1].tPower;
+
+ if (!AR_SREV_5416_V20_OR_LATER(ah) ||
+ AR_SREV_9280_10_OR_LATER(ah))
+ return;
+
+ REG_WRITE(ah, 0x9800 + (651 << 2), 0x11);
+}
+
+static u32 ath9k_hw_def_ini_fixup(struct ath_hal *ah,
+ struct ar5416_eeprom_def *pEepData,
+ u32 reg, u32 value)
+{
+ struct base_eep_header *pBase = &(pEepData->baseEepHeader);
+
+ switch (ah->ah_devid) {
+ case AR9280_DEVID_PCI:
+ if (reg == 0x7894) {
+ DPRINTF(ah->ah_sc, ATH_DBG_ANY,
+ "ini VAL: %x EEPROM: %x\n", value,
+ (pBase->version & 0xff));
+
+ if ((pBase->version & 0xff) > 0x0a) {
+ DPRINTF(ah->ah_sc, ATH_DBG_ANY,
+ "PWDCLKIND: %d\n",
+ pBase->pwdclkind);
+ value &= ~AR_AN_TOP2_PWDCLKIND;
+ value |= AR_AN_TOP2_PWDCLKIND &
+ (pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S);
+ } else {
+ DPRINTF(ah->ah_sc, ATH_DBG_ANY,
+ "PWDCLKIND Earlier Rev\n");
}
- break;
+
+ DPRINTF(ah->ah_sc, ATH_DBG_ANY,
+ "final ini VAL: %x\n", value);
}
+ break;
}
- return twiceMaxEdgePower;
+
+ return value;
}
-static bool
-ath9k_hw_set_power_per_rate_table(struct ath_hal *ah,
- struct ar5416_eeprom *pEepData,
- struct ath9k_channel *chan,
- int16_t *ratesArray,
- u16 cfgCtl,
- u8 AntennaReduction,
- u8 twiceMaxRegulatoryPower,
- u8 powerLimit)
+static u32 ath9k_hw_ini_fixup(struct ath_hal *ah,
+ struct ar5416_eeprom_def *pEepData,
+ u32 reg, u32 value)
{
- u8 twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
- static const u16 tpScaleReductionTable[5] =
- { 0, 3, 6, 9, AR5416_MAX_RATE_POWER };
+ struct ath_hal_5416 *ahp = AH5416(ah);
- int i;
- int8_t twiceLargestAntenna;
- struct cal_ctl_data *rep;
- struct cal_target_power_leg targetPowerOfdm, targetPowerCck = {
- 0, { 0, 0, 0, 0}
- };
- struct cal_target_power_leg targetPowerOfdmExt = {
- 0, { 0, 0, 0, 0} }, targetPowerCckExt = {
- 0, { 0, 0, 0, 0 }
- };
- struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = {
- 0, {0, 0, 0, 0}
- };
- u8 scaledPower = 0, minCtlPower, maxRegAllowedPower;
- u16 ctlModesFor11a[] =
- { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 };
- u16 ctlModesFor11g[] =
- { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT,
- CTL_2GHT40
- };
- u16 numCtlModes, *pCtlMode, ctlMode, freq;
- struct chan_centers centers;
- int tx_chainmask;
- u8 twiceMinEdgePower;
+ if (ahp->ah_eep_map == EEP_MAP_4KBITS)
+ return value;
+ else
+ return ath9k_hw_def_ini_fixup(ah, pEepData, reg, value);
+}
+
+static int ath9k_hw_process_ini(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ enum ath9k_ht_macmode macmode)
+{
+ int i, regWrites = 0;
struct ath_hal_5416 *ahp = AH5416(ah);
+ u32 modesIndex, freqIndex;
+ int status;
- tx_chainmask = ahp->ah_txchainmask;
+ switch (chan->chanmode) {
+ case CHANNEL_A:
+ case CHANNEL_A_HT20:
+ modesIndex = 1;
+ freqIndex = 1;
+ break;
+ case CHANNEL_A_HT40PLUS:
+ case CHANNEL_A_HT40MINUS:
+ modesIndex = 2;
+ freqIndex = 1;
+ break;
+ case CHANNEL_G:
+ case CHANNEL_G_HT20:
+ case CHANNEL_B:
+ modesIndex = 4;
+ freqIndex = 2;
+ break;
+ case CHANNEL_G_HT40PLUS:
+ case CHANNEL_G_HT40MINUS:
+ modesIndex = 3;
+ freqIndex = 2;
+ break;
- ath9k_hw_get_channel_centers(ah, chan, &centers);
+ default:
+ return -EINVAL;
+ }
- twiceLargestAntenna = max(
- pEepData->modalHeader
- [IS_CHAN_2GHZ(chan)].antennaGainCh[0],
- pEepData->modalHeader
- [IS_CHAN_2GHZ(chan)].antennaGainCh[1]);
+ REG_WRITE(ah, AR_PHY(0), 0x00000007);
- twiceLargestAntenna = max((u8) twiceLargestAntenna,
- pEepData->modalHeader
- [IS_CHAN_2GHZ(chan)].antennaGainCh[2]);
+ REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
- twiceLargestAntenna =
- (int8_t) min(AntennaReduction - twiceLargestAntenna, 0);
+ ath9k_hw_set_addac(ah, chan);
- maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna;
+ if (AR_SREV_5416_V22_OR_LATER(ah)) {
+ REG_WRITE_ARRAY(&ahp->ah_iniAddac, 1, regWrites);
+ } else {
+ struct ar5416IniArray temp;
+ u32 addacSize =
+ sizeof(u32) * ahp->ah_iniAddac.ia_rows *
+ ahp->ah_iniAddac.ia_columns;
- if (ah->ah_tpScale != ATH9K_TP_SCALE_MAX) {
- maxRegAllowedPower -=
- (tpScaleReductionTable[(ah->ah_tpScale)] * 2);
- }
+ memcpy(ahp->ah_addac5416_21,
+ ahp->ah_iniAddac.ia_array, addacSize);
- scaledPower = min(powerLimit, maxRegAllowedPower);
+ (ahp->ah_addac5416_21)[31 * ahp->ah_iniAddac.ia_columns + 1] = 0;
- switch (ar5416_get_ntxchains(tx_chainmask)) {
- case 1:
- break;
- case 2:
- scaledPower -=
- pEepData->modalHeader[IS_CHAN_2GHZ(chan)].
- pwrDecreaseFor2Chain;
- break;
- case 3:
- scaledPower -=
- pEepData->modalHeader[IS_CHAN_2GHZ(chan)].
- pwrDecreaseFor3Chain;
- break;
+ temp.ia_array = ahp->ah_addac5416_21;
+ temp.ia_columns = ahp->ah_iniAddac.ia_columns;
+ temp.ia_rows = ahp->ah_iniAddac.ia_rows;
+ REG_WRITE_ARRAY(&temp, 1, regWrites);
}
- scaledPower = max(0, (int32_t) scaledPower);
-
- if (IS_CHAN_2GHZ(chan)) {
- numCtlModes =
- ARRAY_SIZE(ctlModesFor11g) -
- SUB_NUM_CTL_MODES_AT_2G_40;
- pCtlMode = ctlModesFor11g;
-
- ath9k_hw_get_legacy_target_powers(ah, chan,
- pEepData->
- calTargetPowerCck,
- AR5416_NUM_2G_CCK_TARGET_POWERS,
- &targetPowerCck, 4,
- false);
- ath9k_hw_get_legacy_target_powers(ah, chan,
- pEepData->
- calTargetPower2G,
- AR5416_NUM_2G_20_TARGET_POWERS,
- &targetPowerOfdm, 4,
- false);
- ath9k_hw_get_target_powers(ah, chan,
- pEepData->calTargetPower2GHT20,
- AR5416_NUM_2G_20_TARGET_POWERS,
- &targetPowerHt20, 8, false);
+ REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
- if (IS_CHAN_HT40(chan)) {
- numCtlModes = ARRAY_SIZE(ctlModesFor11g);
- ath9k_hw_get_target_powers(ah, chan,
- pEepData->
- calTargetPower2GHT40,
- AR5416_NUM_2G_40_TARGET_POWERS,
- &targetPowerHt40, 8,
- true);
- ath9k_hw_get_legacy_target_powers(ah, chan,
- pEepData->
- calTargetPowerCck,
- AR5416_NUM_2G_CCK_TARGET_POWERS,
- &targetPowerCckExt,
- 4, true);
- ath9k_hw_get_legacy_target_powers(ah, chan,
- pEepData->
- calTargetPower2G,
- AR5416_NUM_2G_20_TARGET_POWERS,
- &targetPowerOfdmExt,
- 4, true);
- }
- } else {
+ for (i = 0; i < ahp->ah_iniModes.ia_rows; i++) {
+ u32 reg = INI_RA(&ahp->ah_iniModes, i, 0);
+ u32 val = INI_RA(&ahp->ah_iniModes, i, modesIndex);
- numCtlModes =
- ARRAY_SIZE(ctlModesFor11a) -
- SUB_NUM_CTL_MODES_AT_5G_40;
- pCtlMode = ctlModesFor11a;
-
- ath9k_hw_get_legacy_target_powers(ah, chan,
- pEepData->
- calTargetPower5G,
- AR5416_NUM_5G_20_TARGET_POWERS,
- &targetPowerOfdm, 4,
- false);
- ath9k_hw_get_target_powers(ah, chan,
- pEepData->calTargetPower5GHT20,
- AR5416_NUM_5G_20_TARGET_POWERS,
- &targetPowerHt20, 8, false);
+ REG_WRITE(ah, reg, val);
- if (IS_CHAN_HT40(chan)) {
- numCtlModes = ARRAY_SIZE(ctlModesFor11a);
- ath9k_hw_get_target_powers(ah, chan,
- pEepData->
- calTargetPower5GHT40,
- AR5416_NUM_5G_40_TARGET_POWERS,
- &targetPowerHt40, 8,
- true);
- ath9k_hw_get_legacy_target_powers(ah, chan,
- pEepData->
- calTargetPower5G,
- AR5416_NUM_5G_20_TARGET_POWERS,
- &targetPowerOfdmExt,
- 4, true);
+ if (reg >= 0x7800 && reg < 0x78a0
+ && ah->ah_config.analog_shiftreg) {
+ udelay(100);
}
+
+ DO_DELAY(regWrites);
}
- for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) {
- bool isHt40CtlMode =
- (pCtlMode[ctlMode] == CTL_5GHT40)
- || (pCtlMode[ctlMode] == CTL_2GHT40);
- if (isHt40CtlMode)
- freq = centers.synth_center;
- else if (pCtlMode[ctlMode] & EXT_ADDITIVE)
- freq = centers.ext_center;
- else
- freq = centers.ctl_center;
+ if (AR_SREV_9280(ah))
+ REG_WRITE_ARRAY(&ahp->ah_iniModesRxGain, modesIndex, regWrites);
- if (ar5416_get_eep_ver(ahp) == 14
- && ar5416_get_eep_rev(ahp) <= 2)
- twiceMaxEdgePower = AR5416_MAX_RATE_POWER;
+ if (AR_SREV_9280(ah))
+ REG_WRITE_ARRAY(&ahp->ah_iniModesTxGain, modesIndex, regWrites);
- DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
- "LOOP-Mode ctlMode %d < %d, isHt40CtlMode %d, "
- "EXT_ADDITIVE %d\n",
- ctlMode, numCtlModes, isHt40CtlMode,
- (pCtlMode[ctlMode] & EXT_ADDITIVE));
+ for (i = 0; i < ahp->ah_iniCommon.ia_rows; i++) {
+ u32 reg = INI_RA(&ahp->ah_iniCommon, i, 0);
+ u32 val = INI_RA(&ahp->ah_iniCommon, i, 1);
- for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i];
- i++) {
- DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
- " LOOP-Ctlidx %d: cfgCtl 0x%2.2x "
- "pCtlMode 0x%2.2x ctlIndex 0x%2.2x "
- "chan %d\n",
- i, cfgCtl, pCtlMode[ctlMode],
- pEepData->ctlIndex[i], chan->channel);
-
- if ((((cfgCtl & ~CTL_MODE_M) |
- (pCtlMode[ctlMode] & CTL_MODE_M)) ==
- pEepData->ctlIndex[i])
- ||
- (((cfgCtl & ~CTL_MODE_M) |
- (pCtlMode[ctlMode] & CTL_MODE_M)) ==
- ((pEepData->
- ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) {
- rep = &(pEepData->ctlData[i]);
-
- twiceMinEdgePower =
- ath9k_hw_get_max_edge_power(freq,
- rep->
- ctlEdges
- [ar5416_get_ntxchains
- (tx_chainmask)
- - 1],
- IS_CHAN_2GHZ
- (chan));
-
- DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
- " MATCH-EE_IDX %d: ch %d is2 %d "
- "2xMinEdge %d chainmask %d chains %d\n",
- i, freq, IS_CHAN_2GHZ(chan),
- twiceMinEdgePower, tx_chainmask,
- ar5416_get_ntxchains
- (tx_chainmask));
- if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) {
- twiceMaxEdgePower =
- min(twiceMaxEdgePower,
- twiceMinEdgePower);
- } else {
- twiceMaxEdgePower =
- twiceMinEdgePower;
- break;
- }
- }
+ REG_WRITE(ah, reg, val);
+
+ if (reg >= 0x7800 && reg < 0x78a0
+ && ah->ah_config.analog_shiftreg) {
+ udelay(100);
}
- minCtlPower = min(twiceMaxEdgePower, scaledPower);
+ DO_DELAY(regWrites);
+ }
+
+ ath9k_hw_write_regs(ah, modesIndex, freqIndex, regWrites);
- DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
- " SEL-Min ctlMode %d pCtlMode %d "
- "2xMaxEdge %d sP %d minCtlPwr %d\n",
- ctlMode, pCtlMode[ctlMode], twiceMaxEdgePower,
- scaledPower, minCtlPower);
-
- switch (pCtlMode[ctlMode]) {
- case CTL_11B:
- for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x);
- i++) {
- targetPowerCck.tPow2x[i] =
- min(targetPowerCck.tPow2x[i],
- minCtlPower);
- }
- break;
- case CTL_11A:
- case CTL_11G:
- for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x);
- i++) {
- targetPowerOfdm.tPow2x[i] =
- min(targetPowerOfdm.tPow2x[i],
- minCtlPower);
- }
- break;
- case CTL_5GHT20:
- case CTL_2GHT20:
- for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x);
- i++) {
- targetPowerHt20.tPow2x[i] =
- min(targetPowerHt20.tPow2x[i],
- minCtlPower);
- }
- break;
- case CTL_11B_EXT:
- targetPowerCckExt.tPow2x[0] =
- min(targetPowerCckExt.tPow2x[0], minCtlPower);
- break;
- case CTL_11A_EXT:
- case CTL_11G_EXT:
- targetPowerOfdmExt.tPow2x[0] =
- min(targetPowerOfdmExt.tPow2x[0], minCtlPower);
- break;
- case CTL_5GHT40:
- case CTL_2GHT40:
- for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x);
- i++) {
- targetPowerHt40.tPow2x[i] =
- min(targetPowerHt40.tPow2x[i],
- minCtlPower);
- }
- break;
- default:
- break;
- }
+ if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) {
+ REG_WRITE_ARRAY(&ahp->ah_iniModesAdditional, modesIndex,
+ regWrites);
}
- ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] =
- ratesArray[rate18mb] = ratesArray[rate24mb] =
- targetPowerOfdm.tPow2x[0];
- ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1];
- ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2];
- ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3];
- ratesArray[rateXr] = targetPowerOfdm.tPow2x[0];
-
- for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++)
- ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i];
-
- if (IS_CHAN_2GHZ(chan)) {
- ratesArray[rate1l] = targetPowerCck.tPow2x[0];
- ratesArray[rate2s] = ratesArray[rate2l] =
- targetPowerCck.tPow2x[1];
- ratesArray[rate5_5s] = ratesArray[rate5_5l] =
- targetPowerCck.tPow2x[2];
- ;
- ratesArray[rate11s] = ratesArray[rate11l] =
- targetPowerCck.tPow2x[3];
- ;
+ ath9k_hw_override_ini(ah, chan);
+ ath9k_hw_set_regs(ah, chan, macmode);
+ ath9k_hw_init_chain_masks(ah);
+
+ status = ath9k_hw_set_txpower(ah, chan,
+ ath9k_regd_get_ctl(ah, chan),
+ ath9k_regd_get_antenna_allowed(ah,
+ chan),
+ chan->maxRegTxPower * 2,
+ min((u32) MAX_RATE_POWER,
+ (u32) ah->ah_powerLimit));
+ if (status != 0) {
+ DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+ "error init'ing transmit power\n");
+ return -EIO;
}
- if (IS_CHAN_HT40(chan)) {
- for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) {
- ratesArray[rateHt40_0 + i] =
- targetPowerHt40.tPow2x[i];
- }
- ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0];
- ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0];
- ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0];
- if (IS_CHAN_2GHZ(chan)) {
- ratesArray[rateExtCck] =
- targetPowerCckExt.tPow2x[0];
- }
+
+ if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+ "ar5416SetRfRegs failed\n");
+ return -EIO;
}
- return true;
+
+ return 0;
}
-static int
-ath9k_hw_set_txpower(struct ath_hal *ah,
- struct ar5416_eeprom *pEepData,
- struct ath9k_channel *chan,
- u16 cfgCtl,
- u8 twiceAntennaReduction,
- u8 twiceMaxRegulatoryPower,
- u8 powerLimit)
+/****************************************/
+/* Reset and Channel Switching Routines */
+/****************************************/
+
+static void ath9k_hw_set_rfmode(struct ath_hal *ah, struct ath9k_channel *chan)
{
- struct modal_eep_header *pModal =
- &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
- int16_t ratesArray[Ar5416RateSize];
- int16_t txPowerIndexOffset = 0;
- u8 ht40PowerIncForPdadc = 2;
- int i;
+ u32 rfMode = 0;
- memset(ratesArray, 0, sizeof(ratesArray));
+ if (chan == NULL)
+ return;
- if ((pEepData->baseEepHeader.
- version & AR5416_EEP_VER_MINOR_MASK) >=
- AR5416_EEP_MINOR_VER_2) {
- ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc;
- }
+ rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan))
+ ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM;
- if (!ath9k_hw_set_power_per_rate_table(ah, pEepData, chan,
- &ratesArray[0], cfgCtl,
- twiceAntennaReduction,
- twiceMaxRegulatoryPower,
- powerLimit)) {
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "ath9k_hw_set_txpower: unable to set "
- "tx power per rate table\n");
- return -EIO;
- }
+ if (!AR_SREV_9280_10_OR_LATER(ah))
+ rfMode |= (IS_CHAN_5GHZ(chan)) ?
+ AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ;
- if (!ath9k_hw_set_power_cal_table
- (ah, pEepData, chan, &txPowerIndexOffset)) {
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "ath9k_hw_set_txpower: unable to set power table\n");
- return -EIO;
- }
+ if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan))
+ rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE);
- for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
- ratesArray[i] =
- (int16_t) (txPowerIndexOffset + ratesArray[i]);
- if (ratesArray[i] > AR5416_MAX_RATE_POWER)
- ratesArray[i] = AR5416_MAX_RATE_POWER;
- }
+ REG_WRITE(ah, AR_PHY_MODE, rfMode);
+}
- if (AR_SREV_9280_10_OR_LATER(ah)) {
- for (i = 0; i < Ar5416RateSize; i++)
- ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2;
- }
+static void ath9k_hw_mark_phy_inactive(struct ath_hal *ah)
+{
+ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS);
+}
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE1,
- ATH9K_POW_SM(ratesArray[rate18mb], 24)
- | ATH9K_POW_SM(ratesArray[rate12mb], 16)
- | ATH9K_POW_SM(ratesArray[rate9mb], 8)
- | ATH9K_POW_SM(ratesArray[rate6mb], 0)
- );
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE2,
- ATH9K_POW_SM(ratesArray[rate54mb], 24)
- | ATH9K_POW_SM(ratesArray[rate48mb], 16)
- | ATH9K_POW_SM(ratesArray[rate36mb], 8)
- | ATH9K_POW_SM(ratesArray[rate24mb], 0)
- );
-
- if (IS_CHAN_2GHZ(chan)) {
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE3,
- ATH9K_POW_SM(ratesArray[rate2s], 24)
- | ATH9K_POW_SM(ratesArray[rate2l], 16)
- | ATH9K_POW_SM(ratesArray[rateXr], 8)
- | ATH9K_POW_SM(ratesArray[rate1l], 0)
- );
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE4,
- ATH9K_POW_SM(ratesArray[rate11s], 24)
- | ATH9K_POW_SM(ratesArray[rate11l], 16)
- | ATH9K_POW_SM(ratesArray[rate5_5s], 8)
- | ATH9K_POW_SM(ratesArray[rate5_5l], 0)
- );
- }
+static inline void ath9k_hw_set_dma(struct ath_hal *ah)
+{
+ u32 regval;
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE5,
- ATH9K_POW_SM(ratesArray[rateHt20_3], 24)
- | ATH9K_POW_SM(ratesArray[rateHt20_2], 16)
- | ATH9K_POW_SM(ratesArray[rateHt20_1], 8)
- | ATH9K_POW_SM(ratesArray[rateHt20_0], 0)
- );
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE6,
- ATH9K_POW_SM(ratesArray[rateHt20_7], 24)
- | ATH9K_POW_SM(ratesArray[rateHt20_6], 16)
- | ATH9K_POW_SM(ratesArray[rateHt20_5], 8)
- | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)
- );
+ regval = REG_READ(ah, AR_AHB_MODE);
+ REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN);
- if (IS_CHAN_HT40(chan)) {
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE7,
- ATH9K_POW_SM(ratesArray[rateHt40_3] +
- ht40PowerIncForPdadc, 24)
- | ATH9K_POW_SM(ratesArray[rateHt40_2] +
- ht40PowerIncForPdadc, 16)
- | ATH9K_POW_SM(ratesArray[rateHt40_1] +
- ht40PowerIncForPdadc, 8)
- | ATH9K_POW_SM(ratesArray[rateHt40_0] +
- ht40PowerIncForPdadc, 0)
- );
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE8,
- ATH9K_POW_SM(ratesArray[rateHt40_7] +
- ht40PowerIncForPdadc, 24)
- | ATH9K_POW_SM(ratesArray[rateHt40_6] +
- ht40PowerIncForPdadc, 16)
- | ATH9K_POW_SM(ratesArray[rateHt40_5] +
- ht40PowerIncForPdadc, 8)
- | ATH9K_POW_SM(ratesArray[rateHt40_4] +
- ht40PowerIncForPdadc, 0)
- );
-
- REG_WRITE(ah, AR_PHY_POWER_TX_RATE9,
- ATH9K_POW_SM(ratesArray[rateExtOfdm], 24)
- | ATH9K_POW_SM(ratesArray[rateExtCck], 16)
- | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
- | ATH9K_POW_SM(ratesArray[rateDupCck], 0)
- );
- }
+ regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK;
+ REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B);
- REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
- ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
- | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)
- );
+ REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->ah_txTrigLevel);
- i = rate6mb;
- if (IS_CHAN_HT40(chan))
- i = rateHt40_0;
- else if (IS_CHAN_HT20(chan))
- i = rateHt20_0;
+ regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK;
+ REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B);
- if (AR_SREV_9280_10_OR_LATER(ah))
- ah->ah_maxPowerLevel =
- ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2;
- else
- ah->ah_maxPowerLevel = ratesArray[i];
+ REG_WRITE(ah, AR_RXFIFO_CFG, 0x200);
- return 0;
+ if (AR_SREV_9285(ah)) {
+ REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
+ AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE);
+ } else {
+ REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
+ AR_PCU_TXBUF_CTRL_USABLE_SIZE);
+ }
+}
+
+static void ath9k_hw_set_operating_mode(struct ath_hal *ah, int opmode)
+{
+ u32 val;
+
+ val = REG_READ(ah, AR_STA_ID1);
+ val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC);
+ switch (opmode) {
+ case NL80211_IFTYPE_AP:
+ REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP
+ | AR_STA_ID1_KSRCH_MODE);
+ REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC
+ | AR_STA_ID1_KSRCH_MODE);
+ REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
+ break;
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_MONITOR:
+ REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE);
+ break;
+ }
}
static inline void ath9k_hw_get_delta_slope_vals(struct ath_hal *ah,
@@ -4632,9 +1501,8 @@ static inline void ath9k_hw_get_delta_slope_vals(struct ath_hal *ah,
*coef_exponent = coef_exp - 16;
}
-static void
-ath9k_hw_set_delta_slope(struct ath_hal *ah,
- struct ath9k_channel *chan)
+static void ath9k_hw_set_delta_slope(struct ath_hal *ah,
+ struct ath9k_channel *chan)
{
u32 coef_scaled, ds_coef_exp, ds_coef_man;
u32 clockMhzScaled = 0x64000000;
@@ -4667,8 +1535,243 @@ ath9k_hw_set_delta_slope(struct ath_hal *ah,
AR_PHY_HALFGI_DSC_EXP, ds_coef_exp);
}
-static void ath9k_hw_9280_spur_mitigate(struct ath_hal *ah,
- struct ath9k_channel *chan)
+static bool ath9k_hw_set_reset(struct ath_hal *ah, int type)
+{
+ u32 rst_flags;
+ u32 tmpReg;
+
+ REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
+ AR_RTC_FORCE_WAKE_ON_INT);
+
+ if (AR_SREV_9100(ah)) {
+ rst_flags = AR_RTC_RC_MAC_WARM | AR_RTC_RC_MAC_COLD |
+ AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET;
+ } else {
+ tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE);
+ if (tmpReg &
+ (AR_INTR_SYNC_LOCAL_TIMEOUT |
+ AR_INTR_SYNC_RADM_CPL_TIMEOUT)) {
+ REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0);
+ REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
+ } else {
+ REG_WRITE(ah, AR_RC, AR_RC_AHB);
+ }
+
+ rst_flags = AR_RTC_RC_MAC_WARM;
+ if (type == ATH9K_RESET_COLD)
+ rst_flags |= AR_RTC_RC_MAC_COLD;
+ }
+
+ REG_WRITE(ah, (u16) (AR_RTC_RC), rst_flags);
+ udelay(50);
+
+ REG_WRITE(ah, (u16) (AR_RTC_RC), 0);
+ if (!ath9k_hw_wait(ah, (u16) (AR_RTC_RC), AR_RTC_RC_M, 0)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_RESET,
+ "RTC stuck in MAC reset\n");
+ return false;
+ }
+
+ if (!AR_SREV_9100(ah))
+ REG_WRITE(ah, AR_RC, 0);
+
+ ath9k_hw_init_pll(ah, NULL);
+
+ if (AR_SREV_9100(ah))
+ udelay(50);
+
+ return true;
+}
+
+static bool ath9k_hw_set_reset_power_on(struct ath_hal *ah)
+{
+ REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN |
+ AR_RTC_FORCE_WAKE_ON_INT);
+
+ REG_WRITE(ah, (u16) (AR_RTC_RESET), 0);
+ REG_WRITE(ah, (u16) (AR_RTC_RESET), 1);
+
+ if (!ath9k_hw_wait(ah,
+ AR_RTC_STATUS,
+ AR_RTC_STATUS_M,
+ AR_RTC_STATUS_ON)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_RESET, "RTC not waking up\n");
+ return false;
+ }
+
+ ath9k_hw_read_revisions(ah);
+
+ return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM);
+}
+
+static bool ath9k_hw_set_reset_reg(struct ath_hal *ah, u32 type)
+{
+ REG_WRITE(ah, AR_RTC_FORCE_WAKE,
+ AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT);
+
+ switch (type) {
+ case ATH9K_RESET_POWER_ON:
+ return ath9k_hw_set_reset_power_on(ah);
+ break;
+ case ATH9K_RESET_WARM:
+ case ATH9K_RESET_COLD:
+ return ath9k_hw_set_reset(ah, type);
+ break;
+ default:
+ return false;
+ }
+}
+
+static void ath9k_hw_set_regs(struct ath_hal *ah, struct ath9k_channel *chan,
+ enum ath9k_ht_macmode macmode)
+{
+ u32 phymode;
+ u32 enableDacFifo = 0;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ if (AR_SREV_9285_10_OR_LATER(ah))
+ enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) &
+ AR_PHY_FC_ENABLE_DAC_FIFO);
+
+ phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40
+ | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH | enableDacFifo;
+
+ if (IS_CHAN_HT40(chan)) {
+ phymode |= AR_PHY_FC_DYN2040_EN;
+
+ if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
+ (chan->chanmode == CHANNEL_G_HT40PLUS))
+ phymode |= AR_PHY_FC_DYN2040_PRI_CH;
+
+ if (ahp->ah_extprotspacing == ATH9K_HT_EXTPROTSPACING_25)
+ phymode |= AR_PHY_FC_DYN2040_EXT_CH;
+ }
+ REG_WRITE(ah, AR_PHY_TURBO, phymode);
+
+ ath9k_hw_set11nmac2040(ah, macmode);
+
+ REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S);
+ REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S);
+}
+
+static bool ath9k_hw_chip_reset(struct ath_hal *ah,
+ struct ath9k_channel *chan)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
+ return false;
+
+ if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
+ return false;
+
+ ahp->ah_chipFullSleep = false;
+
+ ath9k_hw_init_pll(ah, chan);
+
+ ath9k_hw_set_rfmode(ah, chan);
+
+ return true;
+}
+
+static struct ath9k_channel *ath9k_hw_check_chan(struct ath_hal *ah,
+ struct ath9k_channel *chan)
+{
+ if (!(IS_CHAN_2GHZ(chan) ^ IS_CHAN_5GHZ(chan))) {
+ DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
+ "invalid channel %u/0x%x; not marked as "
+ "2GHz or 5GHz\n", chan->channel, chan->channelFlags);
+ return NULL;
+ }
+
+ if (!IS_CHAN_OFDM(chan) &&
+ !IS_CHAN_B(chan) &&
+ !IS_CHAN_HT20(chan) &&
+ !IS_CHAN_HT40(chan)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
+ "invalid channel %u/0x%x; not marked as "
+ "OFDM or CCK or HT20 or HT40PLUS or HT40MINUS\n",
+ chan->channel, chan->channelFlags);
+ return NULL;
+ }
+
+ return ath9k_regd_check_channel(ah, chan);
+}
+
+static bool ath9k_hw_channel_change(struct ath_hal *ah,
+ struct ath9k_channel *chan,
+ enum ath9k_ht_macmode macmode)
+{
+ u32 synthDelay, qnum;
+
+ for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
+ if (ath9k_hw_numtxpending(ah, qnum)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
+ "Transmit frames pending on queue %d\n", qnum);
+ return false;
+ }
+ }
+
+ REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
+ if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,
+ AR_PHY_RFBUS_GRANT_EN)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
+ "Could not kill baseband RX\n");
+ return false;
+ }
+
+ ath9k_hw_set_regs(ah, chan, macmode);
+
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ if (!(ath9k_hw_ar9280_set_channel(ah, chan))) {
+ DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
+ "failed to set channel\n");
+ return false;
+ }
+ } else {
+ if (!(ath9k_hw_set_channel(ah, chan))) {
+ DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
+ "failed to set channel\n");
+ return false;
+ }
+ }
+
+ if (ath9k_hw_set_txpower(ah, chan,
+ ath9k_regd_get_ctl(ah, chan),
+ ath9k_regd_get_antenna_allowed(ah, chan),
+ chan->maxRegTxPower * 2,
+ min((u32) MAX_RATE_POWER,
+ (u32) ah->ah_powerLimit)) != 0) {
+ DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
+ "error init'ing transmit power\n");
+ return false;
+ }
+
+ synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
+ if (IS_CHAN_B(chan))
+ synthDelay = (4 * synthDelay) / 22;
+ else
+ synthDelay /= 10;
+
+ udelay(synthDelay + BASE_ACTIVATE_DELAY);
+
+ REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
+
+ if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
+ ath9k_hw_set_delta_slope(ah, chan);
+
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ ath9k_hw_9280_spur_mitigate(ah, chan);
+ else
+ ath9k_hw_spur_mitigate(ah, chan);
+
+ if (!chan->oneTimeCalsDone)
+ chan->oneTimeCalsDone = true;
+
+ return true;
+}
+
+static void ath9k_hw_9280_spur_mitigate(struct ath_hal *ah, struct ath9k_channel *chan)
{
int bb_spur = AR_NO_SPUR;
int freq;
@@ -4918,8 +2021,7 @@ static void ath9k_hw_9280_spur_mitigate(struct ath_hal *ah,
REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
}
-static void ath9k_hw_spur_mitigate(struct ath_hal *ah,
- struct ath9k_channel *chan)
+static void ath9k_hw_spur_mitigate(struct ath_hal *ah, struct ath9k_channel *chan)
{
int bb_spur = AR_NO_SPUR;
int bin, cur_bin;
@@ -5120,752 +2222,11 @@ static void ath9k_hw_spur_mitigate(struct ath_hal *ah,
REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask);
}
-static void ath9k_hw_init_chain_masks(struct ath_hal *ah)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- int rx_chainmask, tx_chainmask;
-
- rx_chainmask = ahp->ah_rxchainmask;
- tx_chainmask = ahp->ah_txchainmask;
-
- switch (rx_chainmask) {
- case 0x5:
- REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
- AR_PHY_SWAP_ALT_CHAIN);
- case 0x3:
- if (((ah)->ah_macVersion <= AR_SREV_VERSION_9160)) {
- REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7);
- REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7);
- break;
- }
- case 0x1:
- case 0x2:
- if (!AR_SREV_9280(ah))
- break;
- case 0x7:
- REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask);
- REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask);
- break;
- default:
- break;
- }
-
- REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask);
- if (tx_chainmask == 0x5) {
- REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
- AR_PHY_SWAP_ALT_CHAIN);
- }
- if (AR_SREV_9100(ah))
- REG_WRITE(ah, AR_PHY_ANALOG_SWAP,
- REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001);
-}
-
-static void ath9k_hw_set_addac(struct ath_hal *ah,
- struct ath9k_channel *chan)
-{
- struct modal_eep_header *pModal;
- struct ath_hal_5416 *ahp = AH5416(ah);
- struct ar5416_eeprom *eep = &ahp->ah_eeprom;
- u8 biaslevel;
-
- if (ah->ah_macVersion != AR_SREV_VERSION_9160)
- return;
-
- if (ar5416_get_eep_rev(ahp) < AR5416_EEP_MINOR_VER_7)
- return;
-
- pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]);
-
- if (pModal->xpaBiasLvl != 0xff) {
- biaslevel = pModal->xpaBiasLvl;
- } else {
-
- u16 resetFreqBin, freqBin, freqCount = 0;
- struct chan_centers centers;
-
- ath9k_hw_get_channel_centers(ah, chan, &centers);
-
- resetFreqBin =
- FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan));
- freqBin = pModal->xpaBiasLvlFreq[0] & 0xff;
- biaslevel = (u8) (pModal->xpaBiasLvlFreq[0] >> 14);
-
- freqCount++;
-
- while (freqCount < 3) {
- if (pModal->xpaBiasLvlFreq[freqCount] == 0x0)
- break;
-
- freqBin = pModal->xpaBiasLvlFreq[freqCount] & 0xff;
- if (resetFreqBin >= freqBin) {
- biaslevel =
- (u8) (pModal->
- xpaBiasLvlFreq[freqCount]
- >> 14);
- } else {
- break;
- }
- freqCount++;
- }
- }
-
- if (IS_CHAN_2GHZ(chan)) {
- INI_RA(&ahp->ah_iniAddac, 7, 1) =
- (INI_RA(&ahp->ah_iniAddac, 7, 1) & (~0x18)) | biaslevel
- << 3;
- } else {
- INI_RA(&ahp->ah_iniAddac, 6, 1) =
- (INI_RA(&ahp->ah_iniAddac, 6, 1) & (~0xc0)) | biaslevel
- << 6;
- }
-}
-
-static u32 ath9k_hw_mac_usec(struct ath_hal *ah, u32 clks)
-{
- if (ah->ah_curchan != NULL)
- return clks /
- CLOCK_RATE[ath9k_hw_chan2wmode(ah, ah->ah_curchan)];
- else
- return clks / CLOCK_RATE[ATH9K_MODE_11B];
-}
-
-static u32 ath9k_hw_mac_to_usec(struct ath_hal *ah, u32 clks)
-{
- struct ath9k_channel *chan = ah->ah_curchan;
-
- if (chan && IS_CHAN_HT40(chan))
- return ath9k_hw_mac_usec(ah, clks) / 2;
- else
- return ath9k_hw_mac_usec(ah, clks);
-}
-
-static u32 ath9k_hw_mac_clks(struct ath_hal *ah, u32 usecs)
-{
- if (ah->ah_curchan != NULL)
- return usecs * CLOCK_RATE[ath9k_hw_chan2wmode(ah,
- ah->ah_curchan)];
- else
- return usecs * CLOCK_RATE[ATH9K_MODE_11B];
-}
-
-static u32 ath9k_hw_mac_to_clks(struct ath_hal *ah, u32 usecs)
-{
- struct ath9k_channel *chan = ah->ah_curchan;
-
- if (chan && IS_CHAN_HT40(chan))
- return ath9k_hw_mac_clks(ah, usecs) * 2;
- else
- return ath9k_hw_mac_clks(ah, usecs);
-}
-
-static bool ath9k_hw_set_ack_timeout(struct ath_hal *ah, u32 us)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
-
- if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) {
- DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: bad ack timeout %u\n",
- __func__, us);
- ahp->ah_acktimeout = (u32) -1;
- return false;
- } else {
- REG_RMW_FIELD(ah, AR_TIME_OUT,
- AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us));
- ahp->ah_acktimeout = us;
- return true;
- }
-}
-
-static bool ath9k_hw_set_cts_timeout(struct ath_hal *ah, u32 us)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
-
- if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) {
- DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: bad cts timeout %u\n",
- __func__, us);
- ahp->ah_ctstimeout = (u32) -1;
- return false;
- } else {
- REG_RMW_FIELD(ah, AR_TIME_OUT,
- AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us));
- ahp->ah_ctstimeout = us;
- return true;
- }
-}
-static bool ath9k_hw_set_global_txtimeout(struct ath_hal *ah,
- u32 tu)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
-
- if (tu > 0xFFFF) {
- DPRINTF(ah->ah_sc, ATH_DBG_XMIT,
- "%s: bad global tx timeout %u\n", __func__, tu);
- ahp->ah_globaltxtimeout = (u32) -1;
- return false;
- } else {
- REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu);
- ahp->ah_globaltxtimeout = tu;
- return true;
- }
-}
-
-bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
-
- if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) {
- DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: bad slot time %u\n",
- __func__, us);
- ahp->ah_slottime = (u32) -1;
- return false;
- } else {
- REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us));
- ahp->ah_slottime = us;
- return true;
- }
-}
-
-static void ath9k_hw_init_user_settings(struct ath_hal *ah)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
-
- DPRINTF(ah->ah_sc, ATH_DBG_RESET, "--AP %s ahp->ah_miscMode 0x%x\n",
- __func__, ahp->ah_miscMode);
- if (ahp->ah_miscMode != 0)
- REG_WRITE(ah, AR_PCU_MISC,
- REG_READ(ah, AR_PCU_MISC) | ahp->ah_miscMode);
- if (ahp->ah_slottime != (u32) -1)
- ath9k_hw_setslottime(ah, ahp->ah_slottime);
- if (ahp->ah_acktimeout != (u32) -1)
- ath9k_hw_set_ack_timeout(ah, ahp->ah_acktimeout);
- if (ahp->ah_ctstimeout != (u32) -1)
- ath9k_hw_set_cts_timeout(ah, ahp->ah_ctstimeout);
- if (ahp->ah_globaltxtimeout != (u32) -1)
- ath9k_hw_set_global_txtimeout(ah, ahp->ah_globaltxtimeout);
-}
-
-static int
-ath9k_hw_process_ini(struct ath_hal *ah,
- struct ath9k_channel *chan,
- enum ath9k_ht_macmode macmode)
-{
- int i, regWrites = 0;
- struct ath_hal_5416 *ahp = AH5416(ah);
- u32 modesIndex, freqIndex;
- int status;
-
- switch (chan->chanmode) {
- case CHANNEL_A:
- case CHANNEL_A_HT20:
- modesIndex = 1;
- freqIndex = 1;
- break;
- case CHANNEL_A_HT40PLUS:
- case CHANNEL_A_HT40MINUS:
- modesIndex = 2;
- freqIndex = 1;
- break;
- case CHANNEL_G:
- case CHANNEL_G_HT20:
- case CHANNEL_B:
- modesIndex = 4;
- freqIndex = 2;
- break;
- case CHANNEL_G_HT40PLUS:
- case CHANNEL_G_HT40MINUS:
- modesIndex = 3;
- freqIndex = 2;
- break;
-
- default:
- return -EINVAL;
- }
-
- REG_WRITE(ah, AR_PHY(0), 0x00000007);
-
- REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO);
-
- ath9k_hw_set_addac(ah, chan);
-
- if (AR_SREV_5416_V22_OR_LATER(ah)) {
- REG_WRITE_ARRAY(&ahp->ah_iniAddac, 1, regWrites);
- } else {
- struct ar5416IniArray temp;
- u32 addacSize =
- sizeof(u32) * ahp->ah_iniAddac.ia_rows *
- ahp->ah_iniAddac.ia_columns;
-
- memcpy(ahp->ah_addac5416_21,
- ahp->ah_iniAddac.ia_array, addacSize);
-
- (ahp->ah_addac5416_21)[31 *
- ahp->ah_iniAddac.ia_columns + 1] = 0;
-
- temp.ia_array = ahp->ah_addac5416_21;
- temp.ia_columns = ahp->ah_iniAddac.ia_columns;
- temp.ia_rows = ahp->ah_iniAddac.ia_rows;
- REG_WRITE_ARRAY(&temp, 1, regWrites);
- }
- REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC);
-
- for (i = 0; i < ahp->ah_iniModes.ia_rows; i++) {
- u32 reg = INI_RA(&ahp->ah_iniModes, i, 0);
- u32 val = INI_RA(&ahp->ah_iniModes, i, modesIndex);
-
-#ifdef CONFIG_SLOW_ANT_DIV
- if (ah->ah_devid == AR9280_DEVID_PCI)
- val = ath9k_hw_ini_fixup(ah, &ahp->ah_eeprom, reg,
- val);
-#endif
-
- REG_WRITE(ah, reg, val);
-
- if (reg >= 0x7800 && reg < 0x78a0
- && ah->ah_config.analog_shiftreg) {
- udelay(100);
- }
-
- DO_DELAY(regWrites);
- }
-
- for (i = 0; i < ahp->ah_iniCommon.ia_rows; i++) {
- u32 reg = INI_RA(&ahp->ah_iniCommon, i, 0);
- u32 val = INI_RA(&ahp->ah_iniCommon, i, 1);
-
- REG_WRITE(ah, reg, val);
-
- if (reg >= 0x7800 && reg < 0x78a0
- && ah->ah_config.analog_shiftreg) {
- udelay(100);
- }
-
- DO_DELAY(regWrites);
- }
-
- ath9k_hw_write_regs(ah, modesIndex, freqIndex, regWrites);
-
- if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) {
- REG_WRITE_ARRAY(&ahp->ah_iniModesAdditional, modesIndex,
- regWrites);
- }
-
- ath9k_hw_override_ini(ah, chan);
- ath9k_hw_set_regs(ah, chan, macmode);
- ath9k_hw_init_chain_masks(ah);
-
- status = ath9k_hw_set_txpower(ah, &ahp->ah_eeprom, chan,
- ath9k_regd_get_ctl(ah, chan),
- ath9k_regd_get_antenna_allowed(ah,
- chan),
- chan->maxRegTxPower * 2,
- min((u32) MAX_RATE_POWER,
- (u32) ah->ah_powerLimit));
- if (status != 0) {
- DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
- "%s: error init'ing transmit power\n", __func__);
- return -EIO;
- }
-
- if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) {
- DPRINTF(ah->ah_sc, ATH_DBG_REG_IO,
- "%s: ar5416SetRfRegs failed\n", __func__);
- return -EIO;
- }
-
- return 0;
-}
-
-static void ath9k_hw_setup_calibration(struct ath_hal *ah,
- struct hal_cal_list *currCal)
-{
- REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0),
- AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX,
- currCal->calData->calCountMax);
-
- switch (currCal->calData->calType) {
- case IQ_MISMATCH_CAL:
- REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "%s: starting IQ Mismatch Calibration\n",
- __func__);
- break;
- case ADC_GAIN_CAL:
- REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "%s: starting ADC Gain Calibration\n", __func__);
- break;
- case ADC_DC_CAL:
- REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "%s: starting ADC DC Calibration\n", __func__);
- break;
- case ADC_DC_INIT_CAL:
- REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "%s: starting Init ADC DC Calibration\n",
- __func__);
- break;
- }
-
- REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
- AR_PHY_TIMING_CTRL4_DO_CAL);
-}
-
-static void ath9k_hw_reset_calibration(struct ath_hal *ah,
- struct hal_cal_list *currCal)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- int i;
-
- ath9k_hw_setup_calibration(ah, currCal);
-
- currCal->calState = CAL_RUNNING;
-
- for (i = 0; i < AR5416_MAX_CHAINS; i++) {
- ahp->ah_Meas0.sign[i] = 0;
- ahp->ah_Meas1.sign[i] = 0;
- ahp->ah_Meas2.sign[i] = 0;
- ahp->ah_Meas3.sign[i] = 0;
- }
-
- ahp->ah_CalSamples = 0;
-}
-
-static void
-ath9k_hw_per_calibration(struct ath_hal *ah,
- struct ath9k_channel *ichan,
- u8 rxchainmask,
- struct hal_cal_list *currCal,
- bool *isCalDone)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
-
- *isCalDone = false;
-
- if (currCal->calState == CAL_RUNNING) {
- if (!(REG_READ(ah,
- AR_PHY_TIMING_CTRL4(0)) &
- AR_PHY_TIMING_CTRL4_DO_CAL)) {
-
- currCal->calData->calCollect(ah);
-
- ahp->ah_CalSamples++;
-
- if (ahp->ah_CalSamples >=
- currCal->calData->calNumSamples) {
- int i, numChains = 0;
- for (i = 0; i < AR5416_MAX_CHAINS; i++) {
- if (rxchainmask & (1 << i))
- numChains++;
- }
-
- currCal->calData->calPostProc(ah,
- numChains);
-
- ichan->CalValid |=
- currCal->calData->calType;
- currCal->calState = CAL_DONE;
- *isCalDone = true;
- } else {
- ath9k_hw_setup_calibration(ah, currCal);
- }
- }
- } else if (!(ichan->CalValid & currCal->calData->calType)) {
- ath9k_hw_reset_calibration(ah, currCal);
- }
-}
-
-static inline bool ath9k_hw_run_init_cals(struct ath_hal *ah,
- int init_cal_count)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- struct ath9k_channel ichan;
- bool isCalDone;
- struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
- const struct hal_percal_data *calData = currCal->calData;
- int i;
-
- if (currCal == NULL)
- return false;
-
- ichan.CalValid = 0;
-
- for (i = 0; i < init_cal_count; i++) {
- ath9k_hw_reset_calibration(ah, currCal);
-
- if (!ath9k_hw_wait(ah, AR_PHY_TIMING_CTRL4(0),
- AR_PHY_TIMING_CTRL4_DO_CAL, 0)) {
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "%s: Cal %d failed to complete in 100ms.\n",
- __func__, calData->calType);
-
- ahp->ah_cal_list = ahp->ah_cal_list_last =
- ahp->ah_cal_list_curr = NULL;
- return false;
- }
-
- ath9k_hw_per_calibration(ah, &ichan, ahp->ah_rxchainmask,
- currCal, &isCalDone);
- if (!isCalDone) {
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "%s: Not able to run Init Cal %d.\n",
- __func__, calData->calType);
- }
- if (currCal->calNext) {
- currCal = currCal->calNext;
- calData = currCal->calData;
- }
- }
-
- ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = NULL;
- return true;
-}
-
-static bool
-ath9k_hw_channel_change(struct ath_hal *ah,
- struct ath9k_channel *chan,
- enum ath9k_ht_macmode macmode)
-{
- u32 synthDelay, qnum;
- struct ath_hal_5416 *ahp = AH5416(ah);
-
- for (qnum = 0; qnum < AR_NUM_QCU; qnum++) {
- if (ath9k_hw_numtxpending(ah, qnum)) {
- DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
- "%s: Transmit frames pending on queue %d\n",
- __func__, qnum);
- return false;
- }
- }
-
- REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN);
- if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN,
- AR_PHY_RFBUS_GRANT_EN)) {
- DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO,
- "%s: Could not kill baseband RX\n", __func__);
- return false;
- }
-
- ath9k_hw_set_regs(ah, chan, macmode);
-
- if (AR_SREV_9280_10_OR_LATER(ah)) {
- if (!(ath9k_hw_ar9280_set_channel(ah, chan))) {
- DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
- "%s: failed to set channel\n", __func__);
- return false;
- }
- } else {
- if (!(ath9k_hw_set_channel(ah, chan))) {
- DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
- "%s: failed to set channel\n", __func__);
- return false;
- }
- }
-
- if (ath9k_hw_set_txpower(ah, &ahp->ah_eeprom, chan,
- ath9k_regd_get_ctl(ah, chan),
- ath9k_regd_get_antenna_allowed(ah, chan),
- chan->maxRegTxPower * 2,
- min((u32) MAX_RATE_POWER,
- (u32) ah->ah_powerLimit)) != 0) {
- DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "%s: error init'ing transmit power\n", __func__);
- return false;
- }
-
- synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY;
- if (IS_CHAN_CCK(chan))
- synthDelay = (4 * synthDelay) / 22;
- else
- synthDelay /= 10;
-
- udelay(synthDelay + BASE_ACTIVATE_DELAY);
-
- REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0);
-
- if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan))
- ath9k_hw_set_delta_slope(ah, chan);
-
- if (AR_SREV_9280_10_OR_LATER(ah))
- ath9k_hw_9280_spur_mitigate(ah, chan);
- else
- ath9k_hw_spur_mitigate(ah, chan);
-
- if (!chan->oneTimeCalsDone)
- chan->oneTimeCalsDone = true;
-
- return true;
-}
-
-static bool ath9k_hw_chip_reset(struct ath_hal *ah,
- struct ath9k_channel *chan)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
-
- if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM))
- return false;
-
- if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
- return false;
-
- ahp->ah_chipFullSleep = false;
-
- ath9k_hw_init_pll(ah, chan);
-
- ath9k_hw_set_rfmode(ah, chan);
-
- return true;
-}
-
-static inline void ath9k_hw_set_dma(struct ath_hal *ah)
-{
- u32 regval;
-
- regval = REG_READ(ah, AR_AHB_MODE);
- REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN);
-
- regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK;
- REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B);
-
- REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->ah_txTrigLevel);
-
- regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK;
- REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B);
-
- REG_WRITE(ah, AR_RXFIFO_CFG, 0x200);
-
- if (AR_SREV_9285(ah)) {
- REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
- AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE);
- } else {
- REG_WRITE(ah, AR_PCU_TXBUF_CTRL,
- AR_PCU_TXBUF_CTRL_USABLE_SIZE);
- }
-}
-
-bool ath9k_hw_stopdmarecv(struct ath_hal *ah)
-{
- REG_WRITE(ah, AR_CR, AR_CR_RXD);
- if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0)) {
- DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
- "%s: dma failed to stop in 10ms\n"
- "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n",
- __func__,
- REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW));
- return false;
- } else {
- return true;
- }
-}
-
-void ath9k_hw_startpcureceive(struct ath_hal *ah)
-{
- REG_CLR_BIT(ah, AR_DIAG_SW,
- (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
-
- ath9k_enable_mib_counters(ah);
-
- ath9k_ani_reset(ah);
-}
-
-void ath9k_hw_stoppcurecv(struct ath_hal *ah)
-{
- REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
-
- ath9k_hw_disable_mib_counters(ah);
-}
-
-static bool ath9k_hw_iscal_supported(struct ath_hal *ah,
- struct ath9k_channel *chan,
- enum hal_cal_types calType)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- bool retval = false;
-
- switch (calType & ahp->ah_suppCals) {
- case IQ_MISMATCH_CAL:
- if (!IS_CHAN_B(chan))
- retval = true;
- break;
- case ADC_GAIN_CAL:
- case ADC_DC_CAL:
- if (!IS_CHAN_B(chan)
- && !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan)))
- retval = true;
- break;
- }
-
- return retval;
-}
-
-static bool ath9k_hw_init_cal(struct ath_hal *ah,
- struct ath9k_channel *chan)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- struct ath9k_channel *ichan =
- ath9k_regd_check_channel(ah, chan);
-
- REG_WRITE(ah, AR_PHY_AGC_CONTROL,
- REG_READ(ah, AR_PHY_AGC_CONTROL) |
- AR_PHY_AGC_CONTROL_CAL);
-
- if (!ath9k_hw_wait
- (ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, 0)) {
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "%s: offset calibration failed to complete in 1ms; "
- "noisy environment?\n", __func__);
- return false;
- }
-
- REG_WRITE(ah, AR_PHY_AGC_CONTROL,
- REG_READ(ah, AR_PHY_AGC_CONTROL) |
- AR_PHY_AGC_CONTROL_NF);
-
- ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr =
- NULL;
-
- if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) {
- if (ath9k_hw_iscal_supported(ah, chan, ADC_GAIN_CAL)) {
- INIT_CAL(&ahp->ah_adcGainCalData);
- INSERT_CAL(ahp, &ahp->ah_adcGainCalData);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "%s: enabling ADC Gain Calibration.\n",
- __func__);
- }
- if (ath9k_hw_iscal_supported(ah, chan, ADC_DC_CAL)) {
- INIT_CAL(&ahp->ah_adcDcCalData);
- INSERT_CAL(ahp, &ahp->ah_adcDcCalData);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "%s: enabling ADC DC Calibration.\n",
- __func__);
- }
- if (ath9k_hw_iscal_supported(ah, chan, IQ_MISMATCH_CAL)) {
- INIT_CAL(&ahp->ah_iqCalData);
- INSERT_CAL(ahp, &ahp->ah_iqCalData);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "%s: enabling IQ Calibration.\n",
- __func__);
- }
-
- ahp->ah_cal_list_curr = ahp->ah_cal_list;
-
- if (ahp->ah_cal_list_curr)
- ath9k_hw_reset_calibration(ah,
- ahp->ah_cal_list_curr);
- }
-
- ichan->CalValid = 0;
-
- return true;
-}
-
-
-bool ath9k_hw_reset(struct ath_hal *ah,
- struct ath9k_channel *chan,
+bool ath9k_hw_reset(struct ath_hal *ah, struct ath9k_channel *chan,
enum ath9k_ht_macmode macmode,
u8 txchainmask, u8 rxchainmask,
enum ath9k_ht_extprotspacing extprotspacing,
- bool bChannelChange,
- int *status)
+ bool bChannelChange, int *status)
{
u32 saveLedState;
struct ath_hal_5416 *ahp = AH5416(ah);
@@ -5886,8 +2247,8 @@ bool ath9k_hw_reset(struct ath_hal *ah,
if (ath9k_hw_check_chan(ah, chan) == NULL) {
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
- "%s: invalid channel %u/0x%x; no mapping\n",
- __func__, chan->channel, chan->channelFlags);
+ "invalid channel %u/0x%x; no mapping\n",
+ chan->channel, chan->channelFlags);
ecode = -EINVAL;
goto bad;
}
@@ -5907,8 +2268,7 @@ bool ath9k_hw_reset(struct ath_hal *ah,
((chan->channelFlags & CHANNEL_ALL) ==
(ah->ah_curchan->channelFlags & CHANNEL_ALL)) &&
(!AR_SREV_9280(ah) || (!IS_CHAN_A_5MHZ_SPACED(chan) &&
- !IS_CHAN_A_5MHZ_SPACED(ah->
- ah_curchan)))) {
+ !IS_CHAN_A_5MHZ_SPACED(ah->ah_curchan)))) {
if (ath9k_hw_channel_change(ah, chan, macmode)) {
ath9k_hw_loadnf(ah, ah->ah_curchan);
@@ -5930,8 +2290,7 @@ bool ath9k_hw_reset(struct ath_hal *ah,
ath9k_hw_mark_phy_inactive(ah);
if (!ath9k_hw_chip_reset(ah, chan)) {
- DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s: chip reset failed\n",
- __func__);
+ DPRINTF(ah->ah_sc, ATH_DBG_RESET, "chip reset failed\n");
ecode = -EINVAL;
goto bad;
}
@@ -5965,7 +2324,7 @@ bool ath9k_hw_reset(struct ath_hal *ah,
if (!ath9k_hw_eeprom_set_board_values(ah, chan)) {
DPRINTF(ah->ah_sc, ATH_DBG_EEPROM,
- "%s: error setting board options\n", __func__);
+ "error setting board options\n");
ecode = -EIO;
goto bad;
}
@@ -6016,7 +2375,7 @@ bool ath9k_hw_reset(struct ath_hal *ah,
ath9k_hw_init_interrupt_masks(ah, ah->ah_opmode);
ath9k_hw_init_qos(ah);
-#ifdef CONFIG_RFKILL
+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
ath9k_enable_rfkill(ah);
#endif
@@ -6055,15 +2414,13 @@ bool ath9k_hw_reset(struct ath_hal *ah,
mask = REG_READ(ah, AR_CFG);
if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) {
DPRINTF(ah->ah_sc, ATH_DBG_RESET,
- "%s CFG Byte Swap Set 0x%x\n", __func__,
- mask);
+ "CFG Byte Swap Set 0x%x\n", mask);
} else {
mask =
INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB;
REG_WRITE(ah, AR_CFG, mask);
DPRINTF(ah->ah_sc, ATH_DBG_RESET,
- "%s Setting CFG 0x%x\n", __func__,
- REG_READ(ah, AR_CFG));
+ "Setting CFG 0x%x\n", REG_READ(ah, AR_CFG));
}
} else {
#ifdef __BIG_ENDIAN
@@ -6078,693 +2435,402 @@ bad:
return false;
}
-bool ath9k_hw_phy_disable(struct ath_hal *ah)
-{
- return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM);
-}
-
-bool ath9k_hw_disable(struct ath_hal *ah)
-{
- if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
- return false;
-
- return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD);
-}
+/************************/
+/* Key Cache Management */
+/************************/
-bool
-ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan,
- u8 rxchainmask, bool longcal,
- bool *isCalDone)
+bool ath9k_hw_keyreset(struct ath_hal *ah, u16 entry)
{
- struct ath_hal_5416 *ahp = AH5416(ah);
- struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
- struct ath9k_channel *ichan =
- ath9k_regd_check_channel(ah, chan);
-
- *isCalDone = true;
+ u32 keyType;
- if (ichan == NULL) {
- DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
- "%s: invalid channel %u/0x%x; no mapping\n",
- __func__, chan->channel, chan->channelFlags);
+ if (entry >= ah->ah_caps.keycache_size) {
+ DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
+ "entry %u out of range\n", entry);
return false;
}
- if (currCal &&
- (currCal->calState == CAL_RUNNING ||
- currCal->calState == CAL_WAITING)) {
- ath9k_hw_per_calibration(ah, ichan, rxchainmask, currCal,
- isCalDone);
- if (*isCalDone) {
- ahp->ah_cal_list_curr = currCal = currCal->calNext;
-
- if (currCal->calState == CAL_WAITING) {
- *isCalDone = false;
- ath9k_hw_reset_calibration(ah, currCal);
- }
- }
- }
+ keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry));
- if (longcal) {
- ath9k_hw_getnf(ah, ichan);
- ath9k_hw_loadnf(ah, ah->ah_curchan);
- ath9k_hw_start_nfcal(ah);
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
+ REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
- if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) {
+ if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
+ u16 micentry = entry + 64;
+
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
- chan->channelFlags |= CHANNEL_CW_INT;
- ichan->channelFlags &= ~CHANNEL_CW_INT;
- }
}
+ if (ah->ah_curchan == NULL)
+ return true;
+
return true;
}
-static void ath9k_hw_iqcal_collect(struct ath_hal *ah)
+bool ath9k_hw_keysetmac(struct ath_hal *ah, u16 entry, const u8 *mac)
{
- struct ath_hal_5416 *ahp = AH5416(ah);
- int i;
+ u32 macHi, macLo;
- for (i = 0; i < AR5416_MAX_CHAINS; i++) {
- ahp->ah_totalPowerMeasI[i] +=
- REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
- ahp->ah_totalPowerMeasQ[i] +=
- REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
- ahp->ah_totalIqCorrMeas[i] +=
- (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n",
- ahp->ah_CalSamples, i, ahp->ah_totalPowerMeasI[i],
- ahp->ah_totalPowerMeasQ[i],
- ahp->ah_totalIqCorrMeas[i]);
+ if (entry >= ah->ah_caps.keycache_size) {
+ DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
+ "entry %u out of range\n", entry);
+ return false;
}
-}
-static void ath9k_hw_adc_gaincal_collect(struct ath_hal *ah)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- int i;
-
- for (i = 0; i < AR5416_MAX_CHAINS; i++) {
- ahp->ah_totalAdcIOddPhase[i] +=
- REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
- ahp->ah_totalAdcIEvenPhase[i] +=
- REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
- ahp->ah_totalAdcQOddPhase[i] +=
- REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
- ahp->ah_totalAdcQEvenPhase[i] +=
- REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
-
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
- "oddq=0x%08x; evenq=0x%08x;\n",
- ahp->ah_CalSamples, i,
- ahp->ah_totalAdcIOddPhase[i],
- ahp->ah_totalAdcIEvenPhase[i],
- ahp->ah_totalAdcQOddPhase[i],
- ahp->ah_totalAdcQEvenPhase[i]);
+ if (mac != NULL) {
+ macHi = (mac[5] << 8) | mac[4];
+ macLo = (mac[3] << 24) |
+ (mac[2] << 16) |
+ (mac[1] << 8) |
+ mac[0];
+ macLo >>= 1;
+ macLo |= (macHi & 1) << 31;
+ macHi >>= 1;
+ } else {
+ macLo = macHi = 0;
}
-}
-
-static void ath9k_hw_adc_dccal_collect(struct ath_hal *ah)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- int i;
+ REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
+ REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID);
- for (i = 0; i < AR5416_MAX_CHAINS; i++) {
- ahp->ah_totalAdcDcOffsetIOddPhase[i] +=
- (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i));
- ahp->ah_totalAdcDcOffsetIEvenPhase[i] +=
- (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i));
- ahp->ah_totalAdcDcOffsetQOddPhase[i] +=
- (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i));
- ahp->ah_totalAdcDcOffsetQEvenPhase[i] +=
- (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i));
-
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "%d: Chn %d oddi=0x%08x; eveni=0x%08x; "
- "oddq=0x%08x; evenq=0x%08x;\n",
- ahp->ah_CalSamples, i,
- ahp->ah_totalAdcDcOffsetIOddPhase[i],
- ahp->ah_totalAdcDcOffsetIEvenPhase[i],
- ahp->ah_totalAdcDcOffsetQOddPhase[i],
- ahp->ah_totalAdcDcOffsetQEvenPhase[i]);
- }
+ return true;
}
-static void ath9k_hw_iqcalibrate(struct ath_hal *ah, u8 numChains)
+bool ath9k_hw_set_keycache_entry(struct ath_hal *ah, u16 entry,
+ const struct ath9k_keyval *k,
+ const u8 *mac, int xorKey)
{
+ const struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+ u32 key0, key1, key2, key3, key4;
+ u32 keyType;
+ u32 xorMask = xorKey ?
+ (ATH9K_KEY_XOR << 24 | ATH9K_KEY_XOR << 16 | ATH9K_KEY_XOR << 8
+ | ATH9K_KEY_XOR) : 0;
struct ath_hal_5416 *ahp = AH5416(ah);
- u32 powerMeasQ, powerMeasI, iqCorrMeas;
- u32 qCoffDenom, iCoffDenom;
- int32_t qCoff, iCoff;
- int iqCorrNeg, i;
-
- for (i = 0; i < numChains; i++) {
- powerMeasI = ahp->ah_totalPowerMeasI[i];
- powerMeasQ = ahp->ah_totalPowerMeasQ[i];
- iqCorrMeas = ahp->ah_totalIqCorrMeas[i];
-
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Starting IQ Cal and Correction for Chain %d\n",
- i);
-
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Orignal: Chn %diq_corr_meas = 0x%08x\n",
- i, ahp->ah_totalIqCorrMeas[i]);
-
- iqCorrNeg = 0;
+ if (entry >= pCap->keycache_size) {
+ DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
+ "entry %u out of range\n", entry);
+ return false;
+ }
- if (iqCorrMeas > 0x80000000) {
- iqCorrMeas = (0xffffffff - iqCorrMeas) + 1;
- iqCorrNeg = 1;
+ switch (k->kv_type) {
+ case ATH9K_CIPHER_AES_OCB:
+ keyType = AR_KEYTABLE_TYPE_AES;
+ break;
+ case ATH9K_CIPHER_AES_CCM:
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
+ "AES-CCM not supported by mac rev 0x%x\n",
+ ah->ah_macRev);
+ return false;
}
-
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n",
- iqCorrNeg);
-
- iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128;
- qCoffDenom = powerMeasQ / 64;
-
- if (powerMeasQ != 0) {
-
- iCoff = iqCorrMeas / iCoffDenom;
- qCoff = powerMeasI / qCoffDenom - 64;
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Chn %d iCoff = 0x%08x\n", i, iCoff);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Chn %d qCoff = 0x%08x\n", i, qCoff);
-
-
- iCoff = iCoff & 0x3f;
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "New: Chn %d iCoff = 0x%08x\n", i, iCoff);
- if (iqCorrNeg == 0x0)
- iCoff = 0x40 - iCoff;
-
- if (qCoff > 15)
- qCoff = 15;
- else if (qCoff <= -16)
- qCoff = 16;
-
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Chn %d : iCoff = 0x%x qCoff = 0x%x\n",
- i, iCoff, qCoff);
-
- REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
- AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF,
- iCoff);
- REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i),
- AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF,
- qCoff);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "IQ Cal and Correction done for Chain %d\n",
- i);
+ keyType = AR_KEYTABLE_TYPE_CCM;
+ break;
+ case ATH9K_CIPHER_TKIP:
+ keyType = AR_KEYTABLE_TYPE_TKIP;
+ if (ATH9K_IS_MIC_ENABLED(ah)
+ && entry + 64 >= pCap->keycache_size) {
+ DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
+ "entry %u inappropriate for TKIP\n", entry);
+ return false;
}
- }
-
- REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0),
- AR_PHY_TIMING_CTRL4_IQCORR_ENABLE);
-}
-
-static void
-ath9k_hw_adc_gaincal_calibrate(struct ath_hal *ah, u8 numChains)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset,
- qEvenMeasOffset;
- u32 qGainMismatch, iGainMismatch, val, i;
-
- for (i = 0; i < numChains; i++) {
- iOddMeasOffset = ahp->ah_totalAdcIOddPhase[i];
- iEvenMeasOffset = ahp->ah_totalAdcIEvenPhase[i];
- qOddMeasOffset = ahp->ah_totalAdcQOddPhase[i];
- qEvenMeasOffset = ahp->ah_totalAdcQEvenPhase[i];
-
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Starting ADC Gain Cal for Chain %d\n", i);
-
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Chn %d pwr_meas_odd_i = 0x%08x\n", i,
- iOddMeasOffset);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Chn %d pwr_meas_even_i = 0x%08x\n", i,
- iEvenMeasOffset);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Chn %d pwr_meas_odd_q = 0x%08x\n", i,
- qOddMeasOffset);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Chn %d pwr_meas_even_q = 0x%08x\n", i,
- qEvenMeasOffset);
-
- if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) {
- iGainMismatch =
- ((iEvenMeasOffset * 32) /
- iOddMeasOffset) & 0x3f;
- qGainMismatch =
- ((qOddMeasOffset * 32) /
- qEvenMeasOffset) & 0x3f;
-
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Chn %d gain_mismatch_i = 0x%08x\n", i,
- iGainMismatch);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Chn %d gain_mismatch_q = 0x%08x\n", i,
- qGainMismatch);
-
- val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
- val &= 0xfffff000;
- val |= (qGainMismatch) | (iGainMismatch << 6);
- REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
-
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "ADC Gain Cal done for Chain %d\n", i);
+ break;
+ case ATH9K_CIPHER_WEP:
+ if (k->kv_len < LEN_WEP40) {
+ DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
+ "WEP key length %u too small\n", k->kv_len);
+ return false;
}
+ if (k->kv_len <= LEN_WEP40)
+ keyType = AR_KEYTABLE_TYPE_40;
+ else if (k->kv_len <= LEN_WEP104)
+ keyType = AR_KEYTABLE_TYPE_104;
+ else
+ keyType = AR_KEYTABLE_TYPE_128;
+ break;
+ case ATH9K_CIPHER_CLR:
+ keyType = AR_KEYTABLE_TYPE_CLR;
+ break;
+ default:
+ DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
+ "cipher %u not supported\n", k->kv_type);
+ return false;
}
- REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
- REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
- AR_PHY_NEW_ADC_GAIN_CORR_ENABLE);
-}
-
-static void
-ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah, u8 numChains)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- u32 iOddMeasOffset, iEvenMeasOffset, val, i;
- int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch;
- const struct hal_percal_data *calData =
- ahp->ah_cal_list_curr->calData;
- u32 numSamples =
- (1 << (calData->calCountMax + 5)) * calData->calNumSamples;
-
- for (i = 0; i < numChains; i++) {
- iOddMeasOffset = ahp->ah_totalAdcDcOffsetIOddPhase[i];
- iEvenMeasOffset = ahp->ah_totalAdcDcOffsetIEvenPhase[i];
- qOddMeasOffset = ahp->ah_totalAdcDcOffsetQOddPhase[i];
- qEvenMeasOffset = ahp->ah_totalAdcDcOffsetQEvenPhase[i];
-
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Starting ADC DC Offset Cal for Chain %d\n", i);
-
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Chn %d pwr_meas_odd_i = %d\n", i,
- iOddMeasOffset);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Chn %d pwr_meas_even_i = %d\n", i,
- iEvenMeasOffset);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Chn %d pwr_meas_odd_q = %d\n", i,
- qOddMeasOffset);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Chn %d pwr_meas_even_q = %d\n", i,
- qEvenMeasOffset);
-
- iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) /
- numSamples) & 0x1ff;
- qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) /
- numSamples) & 0x1ff;
-
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Chn %d dc_offset_mismatch_i = 0x%08x\n", i,
- iDcMismatch);
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "Chn %d dc_offset_mismatch_q = 0x%08x\n", i,
- qDcMismatch);
-
- val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i));
- val &= 0xc0000fff;
- val |= (qDcMismatch << 12) | (iDcMismatch << 21);
- REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val);
-
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "ADC DC Offset Cal done for Chain %d\n", i);
- }
-
- REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0),
- REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) |
- AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE);
-}
-
-bool ath9k_hw_set_txpowerlimit(struct ath_hal *ah, u32 limit)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- struct ath9k_channel *chan = ah->ah_curchan;
+ key0 = get_unaligned_le32(k->kv_val + 0) ^ xorMask;
+ key1 = (get_unaligned_le16(k->kv_val + 4) ^ xorMask) & 0xffff;
+ key2 = get_unaligned_le32(k->kv_val + 6) ^ xorMask;
+ key3 = (get_unaligned_le16(k->kv_val + 10) ^ xorMask) & 0xffff;
+ key4 = get_unaligned_le32(k->kv_val + 12) ^ xorMask;
+ if (k->kv_len <= LEN_WEP104)
+ key4 &= 0xff;
- ah->ah_powerLimit = min(limit, (u32) MAX_RATE_POWER);
+ if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
+ u16 micentry = entry + 64;
- if (ath9k_hw_set_txpower(ah, &ahp->ah_eeprom, chan,
- ath9k_regd_get_ctl(ah, chan),
- ath9k_regd_get_antenna_allowed(ah,
- chan),
- chan->maxRegTxPower * 2,
- min((u32) MAX_RATE_POWER,
- (u32) ah->ah_powerLimit)) != 0)
- return false;
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
+ REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
+ REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
+ REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
+ REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
+ (void) ath9k_hw_keysetmac(ah, entry, mac);
- return true;
-}
+ if (ahp->ah_miscMode & AR_PCU_MIC_NEW_LOC_ENA) {
+ u32 mic0, mic1, mic2, mic3, mic4;
-void
-ath9k_hw_get_channel_centers(struct ath_hal *ah,
- struct ath9k_channel *chan,
- struct chan_centers *centers)
-{
- int8_t extoff;
- struct ath_hal_5416 *ahp = AH5416(ah);
+ mic0 = get_unaligned_le32(k->kv_mic + 0);
+ mic2 = get_unaligned_le32(k->kv_mic + 4);
+ mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff;
+ mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff;
+ mic4 = get_unaligned_le32(k->kv_txmic + 4);
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
+ REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
+ REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
+ REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
+ REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
+ AR_KEYTABLE_TYPE_CLR);
- if (!IS_CHAN_HT40(chan)) {
- centers->ctl_center = centers->ext_center =
- centers->synth_center = chan->channel;
- return;
- }
+ } else {
+ u32 mic0, mic2;
- if ((chan->chanmode == CHANNEL_A_HT40PLUS) ||
- (chan->chanmode == CHANNEL_G_HT40PLUS)) {
- centers->synth_center =
- chan->channel + HT40_CHANNEL_CENTER_SHIFT;
- extoff = 1;
+ mic0 = get_unaligned_le32(k->kv_mic + 0);
+ mic2 = get_unaligned_le32(k->kv_mic + 4);
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
+ REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
+ AR_KEYTABLE_TYPE_CLR);
+ }
+ REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
} else {
- centers->synth_center =
- chan->channel - HT40_CHANNEL_CENTER_SHIFT;
- extoff = -1;
+ REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
+ REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
+ REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
+ REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
+ REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
+ REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
+
+ (void) ath9k_hw_keysetmac(ah, entry, mac);
}
- centers->ctl_center = centers->synth_center - (extoff *
- HT40_CHANNEL_CENTER_SHIFT);
- centers->ext_center = centers->synth_center + (extoff *
- ((ahp->
- ah_extprotspacing
- ==
- ATH9K_HT_EXTPROTSPACING_20)
- ?
- HT40_CHANNEL_CENTER_SHIFT
- : 15));
+ if (ah->ah_curchan == NULL)
+ return true;
+ return true;
}
-void
-ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan,
- bool *isCalDone)
+bool ath9k_hw_keyisvalid(struct ath_hal *ah, u16 entry)
{
- struct ath_hal_5416 *ahp = AH5416(ah);
- struct ath9k_channel *ichan =
- ath9k_regd_check_channel(ah, chan);
- struct hal_cal_list *currCal = ahp->ah_cal_list_curr;
-
- *isCalDone = true;
-
- if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
- return;
-
- if (currCal == NULL)
- return;
-
- if (ichan == NULL) {
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "%s: invalid channel %u/0x%x; no mapping\n",
- __func__, chan->channel, chan->channelFlags);
- return;
- }
-
-
- if (currCal->calState != CAL_DONE) {
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "%s: Calibration state incorrect, %d\n",
- __func__, currCal->calState);
- return;
+ if (entry < ah->ah_caps.keycache_size) {
+ u32 val = REG_READ(ah, AR_KEYTABLE_MAC1(entry));
+ if (val & AR_KEYTABLE_VALID)
+ return true;
}
-
-
- if (!ath9k_hw_iscal_supported(ah, chan, currCal->calData->calType))
- return;
-
- DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE,
- "%s: Resetting Cal %d state for channel %u/0x%x\n",
- __func__, currCal->calData->calType, chan->channel,
- chan->channelFlags);
-
- ichan->CalValid &= ~currCal->calData->calType;
- currCal->calState = CAL_WAITING;
-
- *isCalDone = false;
+ return false;
}
-void ath9k_hw_getmac(struct ath_hal *ah, u8 *mac)
+/******************************/
+/* Power Management (Chipset) */
+/******************************/
+
+static void ath9k_set_power_sleep(struct ath_hal *ah, int setChip)
{
- struct ath_hal_5416 *ahp = AH5416(ah);
+ REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+ if (setChip) {
+ REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
+ AR_RTC_FORCE_WAKE_EN);
+ if (!AR_SREV_9100(ah))
+ REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF);
- memcpy(mac, ahp->ah_macaddr, ETH_ALEN);
+ REG_CLR_BIT(ah, (u16) (AR_RTC_RESET),
+ AR_RTC_RESET_EN);
+ }
}
-bool ath9k_hw_setmac(struct ath_hal *ah, const u8 *mac)
+static void ath9k_set_power_network_sleep(struct ath_hal *ah, int setChip)
{
- struct ath_hal_5416 *ahp = AH5416(ah);
+ REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
+ if (setChip) {
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
- memcpy(ahp->ah_macaddr, mac, ETH_ALEN);
- return true;
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) {
+ REG_WRITE(ah, AR_RTC_FORCE_WAKE,
+ AR_RTC_FORCE_WAKE_ON_INT);
+ } else {
+ REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE,
+ AR_RTC_FORCE_WAKE_EN);
+ }
+ }
}
-void ath9k_hw_getbssidmask(struct ath_hal *ah, u8 *mask)
+static bool ath9k_hw_set_power_awake(struct ath_hal *ah,
+ int setChip)
{
- struct ath_hal_5416 *ahp = AH5416(ah);
+ u32 val;
+ int i;
- memcpy(mask, ahp->ah_bssidmask, ETH_ALEN);
-}
+ if (setChip) {
+ if ((REG_READ(ah, AR_RTC_STATUS) &
+ AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) {
+ if (ath9k_hw_set_reset_reg(ah,
+ ATH9K_RESET_POWER_ON) != true) {
+ return false;
+ }
+ }
+ if (AR_SREV_9100(ah))
+ REG_SET_BIT(ah, AR_RTC_RESET,
+ AR_RTC_RESET_EN);
-bool
-ath9k_hw_setbssidmask(struct ath_hal *ah, const u8 *mask)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
+ REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
+ AR_RTC_FORCE_WAKE_EN);
+ udelay(50);
- memcpy(ahp->ah_bssidmask, mask, ETH_ALEN);
+ for (i = POWER_UP_TIME / 50; i > 0; i--) {
+ val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
+ if (val == AR_RTC_STATUS_ON)
+ break;
+ udelay(50);
+ REG_SET_BIT(ah, AR_RTC_FORCE_WAKE,
+ AR_RTC_FORCE_WAKE_EN);
+ }
+ if (i == 0) {
+ DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+ "Failed to wakeup in %uus\n", POWER_UP_TIME / 20);
+ return false;
+ }
+ }
- REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(ahp->ah_bssidmask));
- REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(ahp->ah_bssidmask + 4));
+ REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
return true;
}
-void
-ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid,
- u16 assocId)
+bool ath9k_hw_setpower(struct ath_hal *ah,
+ enum ath9k_power_mode mode)
{
struct ath_hal_5416 *ahp = AH5416(ah);
+ static const char *modes[] = {
+ "AWAKE",
+ "FULL-SLEEP",
+ "NETWORK SLEEP",
+ "UNDEFINED"
+ };
+ int status = true, setChip = true;
- memcpy(ahp->ah_bssid, bssid, ETH_ALEN);
- ahp->ah_assocId = assocId;
-
- REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(ahp->ah_bssid));
- REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(ahp->ah_bssid + 4) |
- ((assocId & 0x3fff) << AR_BSS_ID1_AID_S));
-}
-
-u64 ath9k_hw_gettsf64(struct ath_hal *ah)
-{
- u64 tsf;
-
- tsf = REG_READ(ah, AR_TSF_U32);
- tsf = (tsf << 32) | REG_READ(ah, AR_TSF_L32);
- return tsf;
-}
-
-void ath9k_hw_reset_tsf(struct ath_hal *ah)
-{
- int count;
+ DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT, "%s -> %s (%s)\n",
+ modes[ahp->ah_powerMode], modes[mode],
+ setChip ? "set chip " : "");
- count = 0;
- while (REG_READ(ah, AR_SLP32_MODE) & AR_SLP32_TSF_WRITE_STATUS) {
- count++;
- if (count > 10) {
- DPRINTF(ah->ah_sc, ATH_DBG_RESET,
- "%s: AR_SLP32_TSF_WRITE_STATUS limit exceeded\n",
- __func__);
- break;
- }
- udelay(10);
+ switch (mode) {
+ case ATH9K_PM_AWAKE:
+ status = ath9k_hw_set_power_awake(ah, setChip);
+ break;
+ case ATH9K_PM_FULL_SLEEP:
+ ath9k_set_power_sleep(ah, setChip);
+ ahp->ah_chipFullSleep = true;
+ break;
+ case ATH9K_PM_NETWORK_SLEEP:
+ ath9k_set_power_network_sleep(ah, setChip);
+ break;
+ default:
+ DPRINTF(ah->ah_sc, ATH_DBG_POWER_MGMT,
+ "Unknown power mode %u\n", mode);
+ return false;
}
- REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
-}
-
-u32 ath9k_hw_getdefantenna(struct ath_hal *ah)
-{
- return REG_READ(ah, AR_DEF_ANTENNA) & 0x7;
-}
+ ahp->ah_powerMode = mode;
-void ath9k_hw_setantenna(struct ath_hal *ah, u32 antenna)
-{
- REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
+ return status;
}
-bool
-ath9k_hw_setantennaswitch(struct ath_hal *ah,
- enum ath9k_ant_setting settings,
- struct ath9k_channel *chan,
- u8 *tx_chainmask,
- u8 *rx_chainmask,
- u8 *antenna_cfgd)
+void ath9k_hw_configpcipowersave(struct ath_hal *ah, int restore)
{
struct ath_hal_5416 *ahp = AH5416(ah);
- static u8 tx_chainmask_cfg, rx_chainmask_cfg;
+ u8 i;
- if (AR_SREV_9280(ah)) {
- if (!tx_chainmask_cfg) {
+ if (ah->ah_isPciExpress != true)
+ return;
- tx_chainmask_cfg = *tx_chainmask;
- rx_chainmask_cfg = *rx_chainmask;
- }
+ if (ah->ah_config.pcie_powersave_enable == 2)
+ return;
- switch (settings) {
- case ATH9K_ANT_FIXED_A:
- *tx_chainmask = ATH9K_ANTENNA0_CHAINMASK;
- *rx_chainmask = ATH9K_ANTENNA0_CHAINMASK;
- *antenna_cfgd = true;
- break;
- case ATH9K_ANT_FIXED_B:
- if (ah->ah_caps.tx_chainmask >
- ATH9K_ANTENNA1_CHAINMASK) {
- *tx_chainmask = ATH9K_ANTENNA1_CHAINMASK;
- }
- *rx_chainmask = ATH9K_ANTENNA1_CHAINMASK;
- *antenna_cfgd = true;
- break;
- case ATH9K_ANT_VARIABLE:
- *tx_chainmask = tx_chainmask_cfg;
- *rx_chainmask = rx_chainmask_cfg;
- *antenna_cfgd = true;
- break;
- default:
- break;
+ if (restore)
+ return;
+
+ if (AR_SREV_9280_20_OR_LATER(ah)) {
+ for (i = 0; i < ahp->ah_iniPcieSerdes.ia_rows; i++) {
+ REG_WRITE(ah, INI_RA(&ahp->ah_iniPcieSerdes, i, 0),
+ INI_RA(&ahp->ah_iniPcieSerdes, i, 1));
}
- } else {
- ahp->ah_diversityControl = settings;
- }
+ udelay(1000);
+ } else if (AR_SREV_9280(ah) &&
+ (ah->ah_macRev == AR_SREV_REVISION_9280_10)) {
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
- return true;
-}
+ REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560);
-void ath9k_hw_setopmode(struct ath_hal *ah)
-{
- ath9k_hw_set_operating_mode(ah, ah->ah_opmode);
-}
+ if (ah->ah_config.pcie_clock_req)
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc);
+ else
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd);
-bool
-ath9k_hw_getcapability(struct ath_hal *ah, enum ath9k_capability_type type,
- u32 capability, u32 *result)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- const struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007);
- switch (type) {
- case ATH9K_CAP_CIPHER:
- switch (capability) {
- case ATH9K_CIPHER_AES_CCM:
- case ATH9K_CIPHER_AES_OCB:
- case ATH9K_CIPHER_TKIP:
- case ATH9K_CIPHER_WEP:
- case ATH9K_CIPHER_MIC:
- case ATH9K_CIPHER_CLR:
- return true;
- default:
- return false;
- }
- case ATH9K_CAP_TKIP_MIC:
- switch (capability) {
- case 0:
- return true;
- case 1:
- return (ahp->ah_staId1Defaults &
- AR_STA_ID1_CRPT_MIC_ENABLE) ? true :
- false;
- }
- case ATH9K_CAP_TKIP_SPLIT:
- return (ahp->ah_miscMode & AR_PCU_MIC_NEW_LOC_ENA) ?
- false : true;
- case ATH9K_CAP_WME_TKIPMIC:
- return 0;
- case ATH9K_CAP_PHYCOUNTERS:
- return ahp->ah_hasHwPhyCounters ? 0 : -ENXIO;
- case ATH9K_CAP_DIVERSITY:
- return (REG_READ(ah, AR_PHY_CCK_DETECT) &
- AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ?
- true : false;
- case ATH9K_CAP_PHYDIAG:
- return true;
- case ATH9K_CAP_MCAST_KEYSRCH:
- switch (capability) {
- case 0:
- return true;
- case 1:
- if (REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_ADHOC) {
- return false;
- } else {
- return (ahp->ah_staId1Defaults &
- AR_STA_ID1_MCAST_KSRCH) ? true :
- false;
- }
- }
- return false;
- case ATH9K_CAP_TSF_ADJUST:
- return (ahp->ah_miscMode & AR_PCU_TX_ADD_TSF) ?
- true : false;
- case ATH9K_CAP_RFSILENT:
- if (capability == 3)
- return false;
- case ATH9K_CAP_ANT_CFG_2GHZ:
- *result = pCap->num_antcfg_2ghz;
- return true;
- case ATH9K_CAP_ANT_CFG_5GHZ:
- *result = pCap->num_antcfg_5ghz;
- return true;
- case ATH9K_CAP_TXPOW:
- switch (capability) {
- case 0:
- return 0;
- case 1:
- *result = ah->ah_powerLimit;
- return 0;
- case 2:
- *result = ah->ah_maxPowerLevel;
- return 0;
- case 3:
- *result = ah->ah_tpScale;
- return 0;
- }
- return false;
- default:
- return false;
- }
-}
+ REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
-int
-ath9k_hw_select_antconfig(struct ath_hal *ah, u32 cfg)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- struct ath9k_channel *chan = ah->ah_curchan;
- const struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
- u16 ant_config;
- u32 halNumAntConfig;
+ udelay(1000);
+ } else {
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554);
+ REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007);
+ REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
+ }
- halNumAntConfig =
- IS_CHAN_2GHZ(chan) ? pCap->num_antcfg_2ghz : pCap->
- num_antcfg_5ghz;
+ REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
- if (cfg < halNumAntConfig) {
- if (!ath9k_hw_get_eeprom_antenna_cfg(ahp, chan,
- cfg, &ant_config)) {
- REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
- return 0;
- }
+ if (ah->ah_config.pcie_waen) {
+ REG_WRITE(ah, AR_WA, ah->ah_config.pcie_waen);
+ } else {
+ if (AR_SREV_9285(ah))
+ REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT);
+ else if (AR_SREV_9280(ah))
+ REG_WRITE(ah, AR_WA, AR9280_WA_DEFAULT);
+ else
+ REG_WRITE(ah, AR_WA, AR_WA_DEFAULT);
}
- return -EINVAL;
}
+/**********************/
+/* Interrupt Handling */
+/**********************/
+
bool ath9k_hw_intrpend(struct ath_hal *ah)
{
u32 host_isr;
@@ -6791,6 +2857,7 @@ bool ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked)
struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
u32 sync_cause = 0;
bool fatal_int = false;
+ struct ath_hal_5416 *ahp = AH5416(ah);
if (!AR_SREV_9100(ah)) {
if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) {
@@ -6800,9 +2867,8 @@ bool ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked)
}
}
- sync_cause =
- REG_READ(ah,
- AR_INTR_SYNC_CAUSE) & AR_INTR_SYNC_DEFAULT;
+ sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) &
+ AR_INTR_SYNC_DEFAULT;
*masked = 0;
@@ -6814,8 +2880,6 @@ bool ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked)
}
if (isr) {
- struct ath_hal_5416 *ahp = AH5416(ah);
-
if (isr & AR_ISR_BCNMISC) {
u32 isr2;
isr2 = REG_READ(ah, AR_ISR_S2);
@@ -6842,7 +2906,6 @@ bool ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked)
*masked = isr & ATH9K_INT_COMMON;
if (ahp->ah_intrMitigation) {
-
if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM))
*masked |= ATH9K_INT_RX;
}
@@ -6867,8 +2930,7 @@ bool ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked)
if (isr & AR_ISR_RXORN) {
DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
- "%s: receive FIFO overrun interrupt\n",
- __func__);
+ "receive FIFO overrun interrupt\n");
}
if (!AR_SREV_9100(ah)) {
@@ -6881,8 +2943,10 @@ bool ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked)
*masked |= mask2;
}
+
if (AR_SREV_9100(ah))
return true;
+
if (sync_cause) {
fatal_int =
(sync_cause &
@@ -6892,32 +2956,29 @@ bool ath9k_hw_getisr(struct ath_hal *ah, enum ath9k_int *masked)
if (fatal_int) {
if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) {
DPRINTF(ah->ah_sc, ATH_DBG_ANY,
- "%s: received PCI FATAL interrupt\n",
- __func__);
+ "received PCI FATAL interrupt\n");
}
if (sync_cause & AR_INTR_SYNC_HOST1_PERR) {
DPRINTF(ah->ah_sc, ATH_DBG_ANY,
- "%s: received PCI PERR interrupt\n",
- __func__);
+ "received PCI PERR interrupt\n");
}
}
if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) {
DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
- "%s: AR_INTR_SYNC_RADM_CPL_TIMEOUT\n",
- __func__);
+ "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n");
REG_WRITE(ah, AR_RC, AR_RC_HOSTIF);
REG_WRITE(ah, AR_RC, 0);
*masked |= ATH9K_INT_FATAL;
}
if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) {
DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
- "%s: AR_INTR_SYNC_LOCAL_TIMEOUT\n",
- __func__);
+ "AR_INTR_SYNC_LOCAL_TIMEOUT\n");
}
REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause);
(void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR);
}
+
return true;
}
@@ -6933,12 +2994,10 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah, enum ath9k_int ints)
u32 mask, mask2;
struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
- DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "%s: 0x%x => 0x%x\n", __func__,
- omask, ints);
+ DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
if (omask & ATH9K_INT_GLOBAL) {
- DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "%s: disable IER\n",
- __func__);
+ DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "disable IER\n");
REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
(void) REG_READ(ah, AR_IER);
if (!AR_SREV_9100(ah)) {
@@ -6993,8 +3052,7 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah, enum ath9k_int ints)
mask2 |= AR_IMR_S2_CST;
}
- DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "%s: new IMR 0x%x\n", __func__,
- mask);
+ DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask);
REG_WRITE(ah, AR_IMR, mask);
mask = REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM |
AR_IMR_S2_DTIM |
@@ -7014,8 +3072,7 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah, enum ath9k_int ints)
}
if (ints & ATH9K_INT_GLOBAL) {
- DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "%s: enable IER\n",
- __func__);
+ DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "enable IER\n");
REG_WRITE(ah, AR_IER, AR_IER_ENABLE);
if (!AR_SREV_9100(ah)) {
REG_WRITE(ah, AR_INTR_ASYNC_ENABLE,
@@ -7035,9 +3092,11 @@ enum ath9k_int ath9k_hw_set_interrupts(struct ath_hal *ah, enum ath9k_int ints)
return omask;
}
-void
-ath9k_hw_beaconinit(struct ath_hal *ah,
- u32 next_beacon, u32 beacon_period)
+/*******************/
+/* Beacon Handling */
+/*******************/
+
+void ath9k_hw_beaconinit(struct ath_hal *ah, u32 next_beacon, u32 beacon_period)
{
struct ath_hal_5416 *ahp = AH5416(ah);
int flags = 0;
@@ -7045,14 +3104,14 @@ ath9k_hw_beaconinit(struct ath_hal *ah,
ahp->ah_beaconInterval = beacon_period;
switch (ah->ah_opmode) {
- case ATH9K_M_STA:
- case ATH9K_M_MONITOR:
+ case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_MONITOR:
REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon));
REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff);
REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff);
flags |= AR_TBTT_TIMER_EN;
break;
- case ATH9K_M_IBSS:
+ case NL80211_IFTYPE_ADHOC:
REG_SET_BIT(ah, AR_TXCFG,
AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
REG_WRITE(ah, AR_NEXT_NDP_TIMER,
@@ -7060,7 +3119,7 @@ ath9k_hw_beaconinit(struct ath_hal *ah,
(ahp->ah_atimWindow ? ahp->
ah_atimWindow : 1)));
flags |= AR_NDP_TIMER_EN;
- case ATH9K_M_HOSTAP:
+ case NL80211_IFTYPE_AP:
REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon));
REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT,
TU_TO_USEC(next_beacon -
@@ -7073,6 +3132,12 @@ ath9k_hw_beaconinit(struct ath_hal *ah,
flags |=
AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN;
break;
+ default:
+ DPRINTF(ah->ah_sc, ATH_DBG_BEACON,
+ "%s: unsupported opmode: %d\n",
+ __func__, ah->ah_opmode);
+ return;
+ break;
}
REG_WRITE(ah, AR_BEACON_PERIOD, TU_TO_USEC(beacon_period));
@@ -7089,9 +3154,8 @@ ath9k_hw_beaconinit(struct ath_hal *ah,
REG_SET_BIT(ah, AR_TIMER_MODE, flags);
}
-void
-ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah,
- const struct ath9k_beacon_state *bs)
+void ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah,
+ const struct ath9k_beacon_state *bs)
{
u32 nextTbtt, beaconintval, dtimperiod, beacontimeout;
struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
@@ -7120,14 +3184,10 @@ ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah,
else
nextTbtt = bs->bs_nexttbtt;
- DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "%s: next DTIM %d\n", __func__,
- bs->bs_nextdtim);
- DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "%s: next beacon %d\n", __func__,
- nextTbtt);
- DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "%s: beacon period %d\n", __func__,
- beaconintval);
- DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "%s: DTIM period %d\n", __func__,
- dtimperiod);
+ DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "next DTIM %d\n", bs->bs_nextdtim);
+ DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "next beacon %d\n", nextTbtt);
+ DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "beacon period %d\n", beaconintval);
+ DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod);
REG_WRITE(ah, AR_NEXT_DTIM,
TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP));
@@ -7154,1424 +3214,682 @@ ath9k_hw_set_sta_beacon_timers(struct ath_hal *ah,
}
-bool ath9k_hw_keyisvalid(struct ath_hal *ah, u16 entry)
-{
- if (entry < ah->ah_caps.keycache_size) {
- u32 val = REG_READ(ah, AR_KEYTABLE_MAC1(entry));
- if (val & AR_KEYTABLE_VALID)
- return true;
- }
- return false;
-}
+/*******************/
+/* HW Capabilities */
+/*******************/
-bool ath9k_hw_keyreset(struct ath_hal *ah, u16 entry)
+bool ath9k_hw_fill_cap_info(struct ath_hal *ah)
{
- u32 keyType;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+ u16 capField = 0, eeval;
- if (entry >= ah->ah_caps.keycache_size) {
- DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
- "%s: entry %u out of range\n", __func__, entry);
- return false;
- }
- keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry));
+ eeval = ath9k_hw_get_eeprom(ah, EEP_REG_0);
- REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0);
- REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0);
- REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0);
- REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0);
- REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0);
- REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR);
- REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0);
- REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0);
+ ah->ah_currentRD = eeval;
- if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
- u16 micentry = entry + 64;
+ eeval = ath9k_hw_get_eeprom(ah, EEP_REG_1);
+ ah->ah_currentRDExt = eeval;
- REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0);
- REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
- REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0);
- REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
+ capField = ath9k_hw_get_eeprom(ah, EEP_OP_CAP);
+ if (ah->ah_opmode != NL80211_IFTYPE_AP &&
+ ah->ah_subvendorid == AR_SUBVENDOR_ID_NEW_A) {
+ if (ah->ah_currentRD == 0x64 || ah->ah_currentRD == 0x65)
+ ah->ah_currentRD += 5;
+ else if (ah->ah_currentRD == 0x41)
+ ah->ah_currentRD = 0x43;
+ DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
+ "regdomain mapped to 0x%x\n", ah->ah_currentRD);
}
- if (ah->ah_curchan == NULL)
- return true;
-
- return true;
-}
-
-bool
-ath9k_hw_keysetmac(struct ath_hal *ah, u16 entry,
- const u8 *mac)
-{
- u32 macHi, macLo;
-
- if (entry >= ah->ah_caps.keycache_size) {
- DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
- "%s: entry %u out of range\n", __func__, entry);
- return false;
- }
+ eeval = ath9k_hw_get_eeprom(ah, EEP_OP_MODE);
+ bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX);
- if (mac != NULL) {
- macHi = (mac[5] << 8) | mac[4];
- macLo = (mac[3] << 24) | (mac[2] << 16)
- | (mac[1] << 8) | mac[0];
- macLo >>= 1;
- macLo |= (macHi & 1) << 31;
- macHi >>= 1;
- } else {
- macLo = macHi = 0;
+ if (eeval & AR5416_OPFLAGS_11A) {
+ set_bit(ATH9K_MODE_11A, pCap->wireless_modes);
+ if (ah->ah_config.ht_enable) {
+ if (!(eeval & AR5416_OPFLAGS_N_5G_HT20))
+ set_bit(ATH9K_MODE_11NA_HT20,
+ pCap->wireless_modes);
+ if (!(eeval & AR5416_OPFLAGS_N_5G_HT40)) {
+ set_bit(ATH9K_MODE_11NA_HT40PLUS,
+ pCap->wireless_modes);
+ set_bit(ATH9K_MODE_11NA_HT40MINUS,
+ pCap->wireless_modes);
+ }
+ }
}
- REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo);
- REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID);
- return true;
-}
-
-bool
-ath9k_hw_set_keycache_entry(struct ath_hal *ah, u16 entry,
- const struct ath9k_keyval *k,
- const u8 *mac, int xorKey)
-{
- const struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
- u32 key0, key1, key2, key3, key4;
- u32 keyType;
- u32 xorMask = xorKey ?
- (ATH9K_KEY_XOR << 24 | ATH9K_KEY_XOR << 16 | ATH9K_KEY_XOR << 8
- | ATH9K_KEY_XOR) : 0;
- struct ath_hal_5416 *ahp = AH5416(ah);
-
- if (entry >= pCap->keycache_size) {
- DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
- "%s: entry %u out of range\n", __func__, entry);
- return false;
- }
- switch (k->kv_type) {
- case ATH9K_CIPHER_AES_OCB:
- keyType = AR_KEYTABLE_TYPE_AES;
- break;
- case ATH9K_CIPHER_AES_CCM:
- if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) {
- DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
- "%s: AES-CCM not supported by "
- "mac rev 0x%x\n", __func__,
- ah->ah_macRev);
- return false;
- }
- keyType = AR_KEYTABLE_TYPE_CCM;
- break;
- case ATH9K_CIPHER_TKIP:
- keyType = AR_KEYTABLE_TYPE_TKIP;
- if (ATH9K_IS_MIC_ENABLED(ah)
- && entry + 64 >= pCap->keycache_size) {
- DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
- "%s: entry %u inappropriate for TKIP\n",
- __func__, entry);
- return false;
- }
- break;
- case ATH9K_CIPHER_WEP:
- if (k->kv_len < LEN_WEP40) {
- DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
- "%s: WEP key length %u too small\n",
- __func__, k->kv_len);
- return false;
+ if (eeval & AR5416_OPFLAGS_11G) {
+ set_bit(ATH9K_MODE_11B, pCap->wireless_modes);
+ set_bit(ATH9K_MODE_11G, pCap->wireless_modes);
+ if (ah->ah_config.ht_enable) {
+ if (!(eeval & AR5416_OPFLAGS_N_2G_HT20))
+ set_bit(ATH9K_MODE_11NG_HT20,
+ pCap->wireless_modes);
+ if (!(eeval & AR5416_OPFLAGS_N_2G_HT40)) {
+ set_bit(ATH9K_MODE_11NG_HT40PLUS,
+ pCap->wireless_modes);
+ set_bit(ATH9K_MODE_11NG_HT40MINUS,
+ pCap->wireless_modes);
+ }
}
- if (k->kv_len <= LEN_WEP40)
- keyType = AR_KEYTABLE_TYPE_40;
- else if (k->kv_len <= LEN_WEP104)
- keyType = AR_KEYTABLE_TYPE_104;
- else
- keyType = AR_KEYTABLE_TYPE_128;
- break;
- case ATH9K_CIPHER_CLR:
- keyType = AR_KEYTABLE_TYPE_CLR;
- break;
- default:
- DPRINTF(ah->ah_sc, ATH_DBG_KEYCACHE,
- "%s: cipher %u not supported\n", __func__,
- k->kv_type);
- return false;
}
- key0 = get_unaligned_le32(k->kv_val + 0) ^ xorMask;
- key1 = (get_unaligned_le16(k->kv_val + 4) ^ xorMask) & 0xffff;
- key2 = get_unaligned_le32(k->kv_val + 6) ^ xorMask;
- key3 = (get_unaligned_le16(k->kv_val + 10) ^ xorMask) & 0xffff;
- key4 = get_unaligned_le32(k->kv_val + 12) ^ xorMask;
- if (k->kv_len <= LEN_WEP104)
- key4 &= 0xff;
-
- if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) {
- u16 micentry = entry + 64;
-
- REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0);
- REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1);
- REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
- REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
- REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
- REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
- (void) ath9k_hw_keysetmac(ah, entry, mac);
-
- if (ahp->ah_miscMode & AR_PCU_MIC_NEW_LOC_ENA) {
- u32 mic0, mic1, mic2, mic3, mic4;
-
- mic0 = get_unaligned_le32(k->kv_mic + 0);
- mic2 = get_unaligned_le32(k->kv_mic + 4);
- mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff;
- mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff;
- mic4 = get_unaligned_le32(k->kv_txmic + 4);
- REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
- REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1);
- REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
- REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3);
- REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4);
- REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
- AR_KEYTABLE_TYPE_CLR);
-
- } else {
- u32 mic0, mic2;
-
- mic0 = get_unaligned_le32(k->kv_mic + 0);
- mic2 = get_unaligned_le32(k->kv_mic + 4);
- REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0);
- REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0);
- REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2);
- REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0);
- REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
- REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
- AR_KEYTABLE_TYPE_CLR);
- }
- REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0);
- REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0);
- REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
- REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
+ pCap->tx_chainmask = ath9k_hw_get_eeprom(ah, EEP_TX_MASK);
+ if ((ah->ah_isPciExpress)
+ || (eeval & AR5416_OPFLAGS_11A)) {
+ pCap->rx_chainmask =
+ ath9k_hw_get_eeprom(ah, EEP_RX_MASK);
} else {
- REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0);
- REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1);
- REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2);
- REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3);
- REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4);
- REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType);
-
- (void) ath9k_hw_keysetmac(ah, entry, mac);
+ pCap->rx_chainmask =
+ (ath9k_hw_gpio_get(ah, 0)) ? 0x5 : 0x7;
}
- if (ah->ah_curchan == NULL)
- return true;
-
- return true;
-}
-
-bool
-ath9k_hw_updatetxtriglevel(struct ath_hal *ah, bool bIncTrigLevel)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- u32 txcfg, curLevel, newLevel;
- enum ath9k_int omask;
-
- if (ah->ah_txTrigLevel >= MAX_TX_FIFO_THRESHOLD)
- return false;
-
- omask = ath9k_hw_set_interrupts(ah,
- ahp->ah_maskReg & ~ATH9K_INT_GLOBAL);
-
- txcfg = REG_READ(ah, AR_TXCFG);
- curLevel = MS(txcfg, AR_FTRIG);
- newLevel = curLevel;
- if (bIncTrigLevel) {
- if (curLevel < MAX_TX_FIFO_THRESHOLD)
- newLevel++;
- } else if (curLevel > MIN_TX_FIFO_THRESHOLD)
- newLevel--;
- if (newLevel != curLevel)
- REG_WRITE(ah, AR_TXCFG,
- (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
+ if (!(AR_SREV_9280(ah) && (ah->ah_macRev == 0)))
+ ahp->ah_miscMode |= AR_PCU_MIC_NEW_LOC_ENA;
- ath9k_hw_set_interrupts(ah, omask);
+ pCap->low_2ghz_chan = 2312;
+ pCap->high_2ghz_chan = 2732;
- ah->ah_txTrigLevel = newLevel;
+ pCap->low_5ghz_chan = 4920;
+ pCap->high_5ghz_chan = 6100;
- return newLevel != curLevel;
-}
+ pCap->hw_caps &= ~ATH9K_HW_CAP_CIPHER_CKIP;
+ pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_TKIP;
+ pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_AESCCM;
-bool ath9k_hw_set_txq_props(struct ath_hal *ah, int q,
- const struct ath9k_tx_queue_info *qinfo)
-{
- u32 cw;
- struct ath_hal_5416 *ahp = AH5416(ah);
- struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
- struct ath9k_tx_queue_info *qi;
+ pCap->hw_caps &= ~ATH9K_HW_CAP_MIC_CKIP;
+ pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP;
+ pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM;
- if (q >= pCap->total_queues) {
- DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n",
- __func__, q);
- return false;
- }
+ pCap->hw_caps |= ATH9K_HW_CAP_CHAN_SPREAD;
- qi = &ahp->ah_txq[q];
- if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
- DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue\n",
- __func__);
- return false;
- }
+ if (ah->ah_config.ht_enable)
+ pCap->hw_caps |= ATH9K_HW_CAP_HT;
+ else
+ pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
- DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: queue %p\n", __func__, qi);
+ pCap->hw_caps |= ATH9K_HW_CAP_GTT;
+ pCap->hw_caps |= ATH9K_HW_CAP_VEOL;
+ pCap->hw_caps |= ATH9K_HW_CAP_BSSIDMASK;
+ pCap->hw_caps &= ~ATH9K_HW_CAP_MCAST_KEYSEARCH;
- qi->tqi_ver = qinfo->tqi_ver;
- qi->tqi_subtype = qinfo->tqi_subtype;
- qi->tqi_qflags = qinfo->tqi_qflags;
- qi->tqi_priority = qinfo->tqi_priority;
- if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT)
- qi->tqi_aifs = min(qinfo->tqi_aifs, 255U);
+ if (capField & AR_EEPROM_EEPCAP_MAXQCU)
+ pCap->total_queues =
+ MS(capField, AR_EEPROM_EEPCAP_MAXQCU);
else
- qi->tqi_aifs = INIT_AIFS;
- if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) {
- cw = min(qinfo->tqi_cwmin, 1024U);
- qi->tqi_cwmin = 1;
- while (qi->tqi_cwmin < cw)
- qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
- } else
- qi->tqi_cwmin = qinfo->tqi_cwmin;
- if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) {
- cw = min(qinfo->tqi_cwmax, 1024U);
- qi->tqi_cwmax = 1;
- while (qi->tqi_cwmax < cw)
- qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
- } else
- qi->tqi_cwmax = INIT_CWMAX;
+ pCap->total_queues = ATH9K_NUM_TX_QUEUES;
- if (qinfo->tqi_shretry != 0)
- qi->tqi_shretry = min((u32) qinfo->tqi_shretry, 15U);
- else
- qi->tqi_shretry = INIT_SH_RETRY;
- if (qinfo->tqi_lgretry != 0)
- qi->tqi_lgretry = min((u32) qinfo->tqi_lgretry, 15U);
+ if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES)
+ pCap->keycache_size =
+ 1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES);
else
- qi->tqi_lgretry = INIT_LG_RETRY;
- qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod;
- qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit;
- qi->tqi_burstTime = qinfo->tqi_burstTime;
- qi->tqi_readyTime = qinfo->tqi_readyTime;
-
- switch (qinfo->tqi_subtype) {
- case ATH9K_WME_UPSD:
- if (qi->tqi_type == ATH9K_TX_QUEUE_DATA)
- qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS;
- break;
- default:
- break;
- }
- return true;
-}
+ pCap->keycache_size = AR_KEYTABLE_SIZE;
-bool ath9k_hw_get_txq_props(struct ath_hal *ah, int q,
- struct ath9k_tx_queue_info *qinfo)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
- struct ath9k_tx_queue_info *qi;
+ pCap->hw_caps |= ATH9K_HW_CAP_FASTCC;
+ pCap->num_mr_retries = 4;
+ pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD;
- if (q >= pCap->total_queues) {
- DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n",
- __func__, q);
- return false;
- }
+ if (AR_SREV_9280_10_OR_LATER(ah))
+ pCap->num_gpio_pins = AR928X_NUM_GPIO;
+ else
+ pCap->num_gpio_pins = AR_NUM_GPIO;
- qi = &ahp->ah_txq[q];
- if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
- DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue\n",
- __func__);
- return false;
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ pCap->hw_caps |= ATH9K_HW_CAP_WOW;
+ pCap->hw_caps |= ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT;
+ } else {
+ pCap->hw_caps &= ~ATH9K_HW_CAP_WOW;
+ pCap->hw_caps &= ~ATH9K_HW_CAP_WOW_MATCHPATTERN_EXACT;
}
- qinfo->tqi_qflags = qi->tqi_qflags;
- qinfo->tqi_ver = qi->tqi_ver;
- qinfo->tqi_subtype = qi->tqi_subtype;
- qinfo->tqi_qflags = qi->tqi_qflags;
- qinfo->tqi_priority = qi->tqi_priority;
- qinfo->tqi_aifs = qi->tqi_aifs;
- qinfo->tqi_cwmin = qi->tqi_cwmin;
- qinfo->tqi_cwmax = qi->tqi_cwmax;
- qinfo->tqi_shretry = qi->tqi_shretry;
- qinfo->tqi_lgretry = qi->tqi_lgretry;
- qinfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
- qinfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
- qinfo->tqi_burstTime = qi->tqi_burstTime;
- qinfo->tqi_readyTime = qi->tqi_readyTime;
+ if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) {
+ pCap->hw_caps |= ATH9K_HW_CAP_CST;
+ pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX;
+ } else {
+ pCap->rts_aggr_limit = (8 * 1024);
+ }
- return true;
-}
+ pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM;
-int
-ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type,
- const struct ath9k_tx_queue_info *qinfo)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- struct ath9k_tx_queue_info *qi;
- struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
- int q;
+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
+ ah->ah_rfsilent = ath9k_hw_get_eeprom(ah, EEP_RF_SILENT);
+ if (ah->ah_rfsilent & EEP_RFSILENT_ENABLED) {
+ ah->ah_rfkill_gpio =
+ MS(ah->ah_rfsilent, EEP_RFSILENT_GPIO_SEL);
+ ah->ah_rfkill_polarity =
+ MS(ah->ah_rfsilent, EEP_RFSILENT_POLARITY);
- switch (type) {
- case ATH9K_TX_QUEUE_BEACON:
- q = pCap->total_queues - 1;
- break;
- case ATH9K_TX_QUEUE_CAB:
- q = pCap->total_queues - 2;
- break;
- case ATH9K_TX_QUEUE_PSPOLL:
- q = 1;
- break;
- case ATH9K_TX_QUEUE_UAPSD:
- q = pCap->total_queues - 3;
- break;
- case ATH9K_TX_QUEUE_DATA:
- for (q = 0; q < pCap->total_queues; q++)
- if (ahp->ah_txq[q].tqi_type ==
- ATH9K_TX_QUEUE_INACTIVE)
- break;
- if (q == pCap->total_queues) {
- DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
- "%s: no available tx queue\n", __func__);
- return -1;
- }
- break;
- default:
- DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: bad tx queue type %u\n",
- __func__, type);
- return -1;
+ pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT;
}
+#endif
+
+ if ((ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) ||
+ (ah->ah_macVersion == AR_SREV_VERSION_5416_PCIE) ||
+ (ah->ah_macVersion == AR_SREV_VERSION_9160) ||
+ (ah->ah_macVersion == AR_SREV_VERSION_9100) ||
+ (ah->ah_macVersion == AR_SREV_VERSION_9280))
+ pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP;
+ else
+ pCap->hw_caps |= ATH9K_HW_CAP_AUTOSLEEP;
- DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: queue %u\n", __func__, q);
+ if (AR_SREV_9280(ah) || AR_SREV_9285(ah))
+ pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS;
+ else
+ pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS;
- qi = &ahp->ah_txq[q];
- if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
- DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
- "%s: tx queue %u already active\n", __func__, q);
- return -1;
- }
- memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
- qi->tqi_type = type;
- if (qinfo == NULL) {
- qi->tqi_qflags =
- TXQ_FLAG_TXOKINT_ENABLE
- | TXQ_FLAG_TXERRINT_ENABLE
- | TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE;
- qi->tqi_aifs = INIT_AIFS;
- qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
- qi->tqi_cwmax = INIT_CWMAX;
- qi->tqi_shretry = INIT_SH_RETRY;
- qi->tqi_lgretry = INIT_LG_RETRY;
- qi->tqi_physCompBuf = 0;
+ if (ah->ah_currentRDExt & (1 << REG_EXT_JAPAN_MIDBAND)) {
+ pCap->reg_cap =
+ AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
+ AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN |
+ AR_EEPROM_EEREGCAP_EN_KK_U2 |
+ AR_EEPROM_EEREGCAP_EN_KK_MIDBAND;
} else {
- qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
- (void) ath9k_hw_set_txq_props(ah, q, qinfo);
+ pCap->reg_cap =
+ AR_EEPROM_EEREGCAP_EN_KK_NEW_11A |
+ AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN;
}
- return q;
-}
+ pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND;
-static void
-ath9k_hw_set_txq_interrupts(struct ath_hal *ah,
- struct ath9k_tx_queue_info *qi)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
+ pCap->num_antcfg_5ghz =
+ ath9k_hw_get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_5GHZ);
+ pCap->num_antcfg_2ghz =
+ ath9k_hw_get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ);
- DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
- "%s: tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
- __func__, ahp->ah_txOkInterruptMask,
- ahp->ah_txErrInterruptMask, ahp->ah_txDescInterruptMask,
- ahp->ah_txEolInterruptMask, ahp->ah_txUrnInterruptMask);
-
- REG_WRITE(ah, AR_IMR_S0,
- SM(ahp->ah_txOkInterruptMask, AR_IMR_S0_QCU_TXOK)
- | SM(ahp->ah_txDescInterruptMask, AR_IMR_S0_QCU_TXDESC));
- REG_WRITE(ah, AR_IMR_S1,
- SM(ahp->ah_txErrInterruptMask, AR_IMR_S1_QCU_TXERR)
- | SM(ahp->ah_txEolInterruptMask, AR_IMR_S1_QCU_TXEOL));
- REG_RMW_FIELD(ah, AR_IMR_S2,
- AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask);
+ return true;
}
-bool ath9k_hw_releasetxqueue(struct ath_hal *ah, u32 q)
+bool ath9k_hw_getcapability(struct ath_hal *ah, enum ath9k_capability_type type,
+ u32 capability, u32 *result)
{
struct ath_hal_5416 *ahp = AH5416(ah);
- struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
- struct ath9k_tx_queue_info *qi;
+ const struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
- if (q >= pCap->total_queues) {
- DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n",
- __func__, q);
+ switch (type) {
+ case ATH9K_CAP_CIPHER:
+ switch (capability) {
+ case ATH9K_CIPHER_AES_CCM:
+ case ATH9K_CIPHER_AES_OCB:
+ case ATH9K_CIPHER_TKIP:
+ case ATH9K_CIPHER_WEP:
+ case ATH9K_CIPHER_MIC:
+ case ATH9K_CIPHER_CLR:
+ return true;
+ default:
+ return false;
+ }
+ case ATH9K_CAP_TKIP_MIC:
+ switch (capability) {
+ case 0:
+ return true;
+ case 1:
+ return (ahp->ah_staId1Defaults &
+ AR_STA_ID1_CRPT_MIC_ENABLE) ? true :
+ false;
+ }
+ case ATH9K_CAP_TKIP_SPLIT:
+ return (ahp->ah_miscMode & AR_PCU_MIC_NEW_LOC_ENA) ?
+ false : true;
+ case ATH9K_CAP_WME_TKIPMIC:
+ return 0;
+ case ATH9K_CAP_PHYCOUNTERS:
+ return ahp->ah_hasHwPhyCounters ? 0 : -ENXIO;
+ case ATH9K_CAP_DIVERSITY:
+ return (REG_READ(ah, AR_PHY_CCK_DETECT) &
+ AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ?
+ true : false;
+ case ATH9K_CAP_PHYDIAG:
+ return true;
+ case ATH9K_CAP_MCAST_KEYSRCH:
+ switch (capability) {
+ case 0:
+ return true;
+ case 1:
+ if (REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_ADHOC) {
+ return false;
+ } else {
+ return (ahp->ah_staId1Defaults &
+ AR_STA_ID1_MCAST_KSRCH) ? true :
+ false;
+ }
+ }
return false;
- }
- qi = &ahp->ah_txq[q];
- if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
- DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue %u\n",
- __func__, q);
+ case ATH9K_CAP_TSF_ADJUST:
+ return (ahp->ah_miscMode & AR_PCU_TX_ADD_TSF) ?
+ true : false;
+ case ATH9K_CAP_RFSILENT:
+ if (capability == 3)
+ return false;
+ case ATH9K_CAP_ANT_CFG_2GHZ:
+ *result = pCap->num_antcfg_2ghz;
+ return true;
+ case ATH9K_CAP_ANT_CFG_5GHZ:
+ *result = pCap->num_antcfg_5ghz;
+ return true;
+ case ATH9K_CAP_TXPOW:
+ switch (capability) {
+ case 0:
+ return 0;
+ case 1:
+ *result = ah->ah_powerLimit;
+ return 0;
+ case 2:
+ *result = ah->ah_maxPowerLevel;
+ return 0;
+ case 3:
+ *result = ah->ah_tpScale;
+ return 0;
+ }
+ return false;
+ default:
return false;
}
-
- DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: release queue %u\n",
- __func__, q);
-
- qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
- ahp->ah_txOkInterruptMask &= ~(1 << q);
- ahp->ah_txErrInterruptMask &= ~(1 << q);
- ahp->ah_txDescInterruptMask &= ~(1 << q);
- ahp->ah_txEolInterruptMask &= ~(1 << q);
- ahp->ah_txUrnInterruptMask &= ~(1 << q);
- ath9k_hw_set_txq_interrupts(ah, qi);
-
- return true;
}
-bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q)
+bool ath9k_hw_setcapability(struct ath_hal *ah, enum ath9k_capability_type type,
+ u32 capability, u32 setting, int *status)
{
struct ath_hal_5416 *ahp = AH5416(ah);
- struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
- struct ath9k_channel *chan = ah->ah_curchan;
- struct ath9k_tx_queue_info *qi;
- u32 cwMin, chanCwMin, value;
+ u32 v;
- if (q >= pCap->total_queues) {
- DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: invalid queue num %u\n",
- __func__, q);
- return false;
- }
- qi = &ahp->ah_txq[q];
- if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
- DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: inactive queue %u\n",
- __func__, q);
+ switch (type) {
+ case ATH9K_CAP_TKIP_MIC:
+ if (setting)
+ ahp->ah_staId1Defaults |=
+ AR_STA_ID1_CRPT_MIC_ENABLE;
+ else
+ ahp->ah_staId1Defaults &=
+ ~AR_STA_ID1_CRPT_MIC_ENABLE;
return true;
- }
-
- DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: reset queue %u\n", __func__, q);
-
- if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
- if (chan && IS_CHAN_B(chan))
- chanCwMin = INIT_CWMIN_11B;
+ case ATH9K_CAP_DIVERSITY:
+ v = REG_READ(ah, AR_PHY_CCK_DETECT);
+ if (setting)
+ v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
else
- chanCwMin = INIT_CWMIN;
-
- for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1);
- } else
- cwMin = qi->tqi_cwmin;
-
- REG_WRITE(ah, AR_DLCL_IFS(q), SM(cwMin, AR_D_LCL_IFS_CWMIN)
- | SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX)
- | SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
-
- REG_WRITE(ah, AR_DRETRY_LIMIT(q),
- SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH)
- | SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG)
- | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));
-
- REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
- REG_WRITE(ah, AR_DMISC(q),
- AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
-
- if (qi->tqi_cbrPeriod) {
- REG_WRITE(ah, AR_QCBRCFG(q),
- SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL)
- | SM(qi->tqi_cbrOverflowLimit,
- AR_Q_CBRCFG_OVF_THRESH));
- REG_WRITE(ah, AR_QMISC(q),
- REG_READ(ah,
- AR_QMISC(q)) | AR_Q_MISC_FSP_CBR | (qi->
- tqi_cbrOverflowLimit
- ?
- AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN
- :
- 0));
- }
- if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) {
- REG_WRITE(ah, AR_QRDYTIMECFG(q),
- SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
- AR_Q_RDYTIMECFG_EN);
- }
-
- REG_WRITE(ah, AR_DCHNTIME(q),
- SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
- (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
-
- if (qi->tqi_burstTime
- && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) {
- REG_WRITE(ah, AR_QMISC(q),
- REG_READ(ah,
- AR_QMISC(q)) |
- AR_Q_MISC_RDYTIME_EXP_POLICY);
-
- }
-
- if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) {
- REG_WRITE(ah, AR_DMISC(q),
- REG_READ(ah, AR_DMISC(q)) |
- AR_D_MISC_POST_FR_BKOFF_DIS);
- }
- if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {
- REG_WRITE(ah, AR_DMISC(q),
- REG_READ(ah, AR_DMISC(q)) |
- AR_D_MISC_FRAG_BKOFF_EN);
- }
- switch (qi->tqi_type) {
- case ATH9K_TX_QUEUE_BEACON:
- REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
- | AR_Q_MISC_FSP_DBA_GATED
- | AR_Q_MISC_BEACON_USE
- | AR_Q_MISC_CBR_INCR_DIS1);
-
- REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
- | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
- AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
- | AR_D_MISC_BEACON_USE
- | AR_D_MISC_POST_FR_BKOFF_DIS);
- break;
- case ATH9K_TX_QUEUE_CAB:
- REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
- | AR_Q_MISC_FSP_DBA_GATED
- | AR_Q_MISC_CBR_INCR_DIS1
- | AR_Q_MISC_CBR_INCR_DIS0);
- value = (qi->tqi_readyTime
- - (ah->ah_config.sw_beacon_response_time -
- ah->ah_config.dma_beacon_response_time)
- -
- ah->ah_config.additional_swba_backoff) *
- 1024;
- REG_WRITE(ah, AR_QRDYTIMECFG(q),
- value | AR_Q_RDYTIMECFG_EN);
- REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
- | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
- AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
- break;
- case ATH9K_TX_QUEUE_PSPOLL:
- REG_WRITE(ah, AR_QMISC(q),
- REG_READ(ah,
- AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1);
- break;
- case ATH9K_TX_QUEUE_UAPSD:
- REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
- | AR_D_MISC_POST_FR_BKOFF_DIS);
- break;
+ v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV;
+ REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
+ return true;
+ case ATH9K_CAP_MCAST_KEYSRCH:
+ if (setting)
+ ahp->ah_staId1Defaults |= AR_STA_ID1_MCAST_KSRCH;
+ else
+ ahp->ah_staId1Defaults &= ~AR_STA_ID1_MCAST_KSRCH;
+ return true;
+ case ATH9K_CAP_TSF_ADJUST:
+ if (setting)
+ ahp->ah_miscMode |= AR_PCU_TX_ADD_TSF;
+ else
+ ahp->ah_miscMode &= ~AR_PCU_TX_ADD_TSF;
+ return true;
default:
- break;
- }
-
- if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {
- REG_WRITE(ah, AR_DMISC(q),
- REG_READ(ah, AR_DMISC(q)) |
- SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
- AR_D_MISC_ARB_LOCKOUT_CNTRL) |
- AR_D_MISC_POST_FR_BKOFF_DIS);
+ return false;
}
-
- if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
- ahp->ah_txOkInterruptMask |= 1 << q;
- else
- ahp->ah_txOkInterruptMask &= ~(1 << q);
- if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE)
- ahp->ah_txErrInterruptMask |= 1 << q;
- else
- ahp->ah_txErrInterruptMask &= ~(1 << q);
- if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
- ahp->ah_txDescInterruptMask |= 1 << q;
- else
- ahp->ah_txDescInterruptMask &= ~(1 << q);
- if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
- ahp->ah_txEolInterruptMask |= 1 << q;
- else
- ahp->ah_txEolInterruptMask &= ~(1 << q);
- if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
- ahp->ah_txUrnInterruptMask |= 1 << q;
- else
- ahp->ah_txUrnInterruptMask &= ~(1 << q);
- ath9k_hw_set_txq_interrupts(ah, qi);
-
- return true;
}
-void ath9k_hw_gettxintrtxqs(struct ath_hal *ah, u32 *txqs)
-{
- struct ath_hal_5416 *ahp = AH5416(ah);
- *txqs &= ahp->ah_intrTxqs;
- ahp->ah_intrTxqs &= ~(*txqs);
-}
+/****************************/
+/* GPIO / RFKILL / Antennae */
+/****************************/
-bool
-ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,
- u32 segLen, bool firstSeg,
- bool lastSeg, const struct ath_desc *ds0)
-{
- struct ar5416_desc *ads = AR5416DESC(ds);
-
- if (firstSeg) {
- ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
- } else if (lastSeg) {
- ads->ds_ctl0 = 0;
- ads->ds_ctl1 = segLen;
- ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
- ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
- } else {
- ads->ds_ctl0 = 0;
- ads->ds_ctl1 = segLen | AR_TxMore;
- ads->ds_ctl2 = 0;
- ads->ds_ctl3 = 0;
- }
- ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
- ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
- ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
- ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
- ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
- return true;
-}
-
-void ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds)
+static void ath9k_hw_gpio_cfg_output_mux(struct ath_hal *ah,
+ u32 gpio, u32 type)
{
- struct ar5416_desc *ads = AR5416DESC(ds);
+ int addr;
+ u32 gpio_shift, tmp;
- ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
- ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
- ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
- ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
- ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
-}
+ if (gpio > 11)
+ addr = AR_GPIO_OUTPUT_MUX3;
+ else if (gpio > 5)
+ addr = AR_GPIO_OUTPUT_MUX2;
+ else
+ addr = AR_GPIO_OUTPUT_MUX1;
-int
-ath9k_hw_txprocdesc(struct ath_hal *ah, struct ath_desc *ds)
-{
- struct ar5416_desc *ads = AR5416DESC(ds);
-
- if ((ads->ds_txstatus9 & AR_TxDone) == 0)
- return -EINPROGRESS;
-
- ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
- ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp;
- ds->ds_txstat.ts_status = 0;
- ds->ds_txstat.ts_flags = 0;
-
- if (ads->ds_txstatus1 & AR_ExcessiveRetries)
- ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY;
- if (ads->ds_txstatus1 & AR_Filtered)
- ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT;
- if (ads->ds_txstatus1 & AR_FIFOUnderrun)
- ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO;
- if (ads->ds_txstatus9 & AR_TxOpExceeded)
- ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP;
- if (ads->ds_txstatus1 & AR_TxTimerExpired)
- ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
-
- if (ads->ds_txstatus1 & AR_DescCfgErr)
- ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR;
- if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
- ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN;
- ath9k_hw_updatetxtriglevel(ah, true);
- }
- if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
- ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
- ath9k_hw_updatetxtriglevel(ah, true);
- }
- if (ads->ds_txstatus0 & AR_TxBaStatus) {
- ds->ds_txstat.ts_flags |= ATH9K_TX_BA;
- ds->ds_txstat.ba_low = ads->AR_BaBitmapLow;
- ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh;
- }
+ gpio_shift = (gpio % 6) * 5;
- ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
- switch (ds->ds_txstat.ts_rateindex) {
- case 0:
- ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
- break;
- case 1:
- ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
- break;
- case 2:
- ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
- break;
- case 3:
- ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
- break;
+ if (AR_SREV_9280_20_OR_LATER(ah)
+ || (addr != AR_GPIO_OUTPUT_MUX1)) {
+ REG_RMW(ah, addr, (type << gpio_shift),
+ (0x1f << gpio_shift));
+ } else {
+ tmp = REG_READ(ah, addr);
+ tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0);
+ tmp &= ~(0x1f << gpio_shift);
+ tmp |= (type << gpio_shift);
+ REG_WRITE(ah, addr, tmp);
}
-
- ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
- ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
- ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
- ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
- ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
- ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
- ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
- ds->ds_txstat.evm0 = ads->AR_TxEVM0;
- ds->ds_txstat.evm1 = ads->AR_TxEVM1;
- ds->ds_txstat.evm2 = ads->AR_TxEVM2;
- ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
- ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
- ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
- ds->ds_txstat.ts_antenna = 1;
-
- return 0;
}
-void
-ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds,
- u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
- u32 keyIx, enum ath9k_key_type keyType, u32 flags)
+void ath9k_hw_cfg_gpio_input(struct ath_hal *ah, u32 gpio)
{
- struct ar5416_desc *ads = AR5416DESC(ds);
- struct ath_hal_5416 *ahp = AH5416(ah);
-
- txPower += ahp->ah_txPowerIndexOffset;
- if (txPower > 63)
- txPower = 63;
-
- ads->ds_ctl0 = (pktLen & AR_FrameLen)
- | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
- | SM(txPower, AR_XmitPower)
- | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
- | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
- | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
- | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
-
- ads->ds_ctl1 =
- (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
- | SM(type, AR_FrameType)
- | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
- | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
- | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
+ u32 gpio_shift;
- ads->ds_ctl6 = SM(keyType, AR_EncrType);
+ ASSERT(gpio < ah->ah_caps.num_gpio_pins);
- if (AR_SREV_9285(ah)) {
+ gpio_shift = gpio << 1;
- ads->ds_ctl8 = 0;
- ads->ds_ctl9 = 0;
- ads->ds_ctl10 = 0;
- ads->ds_ctl11 = 0;
- }
+ REG_RMW(ah,
+ AR_GPIO_OE_OUT,
+ (AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
+ (AR_GPIO_OE_OUT_DRV << gpio_shift));
}
-void
-ath9k_hw_set11n_ratescenario(struct ath_hal *ah, struct ath_desc *ds,
- struct ath_desc *lastds,
- u32 durUpdateEn, u32 rtsctsRate,
- u32 rtsctsDuration,
- struct ath9k_11n_rate_series series[],
- u32 nseries, u32 flags)
+u32 ath9k_hw_gpio_get(struct ath_hal *ah, u32 gpio)
{
- struct ar5416_desc *ads = AR5416DESC(ds);
- struct ar5416_desc *last_ads = AR5416DESC(lastds);
- u32 ds_ctl0;
-
- (void) nseries;
- (void) rtsctsDuration;
-
- if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
- ds_ctl0 = ads->ds_ctl0;
-
- if (flags & ATH9K_TXDESC_RTSENA) {
- ds_ctl0 &= ~AR_CTSEnable;
- ds_ctl0 |= AR_RTSEnable;
- } else {
- ds_ctl0 &= ~AR_RTSEnable;
- ds_ctl0 |= AR_CTSEnable;
- }
+ if (gpio >= ah->ah_caps.num_gpio_pins)
+ return 0xffffffff;
- ads->ds_ctl0 = ds_ctl0;
+ if (AR_SREV_9280_10_OR_LATER(ah)) {
+ return (MS
+ (REG_READ(ah, AR_GPIO_IN_OUT),
+ AR928X_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) != 0;
} else {
- ads->ds_ctl0 =
- (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
+ return (MS(REG_READ(ah, AR_GPIO_IN_OUT), AR_GPIO_IN_VAL) &
+ AR_GPIO_BIT(gpio)) != 0;
}
-
- ads->ds_ctl2 = set11nTries(series, 0)
- | set11nTries(series, 1)
- | set11nTries(series, 2)
- | set11nTries(series, 3)
- | (durUpdateEn ? AR_DurUpdateEna : 0)
- | SM(0, AR_BurstDur);
-
- ads->ds_ctl3 = set11nRate(series, 0)
- | set11nRate(series, 1)
- | set11nRate(series, 2)
- | set11nRate(series, 3);
-
- ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
- | set11nPktDurRTSCTS(series, 1);
-
- ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
- | set11nPktDurRTSCTS(series, 3);
-
- ads->ds_ctl7 = set11nRateFlags(series, 0)
- | set11nRateFlags(series, 1)
- | set11nRateFlags(series, 2)
- | set11nRateFlags(series, 3)
- | SM(rtsctsRate, AR_RTSCTSRate);
- last_ads->ds_ctl2 = ads->ds_ctl2;
- last_ads->ds_ctl3 = ads->ds_ctl3;
}
-void
-ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds,
- u32 aggrLen)
+void ath9k_hw_cfg_output(struct ath_hal *ah, u32 gpio,
+ u32 ah_signal_type)
{
- struct ar5416_desc *ads = AR5416DESC(ds);
-
- ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
-
- ads->ds_ctl6 &= ~AR_AggrLen;
- ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
-}
+ u32 gpio_shift;
-void
-ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds,
- u32 numDelims)
-{
- struct ar5416_desc *ads = AR5416DESC(ds);
- unsigned int ctl6;
+ ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
- ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
+ gpio_shift = 2 * gpio;
- ctl6 = ads->ds_ctl6;
- ctl6 &= ~AR_PadDelim;
- ctl6 |= SM(numDelims, AR_PadDelim);
- ads->ds_ctl6 = ctl6;
+ REG_RMW(ah,
+ AR_GPIO_OE_OUT,
+ (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
+ (AR_GPIO_OE_OUT_DRV << gpio_shift));
}
-void ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds)
+void ath9k_hw_set_gpio(struct ath_hal *ah, u32 gpio, u32 val)
{
- struct ar5416_desc *ads = AR5416DESC(ds);
-
- ads->ds_ctl1 |= AR_IsAggr;
- ads->ds_ctl1 &= ~AR_MoreAggr;
- ads->ds_ctl6 &= ~AR_PadDelim;
+ REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio),
+ AR_GPIO_BIT(gpio));
}
-void ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds)
+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
+void ath9k_enable_rfkill(struct ath_hal *ah)
{
- struct ar5416_desc *ads = AR5416DESC(ds);
+ REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
+ AR_GPIO_INPUT_EN_VAL_RFSILENT_BB);
- ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
+ REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2,
+ AR_GPIO_INPUT_MUX2_RFSILENT);
+
+ ath9k_hw_cfg_gpio_input(ah, ah->ah_rfkill_gpio);
+ REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB);
}
+#endif
-void
-ath9k_hw_set11n_burstduration(struct ath_hal *ah, struct ath_desc *ds,
- u32 burstDuration)
+int ath9k_hw_select_antconfig(struct ath_hal *ah, u32 cfg)
{
- struct ar5416_desc *ads = AR5416DESC(ds);
+ struct ath9k_channel *chan = ah->ah_curchan;
+ const struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+ u16 ant_config;
+ u32 halNumAntConfig;
- ads->ds_ctl2 &= ~AR_BurstDur;
- ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
-}
+ halNumAntConfig = IS_CHAN_2GHZ(chan) ?
+ pCap->num_antcfg_2ghz : pCap->num_antcfg_5ghz;
-void
-ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah, struct ath_desc *ds,
- u32 vmf)
-{
- struct ar5416_desc *ads = AR5416DESC(ds);
+ if (cfg < halNumAntConfig) {
+ if (!ath9k_hw_get_eeprom_antenna_cfg(ah, chan,
+ cfg, &ant_config)) {
+ REG_WRITE(ah, AR_PHY_SWITCH_COM, ant_config);
+ return 0;
+ }
+ }
- if (vmf)
- ads->ds_ctl0 |= AR_VirtMoreFrag;
- else
- ads->ds_ctl0 &= ~AR_VirtMoreFrag;
+ return -EINVAL;
}
-void ath9k_hw_putrxbuf(struct ath_hal *ah, u32 rxdp)
+u32 ath9k_hw_getdefantenna(struct ath_hal *ah)
{
- REG_WRITE(ah, AR_RXDP, rxdp);
+ return REG_READ(ah, AR_DEF_ANTENNA) & 0x7;
}
-void ath9k_hw_rxena(struct ath_hal *ah)
+void ath9k_hw_setantenna(struct ath_hal *ah, u32 antenna)
{
- REG_WRITE(ah, AR_CR, AR_CR_RXE);
+ REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7));
}
-bool ath9k_hw_setrxabort(struct ath_hal *ah, bool set)
+bool ath9k_hw_setantennaswitch(struct ath_hal *ah,
+ enum ath9k_ant_setting settings,
+ struct ath9k_channel *chan,
+ u8 *tx_chainmask,
+ u8 *rx_chainmask,
+ u8 *antenna_cfgd)
{
- if (set) {
-
- REG_SET_BIT(ah, AR_DIAG_SW,
- (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
-
- if (!ath9k_hw_wait
- (ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, 0)) {
- u32 reg;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ static u8 tx_chainmask_cfg, rx_chainmask_cfg;
- REG_CLR_BIT(ah, AR_DIAG_SW,
- (AR_DIAG_RX_DIS |
- AR_DIAG_RX_ABORT));
+ if (AR_SREV_9280(ah)) {
+ if (!tx_chainmask_cfg) {
- reg = REG_READ(ah, AR_OBS_BUS_1);
- DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
- "%s: rx failed to go idle in 10 ms RXSM=0x%x\n",
- __func__, reg);
+ tx_chainmask_cfg = *tx_chainmask;
+ rx_chainmask_cfg = *rx_chainmask;
+ }
- return false;
+ switch (settings) {
+ case ATH9K_ANT_FIXED_A:
+ *tx_chainmask = ATH9K_ANTENNA0_CHAINMASK;
+ *rx_chainmask = ATH9K_ANTENNA0_CHAINMASK;
+ *antenna_cfgd = true;
+ break;
+ case ATH9K_ANT_FIXED_B:
+ if (ah->ah_caps.tx_chainmask >
+ ATH9K_ANTENNA1_CHAINMASK) {
+ *tx_chainmask = ATH9K_ANTENNA1_CHAINMASK;
+ }
+ *rx_chainmask = ATH9K_ANTENNA1_CHAINMASK;
+ *antenna_cfgd = true;
+ break;
+ case ATH9K_ANT_VARIABLE:
+ *tx_chainmask = tx_chainmask_cfg;
+ *rx_chainmask = rx_chainmask_cfg;
+ *antenna_cfgd = true;
+ break;
+ default:
+ break;
}
} else {
- REG_CLR_BIT(ah, AR_DIAG_SW,
- (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+ ahp->ah_diversityControl = settings;
}
return true;
}
-void
-ath9k_hw_setmcastfilter(struct ath_hal *ah, u32 filter0,
- u32 filter1)
-{
- REG_WRITE(ah, AR_MCAST_FIL0, filter0);
- REG_WRITE(ah, AR_MCAST_FIL1, filter1);
-}
+/*********************/
+/* General Operation */
+/*********************/
-bool
-ath9k_hw_setuprxdesc(struct ath_hal *ah, struct ath_desc *ds,
- u32 size, u32 flags)
+u32 ath9k_hw_getrxfilter(struct ath_hal *ah)
{
- struct ar5416_desc *ads = AR5416DESC(ds);
- struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+ u32 bits = REG_READ(ah, AR_RX_FILTER);
+ u32 phybits = REG_READ(ah, AR_PHY_ERR);
- ads->ds_ctl1 = size & AR_BufLen;
- if (flags & ATH9K_RXDESC_INTREQ)
- ads->ds_ctl1 |= AR_RxIntrReq;
+ if (phybits & AR_PHY_ERR_RADAR)
+ bits |= ATH9K_RX_FILTER_PHYRADAR;
+ if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING))
+ bits |= ATH9K_RX_FILTER_PHYERR;
- ads->ds_rxstatus8 &= ~AR_RxDone;
- if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
- memset(&(ads->u), 0, sizeof(ads->u));
- return true;
+ return bits;
}
-int
-ath9k_hw_rxprocdesc(struct ath_hal *ah, struct ath_desc *ds,
- u32 pa, struct ath_desc *nds, u64 tsf)
+void ath9k_hw_setrxfilter(struct ath_hal *ah, u32 bits)
{
- struct ar5416_desc ads;
- struct ar5416_desc *adsp = AR5416DESC(ds);
-
- if ((adsp->ds_rxstatus8 & AR_RxDone) == 0)
- return -EINPROGRESS;
-
- ads.u.rx = adsp->u.rx;
-
- ds->ds_rxstat.rs_status = 0;
- ds->ds_rxstat.rs_flags = 0;
+ u32 phybits;
- ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
- ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp;
+ REG_WRITE(ah, AR_RX_FILTER, (bits & 0xffff) | AR_RX_COMPR_BAR);
+ phybits = 0;
+ if (bits & ATH9K_RX_FILTER_PHYRADAR)
+ phybits |= AR_PHY_ERR_RADAR;
+ if (bits & ATH9K_RX_FILTER_PHYERR)
+ phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING;
+ REG_WRITE(ah, AR_PHY_ERR, phybits);
- ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
- ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00);
- ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01);
- ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02);
- ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10);
- ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11);
- ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12);
- if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
- ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
+ if (phybits)
+ REG_WRITE(ah, AR_RXCFG,
+ REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA);
else
- ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID;
-
- ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads));
- ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
-
- ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
- ds->ds_rxstat.rs_moreaggr =
- (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
- ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
- ds->ds_rxstat.rs_flags =
- (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0;
- ds->ds_rxstat.rs_flags |=
- (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0;
-
- if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)
- ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
- if (ads.ds_rxstatus8 & AR_PostDelimCRCErr)
- ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST;
- if (ads.ds_rxstatus8 & AR_DecryptBusyErr)
- ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY;
-
- if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
-
- if (ads.ds_rxstatus8 & AR_CRCErr)
- ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC;
- else if (ads.ds_rxstatus8 & AR_PHYErr) {
- u32 phyerr;
-
- ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY;
- phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
- ds->ds_rxstat.rs_phyerr = phyerr;
- } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
- ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT;
- else if (ads.ds_rxstatus8 & AR_MichaelErr)
- ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC;
- }
-
- return 0;
+ REG_WRITE(ah, AR_RXCFG,
+ REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA);
}
-static void ath9k_hw_setup_rate_table(struct ath_hal *ah,
- struct ath9k_rate_table *rt)
+bool ath9k_hw_phy_disable(struct ath_hal *ah)
{
- int i;
-
- if (rt->rateCodeToIndex[0] != 0)
- return;
- for (i = 0; i < 256; i++)
- rt->rateCodeToIndex[i] = (u8) -1;
- for (i = 0; i < rt->rateCount; i++) {
- u8 code = rt->info[i].rateCode;
- u8 cix = rt->info[i].controlRate;
-
- rt->rateCodeToIndex[code] = i;
- rt->rateCodeToIndex[code | rt->info[i].shortPreamble] = i;
-
- rt->info[i].lpAckDuration =
- ath9k_hw_computetxtime(ah, rt,
- WLAN_CTRL_FRAME_SIZE,
- cix,
- false);
- rt->info[i].spAckDuration =
- ath9k_hw_computetxtime(ah, rt,
- WLAN_CTRL_FRAME_SIZE,
- cix,
- true);
- }
+ return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM);
}
-const struct ath9k_rate_table *ath9k_hw_getratetable(struct ath_hal *ah,
- u32 mode)
+bool ath9k_hw_disable(struct ath_hal *ah)
{
- struct ath9k_rate_table *rt;
- switch (mode) {
- case ATH9K_MODE_11A:
- rt = &ar5416_11a_table;
- break;
- case ATH9K_MODE_11B:
- rt = &ar5416_11b_table;
- break;
- case ATH9K_MODE_11G:
- rt = &ar5416_11g_table;
- break;
- case ATH9K_MODE_11NG_HT20:
- case ATH9K_MODE_11NG_HT40PLUS:
- case ATH9K_MODE_11NG_HT40MINUS:
- rt = &ar5416_11ng_table;
- break;
- case ATH9K_MODE_11NA_HT20:
- case ATH9K_MODE_11NA_HT40PLUS:
- case ATH9K_MODE_11NA_HT40MINUS:
- rt = &ar5416_11na_table;
- break;
- default:
- DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, "%s: invalid mode 0x%x\n",
- __func__, mode);
- return NULL;
- }
- ath9k_hw_setup_rate_table(ah, rt);
- return rt;
-}
+ if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
+ return false;
-static const char *ath9k_hw_devname(u16 devid)
-{
- switch (devid) {
- case AR5416_DEVID_PCI:
- case AR5416_DEVID_PCIE:
- return "Atheros 5416";
- case AR9160_DEVID_PCI:
- return "Atheros 9160";
- case AR9280_DEVID_PCI:
- case AR9280_DEVID_PCIE:
- return "Atheros 9280";
- }
- return NULL;
+ return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD);
}
-const char *ath9k_hw_probe(u16 vendorid, u16 devid)
+bool ath9k_hw_set_txpowerlimit(struct ath_hal *ah, u32 limit)
{
- return vendorid == ATHEROS_VENDOR_ID ?
- ath9k_hw_devname(devid) : NULL;
-}
+ struct ath9k_channel *chan = ah->ah_curchan;
-struct ath_hal *ath9k_hw_attach(u16 devid,
- struct ath_softc *sc,
- void __iomem *mem,
- int *error)
-{
- struct ath_hal *ah = NULL;
+ ah->ah_powerLimit = min(limit, (u32) MAX_RATE_POWER);
- switch (devid) {
- case AR5416_DEVID_PCI:
- case AR5416_DEVID_PCIE:
- case AR9160_DEVID_PCI:
- case AR9280_DEVID_PCI:
- case AR9280_DEVID_PCIE:
- ah = ath9k_hw_do_attach(devid, sc, mem, error);
- break;
- default:
- DPRINTF(ah->ah_sc, ATH_DBG_ANY,
- "devid=0x%x not supported.\n", devid);
- ah = NULL;
- *error = -ENXIO;
- break;
- }
+ if (ath9k_hw_set_txpower(ah, chan,
+ ath9k_regd_get_ctl(ah, chan),
+ ath9k_regd_get_antenna_allowed(ah, chan),
+ chan->maxRegTxPower * 2,
+ min((u32) MAX_RATE_POWER,
+ (u32) ah->ah_powerLimit)) != 0)
+ return false;
- return ah;
+ return true;
}
-u16
-ath9k_hw_computetxtime(struct ath_hal *ah,
- const struct ath9k_rate_table *rates,
- u32 frameLen, u16 rateix,
- bool shortPreamble)
+void ath9k_hw_getmac(struct ath_hal *ah, u8 *mac)
{
- u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
- u32 kbps;
-
- kbps = rates->info[rateix].rateKbps;
-
- if (kbps == 0)
- return 0;
- switch (rates->info[rateix].phy) {
-
- case PHY_CCK:
- phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
- if (shortPreamble && rates->info[rateix].shortPreamble)
- phyTime >>= 1;
- numBits = frameLen << 3;
- txTime = CCK_SIFS_TIME + phyTime
- + ((numBits * 1000) / kbps);
- break;
- case PHY_OFDM:
- if (ah->ah_curchan && IS_CHAN_QUARTER_RATE(ah->ah_curchan)) {
- bitsPerSymbol =
- (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000;
-
- numBits = OFDM_PLCP_BITS + (frameLen << 3);
- numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
- txTime = OFDM_SIFS_TIME_QUARTER
- + OFDM_PREAMBLE_TIME_QUARTER
- + (numSymbols * OFDM_SYMBOL_TIME_QUARTER);
- } else if (ah->ah_curchan &&
- IS_CHAN_HALF_RATE(ah->ah_curchan)) {
- bitsPerSymbol =
- (kbps * OFDM_SYMBOL_TIME_HALF) / 1000;
-
- numBits = OFDM_PLCP_BITS + (frameLen << 3);
- numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
- txTime = OFDM_SIFS_TIME_HALF +
- OFDM_PREAMBLE_TIME_HALF
- + (numSymbols * OFDM_SYMBOL_TIME_HALF);
- } else {
- bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000;
-
- numBits = OFDM_PLCP_BITS + (frameLen << 3);
- numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol);
- txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME
- + (numSymbols * OFDM_SYMBOL_TIME);
- }
- break;
+ struct ath_hal_5416 *ahp = AH5416(ah);
- default:
- DPRINTF(ah->ah_sc, ATH_DBG_PHY_IO,
- "%s: unknown phy %u (rate ix %u)\n", __func__,
- rates->info[rateix].phy, rateix);
- txTime = 0;
- break;
- }
- return txTime;
+ memcpy(mac, ahp->ah_macaddr, ETH_ALEN);
}
-u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags)
+bool ath9k_hw_setmac(struct ath_hal *ah, const u8 *mac)
{
- if (flags & CHANNEL_2GHZ) {
- if (freq == 2484)
- return 14;
- if (freq < 2484)
- return (freq - 2407) / 5;
- else
- return 15 + ((freq - 2512) / 20);
- } else if (flags & CHANNEL_5GHZ) {
- if (ath9k_regd_is_public_safety_sku(ah) &&
- IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
- return ((freq * 10) +
- (((freq % 5) == 2) ? 5 : 0) - 49400) / 5;
- } else if ((flags & CHANNEL_A) && (freq <= 5000)) {
- return (freq - 4000) / 5;
- } else {
- return (freq - 5000) / 5;
- }
- } else {
- if (freq == 2484)
- return 14;
- if (freq < 2484)
- return (freq - 2407) / 5;
- if (freq < 5000) {
- if (ath9k_regd_is_public_safety_sku(ah)
- && IS_CHAN_IN_PUBLIC_SAFETY_BAND(freq)) {
- return ((freq * 10) +
- (((freq % 5) ==
- 2) ? 5 : 0) - 49400) / 5;
- } else if (freq > 4900) {
- return (freq - 4000) / 5;
- } else {
- return 15 + ((freq - 2512) / 20);
- }
- }
- return (freq - 5000) / 5;
- }
-}
+ struct ath_hal_5416 *ahp = AH5416(ah);
-/* We can tune this as we go by monitoring really low values */
-#define ATH9K_NF_TOO_LOW -60
+ memcpy(ahp->ah_macaddr, mac, ETH_ALEN);
-/* AR5416 may return very high value (like -31 dBm), in those cases the nf
- * is incorrect and we should use the static NF value. Later we can try to
- * find out why they are reporting these values */
-static bool ath9k_hw_nf_in_range(struct ath_hal *ah, s16 nf)
-{
- if (nf > ATH9K_NF_TOO_LOW) {
- DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
- "%s: noise floor value detected (%d) is "
- "lower than what we think is a "
- "reasonable value (%d)\n",
- __func__, nf, ATH9K_NF_TOO_LOW);
- return false;
- }
return true;
}
-s16
-ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan)
+void ath9k_hw_setopmode(struct ath_hal *ah)
{
- struct ath9k_channel *ichan;
- s16 nf;
-
- ichan = ath9k_regd_check_channel(ah, chan);
- if (ichan == NULL) {
- DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL,
- "%s: invalid channel %u/0x%x; no mapping\n",
- __func__, chan->channel, chan->channelFlags);
- return ATH_DEFAULT_NOISE_FLOOR;
- }
- if (ichan->rawNoiseFloor == 0) {
- enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan);
- nf = NOISE_FLOOR[mode];
- } else
- nf = ichan->rawNoiseFloor;
-
- if (!ath9k_hw_nf_in_range(ah, nf))
- nf = ATH_DEFAULT_NOISE_FLOOR;
-
- return nf;
+ ath9k_hw_set_operating_mode(ah, ah->ah_opmode);
}
-bool ath9k_hw_set_tsfadjust(struct ath_hal *ah, u32 setting)
+void ath9k_hw_setmcastfilter(struct ath_hal *ah, u32 filter0, u32 filter1)
{
- struct ath_hal_5416 *ahp = AH5416(ah);
-
- if (setting)
- ahp->ah_miscMode |= AR_PCU_TX_ADD_TSF;
- else
- ahp->ah_miscMode &= ~AR_PCU_TX_ADD_TSF;
- return true;
+ REG_WRITE(ah, AR_MCAST_FIL0, filter0);
+ REG_WRITE(ah, AR_MCAST_FIL1, filter1);
}
-bool ath9k_hw_phycounters(struct ath_hal *ah)
+void ath9k_hw_getbssidmask(struct ath_hal *ah, u8 *mask)
{
struct ath_hal_5416 *ahp = AH5416(ah);
- return ahp->ah_hasHwPhyCounters ? true : false;
+ memcpy(mask, ahp->ah_bssidmask, ETH_ALEN);
}
-u32 ath9k_hw_gettxbuf(struct ath_hal *ah, u32 q)
+bool ath9k_hw_setbssidmask(struct ath_hal *ah, const u8 *mask)
{
- return REG_READ(ah, AR_QTXDP(q));
-}
+ struct ath_hal_5416 *ahp = AH5416(ah);
-bool ath9k_hw_puttxbuf(struct ath_hal *ah, u32 q,
- u32 txdp)
-{
- REG_WRITE(ah, AR_QTXDP(q), txdp);
+ memcpy(ahp->ah_bssidmask, mask, ETH_ALEN);
+
+ REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(ahp->ah_bssidmask));
+ REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(ahp->ah_bssidmask + 4));
return true;
}
-bool ath9k_hw_txstart(struct ath_hal *ah, u32 q)
+void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid, u16 assocId)
{
- DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "%s: queue %u\n", __func__, q);
+ struct ath_hal_5416 *ahp = AH5416(ah);
- REG_WRITE(ah, AR_Q_TXE, 1 << q);
+ memcpy(ahp->ah_bssid, bssid, ETH_ALEN);
+ ahp->ah_assocId = assocId;
- return true;
+ REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(ahp->ah_bssid));
+ REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(ahp->ah_bssid + 4) |
+ ((assocId & 0x3fff) << AR_BSS_ID1_AID_S));
}
-u32 ath9k_hw_numtxpending(struct ath_hal *ah, u32 q)
+u64 ath9k_hw_gettsf64(struct ath_hal *ah)
{
- u32 npend;
+ u64 tsf;
- npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
- if (npend == 0) {
+ tsf = REG_READ(ah, AR_TSF_U32);
+ tsf = (tsf << 32) | REG_READ(ah, AR_TSF_L32);
- if (REG_READ(ah, AR_Q_TXE) & (1 << q))
- npend = 1;
- }
- return npend;
+ return tsf;
}
-bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q)
+void ath9k_hw_reset_tsf(struct ath_hal *ah)
{
- u32 wait;
-
- REG_WRITE(ah, AR_Q_TXD, 1 << q);
+ int count;
- for (wait = 1000; wait != 0; wait--) {
- if (ath9k_hw_numtxpending(ah, q) == 0)
+ count = 0;
+ while (REG_READ(ah, AR_SLP32_MODE) & AR_SLP32_TSF_WRITE_STATUS) {
+ count++;
+ if (count > 10) {
+ DPRINTF(ah->ah_sc, ATH_DBG_RESET,
+ "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n");
break;
- udelay(100);
+ }
+ udelay(10);
}
+ REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE);
+}
- if (ath9k_hw_numtxpending(ah, q)) {
- u32 tsfLow, j;
-
- DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
- "%s: Num of pending TX Frames %d on Q %d\n",
- __func__, ath9k_hw_numtxpending(ah, q), q);
-
- for (j = 0; j < 2; j++) {
- tsfLow = REG_READ(ah, AR_TSF_L32);
- REG_WRITE(ah, AR_QUIET2,
- SM(10, AR_QUIET2_QUIET_DUR));
- REG_WRITE(ah, AR_QUIET_PERIOD, 100);
- REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
- REG_SET_BIT(ah, AR_TIMER_MODE,
- AR_QUIET_TIMER_EN);
+bool ath9k_hw_set_tsfadjust(struct ath_hal *ah, u32 setting)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
- if ((REG_READ(ah, AR_TSF_L32) >> 10) ==
- (tsfLow >> 10)) {
- break;
- }
- DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
- "%s: TSF have moved while trying to set "
- "quiet time TSF: 0x%08x\n",
- __func__, tsfLow);
- }
+ if (setting)
+ ahp->ah_miscMode |= AR_PCU_TX_ADD_TSF;
+ else
+ ahp->ah_miscMode &= ~AR_PCU_TX_ADD_TSF;
- REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+ return true;
+}
- udelay(200);
- REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
+bool ath9k_hw_setslottime(struct ath_hal *ah, u32 us)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
- wait = 1000;
+ if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad slot time %u\n", us);
+ ahp->ah_slottime = (u32) -1;
+ return false;
+ } else {
+ REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us));
+ ahp->ah_slottime = us;
+ return true;
+ }
+}
- while (ath9k_hw_numtxpending(ah, q)) {
- if ((--wait) == 0) {
- DPRINTF(ah->ah_sc, ATH_DBG_XMIT,
- "%s: Failed to stop Tx DMA in 100 "
- "msec after killing last frame\n",
- __func__);
- break;
- }
- udelay(100);
- }
+void ath9k_hw_set11nmac2040(struct ath_hal *ah, enum ath9k_ht_macmode mode)
+{
+ u32 macmode;
- REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
- }
+ if (mode == ATH9K_HT_MACMODE_2040 &&
+ !ah->ah_config.cwm_ignore_extcca)
+ macmode = AR_2040_JOINED_RX_CLEAR;
+ else
+ macmode = 0;
- REG_WRITE(ah, AR_Q_TXD, 0);
- return wait != 0;
+ REG_WRITE(ah, AR_2040_MODE, macmode);
}
diff --git a/drivers/net/wireless/ath9k/hw.h b/drivers/net/wireless/ath9k/hw.h
index 2113818ee934..91d8f594af81 100644
--- a/drivers/net/wireless/ath9k/hw.h
+++ b/drivers/net/wireless/ath9k/hw.h
@@ -415,6 +415,9 @@ struct ar5416Stats {
#define AR5416_EEP_MINOR_VER_3 0x3
#define AR5416_EEP_MINOR_VER_7 0x7
#define AR5416_EEP_MINOR_VER_9 0x9
+#define AR5416_EEP_MINOR_VER_16 0x10
+#define AR5416_EEP_MINOR_VER_17 0x11
+#define AR5416_EEP_MINOR_VER_19 0x13
#define AR5416_NUM_5G_CAL_PIERS 8
#define AR5416_NUM_2G_CAL_PIERS 4
@@ -436,6 +439,27 @@ struct ar5416Stats {
#define AR5416_MAX_CHAINS 3
#define AR5416_PWR_TABLE_OFFSET -5
+/* Rx gain type values */
+#define AR5416_EEP_RXGAIN_23DB_BACKOFF 0
+#define AR5416_EEP_RXGAIN_13DB_BACKOFF 1
+#define AR5416_EEP_RXGAIN_ORIG 2
+
+/* Tx gain type values */
+#define AR5416_EEP_TXGAIN_ORIGINAL 0
+#define AR5416_EEP_TXGAIN_HIGH_POWER 1
+
+#define AR5416_EEP4K_START_LOC 64
+#define AR5416_EEP4K_NUM_2G_CAL_PIERS 3
+#define AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS 3
+#define AR5416_EEP4K_NUM_2G_20_TARGET_POWERS 3
+#define AR5416_EEP4K_NUM_2G_40_TARGET_POWERS 3
+#define AR5416_EEP4K_NUM_CTLS 12
+#define AR5416_EEP4K_NUM_BAND_EDGES 4
+#define AR5416_EEP4K_NUM_PD_GAINS 2
+#define AR5416_EEP4K_PD_GAINS_IN_MASK 4
+#define AR5416_EEP4K_PD_GAIN_ICEPTS 5
+#define AR5416_EEP4K_MAX_CHAINS 1
+
enum eeprom_param {
EEP_NFTHRESH_5,
EEP_NFTHRESH_2,
@@ -454,6 +478,8 @@ enum eeprom_param {
EEP_MINOR_REV,
EEP_TX_MASK,
EEP_RX_MASK,
+ EEP_RXGAIN_TYPE,
+ EEP_TXGAIN_TYPE,
};
enum ar5416_rates {
@@ -469,6 +495,11 @@ enum ar5416_rates {
Ar5416RateSize
};
+enum ath9k_hal_freq_band {
+ ATH9K_HAL_FREQ_BAND_5GHZ = 0,
+ ATH9K_HAL_FREQ_BAND_2GHZ = 1
+};
+
struct base_eep_header {
u16 length;
u16 checksum;
@@ -485,9 +516,32 @@ struct base_eep_header {
u32 binBuildNumber;
u8 deviceType;
u8 pwdclkind;
- u8 futureBase[32];
+ u8 futureBase_1[2];
+ u8 rxGainType;
+ u8 futureBase_2[3];
+ u8 txGainType;
+ u8 futureBase_3[25];
+} __packed;
+
+struct base_eep_header_4k {
+ u16 length;
+ u16 checksum;
+ u16 version;
+ u8 opCapFlags;
+ u8 eepMisc;
+ u16 regDmn[2];
+ u8 macAddr[6];
+ u8 rxMask;
+ u8 txMask;
+ u16 rfSilent;
+ u16 blueToothOptions;
+ u16 deviceCap;
+ u32 binBuildNumber;
+ u8 deviceType;
+ u8 futureBase[1];
} __packed;
+
struct spur_chan {
u16 spurChan;
u8 spurRangeLow;
@@ -540,11 +594,58 @@ struct modal_eep_header {
struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
} __packed;
+struct modal_eep_4k_header {
+ u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS];
+ u32 antCtrlCommon;
+ u8 antennaGainCh[AR5416_EEP4K_MAX_CHAINS];
+ u8 switchSettling;
+ u8 txRxAttenCh[AR5416_EEP4K_MAX_CHAINS];
+ u8 rxTxMarginCh[AR5416_EEP4K_MAX_CHAINS];
+ u8 adcDesiredSize;
+ u8 pgaDesiredSize;
+ u8 xlnaGainCh[AR5416_EEP4K_MAX_CHAINS];
+ u8 txEndToXpaOff;
+ u8 txEndToRxOn;
+ u8 txFrameToXpaOn;
+ u8 thresh62;
+ u8 noiseFloorThreshCh[AR5416_EEP4K_MAX_CHAINS];
+ u8 xpdGain;
+ u8 xpd;
+ u8 iqCalICh[AR5416_EEP4K_MAX_CHAINS];
+ u8 iqCalQCh[AR5416_EEP4K_MAX_CHAINS];
+ u8 pdGainOverlap;
+ u8 ob_01;
+ u8 db1_01;
+ u8 xpaBiasLvl;
+ u8 txFrameToDataStart;
+ u8 txFrameToPaOn;
+ u8 ht40PowerIncForPdadc;
+ u8 bswAtten[AR5416_EEP4K_MAX_CHAINS];
+ u8 bswMargin[AR5416_EEP4K_MAX_CHAINS];
+ u8 swSettleHt40;
+ u8 xatten2Db[AR5416_EEP4K_MAX_CHAINS];
+ u8 xatten2Margin[AR5416_EEP4K_MAX_CHAINS];
+ u8 db2_01;
+ u8 version;
+ u16 ob_234;
+ u16 db1_234;
+ u16 db2_234;
+ u8 futureModal[4];
+
+ struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS];
+} __packed;
+
+
struct cal_data_per_freq {
u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
u8 vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS];
} __packed;
+struct cal_data_per_freq_4k {
+ u8 pwrPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS];
+ u8 vpdPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS];
+} __packed;
+
struct cal_target_power_leg {
u8 bChannel;
u8 tPow2x[4];
@@ -555,6 +656,7 @@ struct cal_target_power_ht {
u8 tPow2x[8];
} __packed;
+
#ifdef __BIG_ENDIAN_BITFIELD
struct cal_ctl_edges {
u8 bChannel;
@@ -569,10 +671,15 @@ struct cal_ctl_edges {
struct cal_ctl_data {
struct cal_ctl_edges
- ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
+ ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES];
} __packed;
-struct ar5416_eeprom {
+struct cal_ctl_data_4k {
+ struct cal_ctl_edges
+ ctlEdges[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_BAND_EDGES];
+} __packed;
+
+struct ar5416_eeprom_def {
struct base_eep_header baseEepHeader;
u8 custData[64];
struct modal_eep_header modalHeader[2];
@@ -601,6 +708,26 @@ struct ar5416_eeprom {
u8 padding;
} __packed;
+struct ar5416_eeprom_4k {
+ struct base_eep_header_4k baseEepHeader;
+ u8 custData[20];
+ struct modal_eep_4k_header modalHeader;
+ u8 calFreqPier2G[AR5416_EEP4K_NUM_2G_CAL_PIERS];
+ struct cal_data_per_freq_4k
+ calPierData2G[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_2G_CAL_PIERS];
+ struct cal_target_power_leg
+ calTargetPowerCck[AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS];
+ struct cal_target_power_leg
+ calTargetPower2G[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS];
+ struct cal_target_power_ht
+ calTargetPower2GHT20[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS];
+ struct cal_target_power_ht
+ calTargetPower2GHT40[AR5416_EEP4K_NUM_2G_40_TARGET_POWERS];
+ u8 ctlIndex[AR5416_EEP4K_NUM_CTLS];
+ struct cal_ctl_data_4k ctlData[AR5416_EEP4K_NUM_CTLS];
+ u8 padding;
+} __packed;
+
struct ar5416IniArray {
u32 *ia_array;
u32 ia_rows;
@@ -668,9 +795,22 @@ struct hal_cal_list {
struct hal_cal_list *calNext;
};
+/*
+ * Enum to indentify the eeprom mappings
+ */
+enum hal_eep_map {
+ EEP_MAP_DEFAULT = 0x0,
+ EEP_MAP_4KBITS,
+ EEP_MAP_MAX
+};
+
+
struct ath_hal_5416 {
struct ath_hal ah;
- struct ar5416_eeprom ah_eeprom;
+ union {
+ struct ar5416_eeprom_def def;
+ struct ar5416_eeprom_4k map4k;
+ } ah_eeprom;
struct ar5416Stats ah_stats;
struct ath9k_tx_queue_info ah_txq[ATH9K_NUM_TX_QUEUES];
void __iomem *ah_cal_mem;
@@ -792,6 +932,10 @@ struct ath_hal_5416 {
struct ar5416IniArray ah_iniAddac;
struct ar5416IniArray ah_iniPcieSerdes;
struct ar5416IniArray ah_iniModesAdditional;
+ struct ar5416IniArray ah_iniModesRxGain;
+ struct ar5416IniArray ah_iniModesTxGain;
+ /* To indicate EEPROM mapping used */
+ enum hal_eep_map ah_eep_map;
};
#define AH5416(_ah) ((struct ath_hal_5416 *)(_ah))
@@ -833,13 +977,20 @@ struct ath_hal_5416 {
(AR_SREV_9100(ah)) ? 0x1fff1000 : 0x503f1200
#define AR5416_EEPROM_MAX 0xae0
#define ar5416_get_eep_ver(_ahp) \
- (((_ahp)->ah_eeprom.baseEepHeader.version >> 12) & 0xF)
+ (((_ahp)->ah_eeprom.def.baseEepHeader.version >> 12) & 0xF)
#define ar5416_get_eep_rev(_ahp) \
- (((_ahp)->ah_eeprom.baseEepHeader.version) & 0xFFF)
+ (((_ahp)->ah_eeprom.def.baseEepHeader.version) & 0xFFF)
#define ar5416_get_ntxchains(_txchainmask) \
(((_txchainmask >> 2) & 1) + \
((_txchainmask >> 1) & 1) + (_txchainmask & 1))
+/* EEPROM 4K bit map definations */
+#define ar5416_get_eep4k_ver(_ahp) \
+ (((_ahp)->ah_eeprom.map4k.baseEepHeader.version >> 12) & 0xF)
+#define ar5416_get_eep4k_rev(_ahp) \
+ (((_ahp)->ah_eeprom.map4k.baseEepHeader.version) & 0xFFF)
+
+
#ifdef __BIG_ENDIAN
#define AR5416_EEPROM_MAGIC 0x5aa5
#else
@@ -923,7 +1074,7 @@ struct ath_hal_5416 {
#define OFDM_PLCP_BITS_QUARTER 22
#define OFDM_SYMBOL_TIME_QUARTER 16
-u32 ath9k_hw_get_eeprom(struct ath_hal_5416 *ahp,
+u32 ath9k_hw_get_eeprom(struct ath_hal *ah,
enum eeprom_param param);
#endif
diff --git a/drivers/net/wireless/ath9k/initvals.h b/drivers/net/wireless/ath9k/initvals.h
index 3dd3815940a4..f3cfa16525e4 100644
--- a/drivers/net/wireless/ath9k/initvals.h
+++ b/drivers/net/wireless/ath9k/initvals.h
@@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+/* AR5416 to Fowl ar5146.ini */
static const u32 ar5416Modes_9100[][6] = {
{ 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
{ 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
@@ -31,17 +32,17 @@ static const u32 ar5416Modes_9100[][6] = {
{ 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
{ 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
{ 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
- { 0x00009850, 0x6de8b4e0, 0x6de8b4e0, 0x6de8b0de, 0x6de8b0de, 0x6de8b0de },
+ { 0x00009850, 0x6c48b4e0, 0x6c48b4e0, 0x6c48b0de, 0x6c48b0de, 0x6c48b0de },
{ 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e },
- { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e },
+ { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e },
{ 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 },
{ 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
{ 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 },
{ 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
- { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 },
+ { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
{ 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134 },
{ 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b },
- { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 },
+ { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 },
{ 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
{ 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
{ 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 },
@@ -207,7 +208,7 @@ static const u32 ar5416Common_9100[][2] = {
{ 0x00008134, 0x00000000 },
{ 0x00008138, 0x00000000 },
{ 0x0000813c, 0x00000000 },
- { 0x00008144, 0x00000000 },
+ { 0x00008144, 0xffffffff },
{ 0x00008168, 0x00000000 },
{ 0x0000816c, 0x00000000 },
{ 0x00008170, 0x32143320 },
@@ -266,7 +267,7 @@ static const u32 ar5416Common_9100[][2] = {
{ 0x0000832c, 0x00000007 },
{ 0x00008330, 0x00000302 },
{ 0x00008334, 0x00000e00 },
- { 0x00008338, 0x00000000 },
+ { 0x00008338, 0x00070000 },
{ 0x0000833c, 0x00000000 },
{ 0x00008340, 0x000107ff },
{ 0x00009808, 0x00000000 },
@@ -661,6 +662,7 @@ static const u32 ar5416Addac_9100[][2] = {
{0x000098c4, 0x00000000 },
};
+/* ar5416 - howl ar5416_howl.ini */
static const u32 ar5416Modes[][6] = {
{ 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
{ 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
@@ -952,7 +954,7 @@ static const u32 ar5416Common[][2] = {
{ 0x0000994c, 0x00020028 },
{ 0x0000c95c, 0x004b6a8e },
{ 0x0000c968, 0x000003ce },
- { 0x00009970, 0x190fb514 },
+ { 0x00009970, 0x190fb515 },
{ 0x00009974, 0x00000000 },
{ 0x00009978, 0x00000001 },
{ 0x0000997c, 0x00000000 },
@@ -1311,7 +1313,7 @@ static const u32 ar5416Addac[][2] = {
{0x000098cc, 0x00000000 },
};
-
+/* AR5416 9160 Sowl ar5416_sowl.ini */
static const u32 ar5416Modes_9160[][6] = {
{ 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
{ 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
@@ -1329,21 +1331,22 @@ static const u32 ar5416Modes_9160[][6] = {
{ 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
{ 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
{ 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 },
- { 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2, 0x6d48b0e2 },
+ { 0x00009850, 0x6c48b4e2, 0x6c48b4e2, 0x6c48b0e2, 0x6c48b0e2, 0x6c48b0e2 },
{ 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e },
- { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e },
+ { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e },
{ 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 },
{ 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
{ 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 },
{ 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 },
- { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 },
+ { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
{ 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
{ 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
- { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 },
+ { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 },
{ 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
{ 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
{ 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 },
{ 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 },
+ { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce },
{ 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 },
{ 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be },
{ 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
@@ -1505,7 +1508,7 @@ static const u32 ar5416Common_9160[][2] = {
{ 0x00008134, 0x00000000 },
{ 0x00008138, 0x00000000 },
{ 0x0000813c, 0x00000000 },
- { 0x00008144, 0x00000000 },
+ { 0x00008144, 0xffffffff },
{ 0x00008168, 0x00000000 },
{ 0x0000816c, 0x00000000 },
{ 0x00008170, 0x32143320 },
@@ -1564,7 +1567,7 @@ static const u32 ar5416Common_9160[][2] = {
{ 0x0000832c, 0x00000007 },
{ 0x00008330, 0x00000302 },
{ 0x00008334, 0x00000e00 },
- { 0x00008338, 0x00000000 },
+ { 0x00008338, 0x00ff0000 },
{ 0x0000833c, 0x00000000 },
{ 0x00008340, 0x000107ff },
{ 0x00009808, 0x00000000 },
@@ -1597,7 +1600,6 @@ static const u32 ar5416Common_9160[][2] = {
{ 0x00009958, 0x2108ecff },
{ 0x00009940, 0x00750604 },
{ 0x0000c95c, 0x004b6a8e },
- { 0x0000c968, 0x000003ce },
{ 0x00009970, 0x190fb515 },
{ 0x00009974, 0x00000000 },
{ 0x00009978, 0x00000001 },
@@ -1699,7 +1701,7 @@ static const u32 ar5416Common_9160[][2] = {
{ 0x0000a244, 0x00007bb6 },
{ 0x0000a248, 0x0fff3ffc },
{ 0x0000a24c, 0x00000001 },
- { 0x0000a250, 0x0000a000 },
+ { 0x0000a250, 0x0000e000 },
{ 0x0000a254, 0x00000000 },
{ 0x0000a258, 0x0cc75380 },
{ 0x0000a25c, 0x0f0f0f01 },
@@ -1719,7 +1721,7 @@ static const u32 ar5416Common_9160[][2] = {
{ 0x0000a34c, 0x3fffffff },
{ 0x0000a350, 0x3fffffff },
{ 0x0000a354, 0x0003ffff },
- { 0x0000a358, 0x79a8aa33 },
+ { 0x0000a358, 0x79bfaa03 },
{ 0x0000d35c, 0x07ffffef },
{ 0x0000d360, 0x0fffffe7 },
{ 0x0000d364, 0x17ffffe5 },
@@ -1842,7 +1844,6 @@ static const u32 ar5416Bank3_9160[][3] = {
};
static const u32 ar5416Bank6_9160[][3] = {
-
{ 0x0000989c, 0x00000000, 0x00000000 },
{ 0x0000989c, 0x00000000, 0x00000000 },
{ 0x0000989c, 0x00000000, 0x00000000 },
@@ -1920,7 +1921,6 @@ static const u32 ar5416Bank7_9160[][2] = {
{ 0x000098cc, 0x0000000e },
};
-
static u32 ar5416Addac_9160[][2] = {
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
@@ -1956,7 +1956,6 @@ static u32 ar5416Addac_9160[][2] = {
{0x000098cc, 0x00000000 },
};
-
static u32 ar5416Addac_91601_1[][2] = {
{0x0000989c, 0x00000000 },
{0x0000989c, 0x00000000 },
@@ -1992,8 +1991,7 @@ static u32 ar5416Addac_91601_1[][2] = {
{0x000098cc, 0x00000000 },
};
-
-
+/* XXX 9280 1 */
static const u32 ar9280Modes_9280[][6] = {
{ 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
{ 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
@@ -2543,9 +2541,7 @@ static const u32 ar9280Common_9280[][2] = {
{ 0x00007898, 0x2a850160 },
};
-
-
-
+/* XXX 9280 2 */
static const u32 ar9280Modes_9280_2[][6] = {
{ 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
{ 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
@@ -2560,26 +2556,24 @@ static const u32 ar9280Modes_9280_2[][6] = {
{ 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
{ 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
{ 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
- { 0x00009840, 0x206a012e, 0x206a012e, 0x206a022e, 0x206a022e, 0x206a022e },
+ { 0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e },
{ 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 },
- { 0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 },
- { 0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 },
- { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 },
- { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec88d2e, 0x7ec88d2e, 0x7ec88d2e },
- { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e },
+ { 0x00009850, 0x6c4000e2, 0x6c4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 },
+ { 0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
+ { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x3139605e, 0x31395d5e, 0x31395d5e },
{ 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 },
- { 0x0000c864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+ { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
{ 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
{ 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
- { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 },
+ { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
{ 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
- { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
- { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010 },
+ { 0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d },
+ { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010 },
{ 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
{ 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 },
{ 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 },
- { 0x0000c9b8, 0x0000000f, 0x0000000f, 0x0000001c, 0x0000001c, 0x0000001c },
- { 0x0000c9bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 },
+ { 0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c },
+ { 0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00 },
{ 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
{ 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
{ 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 },
@@ -2587,6 +2581,516 @@ static const u32 ar9280Modes_9280_2[][6] = {
{ 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
{ 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
{ 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 },
+ { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 },
+ { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 },
+ { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
+ { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
+ { 0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000 },
+ { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 },
+ { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },
+ { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 },
+};
+
+static const u32 ar9280Common_9280_2[][2] = {
+ { 0x0000000c, 0x00000000 },
+ { 0x00000030, 0x00020015 },
+ { 0x00000034, 0x00000005 },
+ { 0x00000040, 0x00000000 },
+ { 0x00000044, 0x00000008 },
+ { 0x00000048, 0x00000008 },
+ { 0x0000004c, 0x00000010 },
+ { 0x00000050, 0x00000000 },
+ { 0x00000054, 0x0000001f },
+ { 0x00000800, 0x00000000 },
+ { 0x00000804, 0x00000000 },
+ { 0x00000808, 0x00000000 },
+ { 0x0000080c, 0x00000000 },
+ { 0x00000810, 0x00000000 },
+ { 0x00000814, 0x00000000 },
+ { 0x00000818, 0x00000000 },
+ { 0x0000081c, 0x00000000 },
+ { 0x00000820, 0x00000000 },
+ { 0x00000824, 0x00000000 },
+ { 0x00001040, 0x002ffc0f },
+ { 0x00001044, 0x002ffc0f },
+ { 0x00001048, 0x002ffc0f },
+ { 0x0000104c, 0x002ffc0f },
+ { 0x00001050, 0x002ffc0f },
+ { 0x00001054, 0x002ffc0f },
+ { 0x00001058, 0x002ffc0f },
+ { 0x0000105c, 0x002ffc0f },
+ { 0x00001060, 0x002ffc0f },
+ { 0x00001064, 0x002ffc0f },
+ { 0x00001230, 0x00000000 },
+ { 0x00001270, 0x00000000 },
+ { 0x00001038, 0x00000000 },
+ { 0x00001078, 0x00000000 },
+ { 0x000010b8, 0x00000000 },
+ { 0x000010f8, 0x00000000 },
+ { 0x00001138, 0x00000000 },
+ { 0x00001178, 0x00000000 },
+ { 0x000011b8, 0x00000000 },
+ { 0x000011f8, 0x00000000 },
+ { 0x00001238, 0x00000000 },
+ { 0x00001278, 0x00000000 },
+ { 0x000012b8, 0x00000000 },
+ { 0x000012f8, 0x00000000 },
+ { 0x00001338, 0x00000000 },
+ { 0x00001378, 0x00000000 },
+ { 0x000013b8, 0x00000000 },
+ { 0x000013f8, 0x00000000 },
+ { 0x00001438, 0x00000000 },
+ { 0x00001478, 0x00000000 },
+ { 0x000014b8, 0x00000000 },
+ { 0x000014f8, 0x00000000 },
+ { 0x00001538, 0x00000000 },
+ { 0x00001578, 0x00000000 },
+ { 0x000015b8, 0x00000000 },
+ { 0x000015f8, 0x00000000 },
+ { 0x00001638, 0x00000000 },
+ { 0x00001678, 0x00000000 },
+ { 0x000016b8, 0x00000000 },
+ { 0x000016f8, 0x00000000 },
+ { 0x00001738, 0x00000000 },
+ { 0x00001778, 0x00000000 },
+ { 0x000017b8, 0x00000000 },
+ { 0x000017f8, 0x00000000 },
+ { 0x0000103c, 0x00000000 },
+ { 0x0000107c, 0x00000000 },
+ { 0x000010bc, 0x00000000 },
+ { 0x000010fc, 0x00000000 },
+ { 0x0000113c, 0x00000000 },
+ { 0x0000117c, 0x00000000 },
+ { 0x000011bc, 0x00000000 },
+ { 0x000011fc, 0x00000000 },
+ { 0x0000123c, 0x00000000 },
+ { 0x0000127c, 0x00000000 },
+ { 0x000012bc, 0x00000000 },
+ { 0x000012fc, 0x00000000 },
+ { 0x0000133c, 0x00000000 },
+ { 0x0000137c, 0x00000000 },
+ { 0x000013bc, 0x00000000 },
+ { 0x000013fc, 0x00000000 },
+ { 0x0000143c, 0x00000000 },
+ { 0x0000147c, 0x00000000 },
+ { 0x00004030, 0x00000002 },
+ { 0x0000403c, 0x00000002 },
+ { 0x00004024, 0x0000001f },
+ { 0x00004060, 0x00000000 },
+ { 0x00004064, 0x00000000 },
+ { 0x00007010, 0x00000033 },
+ { 0x00007034, 0x00000002 },
+ { 0x00007038, 0x000004c2 },
+ { 0x00008004, 0x00000000 },
+ { 0x00008008, 0x00000000 },
+ { 0x0000800c, 0x00000000 },
+ { 0x00008018, 0x00000700 },
+ { 0x00008020, 0x00000000 },
+ { 0x00008038, 0x00000000 },
+ { 0x0000803c, 0x00000000 },
+ { 0x00008048, 0x40000000 },
+ { 0x00008054, 0x00000000 },
+ { 0x00008058, 0x00000000 },
+ { 0x0000805c, 0x000fc78f },
+ { 0x00008060, 0x0000000f },
+ { 0x00008064, 0x00000000 },
+ { 0x00008070, 0x00000000 },
+ { 0x000080c0, 0x2a80001a },
+ { 0x000080c4, 0x05dc01e0 },
+ { 0x000080c8, 0x1f402710 },
+ { 0x000080cc, 0x01f40000 },
+ { 0x000080d0, 0x00001e00 },
+ { 0x000080d4, 0x00000000 },
+ { 0x000080d8, 0x00400000 },
+ { 0x000080e0, 0xffffffff },
+ { 0x000080e4, 0x0000ffff },
+ { 0x000080e8, 0x003f3f3f },
+ { 0x000080ec, 0x00000000 },
+ { 0x000080f0, 0x00000000 },
+ { 0x000080f4, 0x00000000 },
+ { 0x000080f8, 0x00000000 },
+ { 0x000080fc, 0x00020000 },
+ { 0x00008100, 0x00020000 },
+ { 0x00008104, 0x00000001 },
+ { 0x00008108, 0x00000052 },
+ { 0x0000810c, 0x00000000 },
+ { 0x00008110, 0x00000168 },
+ { 0x00008118, 0x000100aa },
+ { 0x0000811c, 0x00003210 },
+ { 0x00008120, 0x08f04800 },
+ { 0x00008124, 0x00000000 },
+ { 0x00008128, 0x00000000 },
+ { 0x0000812c, 0x00000000 },
+ { 0x00008130, 0x00000000 },
+ { 0x00008134, 0x00000000 },
+ { 0x00008138, 0x00000000 },
+ { 0x0000813c, 0x00000000 },
+ { 0x00008144, 0xffffffff },
+ { 0x00008168, 0x00000000 },
+ { 0x0000816c, 0x00000000 },
+ { 0x00008170, 0x32143320 },
+ { 0x00008174, 0xfaa4fa50 },
+ { 0x00008178, 0x00000100 },
+ { 0x0000817c, 0x00000000 },
+ { 0x000081c0, 0x00000000 },
+ { 0x000081d0, 0x00003210 },
+ { 0x000081ec, 0x00000000 },
+ { 0x000081f0, 0x00000000 },
+ { 0x000081f4, 0x00000000 },
+ { 0x000081f8, 0x00000000 },
+ { 0x000081fc, 0x00000000 },
+ { 0x00008200, 0x00000000 },
+ { 0x00008204, 0x00000000 },
+ { 0x00008208, 0x00000000 },
+ { 0x0000820c, 0x00000000 },
+ { 0x00008210, 0x00000000 },
+ { 0x00008214, 0x00000000 },
+ { 0x00008218, 0x00000000 },
+ { 0x0000821c, 0x00000000 },
+ { 0x00008220, 0x00000000 },
+ { 0x00008224, 0x00000000 },
+ { 0x00008228, 0x00000000 },
+ { 0x0000822c, 0x00000000 },
+ { 0x00008230, 0x00000000 },
+ { 0x00008234, 0x00000000 },
+ { 0x00008238, 0x00000000 },
+ { 0x0000823c, 0x00000000 },
+ { 0x00008240, 0x00100000 },
+ { 0x00008244, 0x0010f400 },
+ { 0x00008248, 0x00000100 },
+ { 0x0000824c, 0x0001e800 },
+ { 0x00008250, 0x00000000 },
+ { 0x00008254, 0x00000000 },
+ { 0x00008258, 0x00000000 },
+ { 0x0000825c, 0x400000ff },
+ { 0x00008260, 0x00080922 },
+ { 0x00008264, 0xa8a00010 },
+ { 0x00008270, 0x00000000 },
+ { 0x00008274, 0x40000000 },
+ { 0x00008278, 0x003e4180 },
+ { 0x0000827c, 0x00000000 },
+ { 0x00008284, 0x0000002c },
+ { 0x00008288, 0x0000002c },
+ { 0x0000828c, 0x00000000 },
+ { 0x00008294, 0x00000000 },
+ { 0x00008298, 0x00000000 },
+ { 0x0000829c, 0x00000000 },
+ { 0x00008300, 0x00000040 },
+ { 0x00008314, 0x00000000 },
+ { 0x00008328, 0x00000000 },
+ { 0x0000832c, 0x00000007 },
+ { 0x00008330, 0x00000302 },
+ { 0x00008334, 0x00000e00 },
+ { 0x00008338, 0x00ff0000 },
+ { 0x0000833c, 0x00000000 },
+ { 0x00008340, 0x000107ff },
+ { 0x00008344, 0x00581043 },
+ { 0x00009808, 0x00000000 },
+ { 0x0000980c, 0xafa68e30 },
+ { 0x00009810, 0xfd14e000 },
+ { 0x00009814, 0x9c0a9f6b },
+ { 0x0000981c, 0x00000000 },
+ { 0x0000982c, 0x0000a000 },
+ { 0x00009830, 0x00000000 },
+ { 0x0000983c, 0x00200400 },
+ { 0x0000984c, 0x0040233c },
+ { 0x0000a84c, 0x0040233c },
+ { 0x00009854, 0x00000044 },
+ { 0x00009900, 0x00000000 },
+ { 0x00009904, 0x00000000 },
+ { 0x00009908, 0x00000000 },
+ { 0x0000990c, 0x00000000 },
+ { 0x00009910, 0x01002310 },
+ { 0x0000991c, 0x10000fff },
+ { 0x00009920, 0x04900000 },
+ { 0x0000a920, 0x04900000 },
+ { 0x00009928, 0x00000001 },
+ { 0x0000992c, 0x00000004 },
+ { 0x00009934, 0x1e1f2022 },
+ { 0x00009938, 0x0a0b0c0d },
+ { 0x0000993c, 0x00000000 },
+ { 0x00009948, 0x9280c00a },
+ { 0x0000994c, 0x00020028 },
+ { 0x00009954, 0x5f3ca3de },
+ { 0x00009958, 0x2108ecff },
+ { 0x00009940, 0x14750604 },
+ { 0x0000c95c, 0x004b6a8e },
+ { 0x00009968, 0x000003ce },
+ { 0x00009970, 0x190fb515 },
+ { 0x00009974, 0x00000000 },
+ { 0x00009978, 0x00000001 },
+ { 0x0000997c, 0x00000000 },
+ { 0x00009980, 0x00000000 },
+ { 0x00009984, 0x00000000 },
+ { 0x00009988, 0x00000000 },
+ { 0x0000998c, 0x00000000 },
+ { 0x00009990, 0x00000000 },
+ { 0x00009994, 0x00000000 },
+ { 0x00009998, 0x00000000 },
+ { 0x0000999c, 0x00000000 },
+ { 0x000099a0, 0x00000000 },
+ { 0x000099a4, 0x00000001 },
+ { 0x000099a8, 0x201fff00 },
+ { 0x000099ac, 0x006f0000 },
+ { 0x000099b0, 0x03051000 },
+ { 0x000099b4, 0x00000820 },
+ { 0x000099dc, 0x00000000 },
+ { 0x000099e0, 0x00000000 },
+ { 0x000099e4, 0xaaaaaaaa },
+ { 0x000099e8, 0x3c466478 },
+ { 0x000099ec, 0x0cc80caa },
+ { 0x000099f0, 0x00000000 },
+ { 0x000099fc, 0x00001042 },
+ { 0x0000a208, 0x803e4788 },
+ { 0x0000a210, 0x4080a333 },
+ { 0x0000a214, 0x40206c10 },
+ { 0x0000a218, 0x009c4060 },
+ { 0x0000a220, 0x01834061 },
+ { 0x0000a224, 0x00000400 },
+ { 0x0000a228, 0x000003b5 },
+ { 0x0000a22c, 0x233f7180 },
+ { 0x0000a234, 0x20202020 },
+ { 0x0000a238, 0x20202020 },
+ { 0x0000a23c, 0x13c88000 },
+ { 0x0000a240, 0x38490a20 },
+ { 0x0000a244, 0x00007bb6 },
+ { 0x0000a248, 0x0fff3ffc },
+ { 0x0000a24c, 0x00000000 },
+ { 0x0000a254, 0x00000000 },
+ { 0x0000a258, 0x0cdbd380 },
+ { 0x0000a25c, 0x0f0f0f01 },
+ { 0x0000a260, 0xdfa91f01 },
+ { 0x0000a268, 0x00000000 },
+ { 0x0000a26c, 0x0ebae9c6 },
+ { 0x0000b26c, 0x0ebae9c6 },
+ { 0x0000d270, 0x00820820 },
+ { 0x0000a278, 0x1ce739ce },
+ { 0x0000d35c, 0x07ffffef },
+ { 0x0000d360, 0x0fffffe7 },
+ { 0x0000d364, 0x17ffffe5 },
+ { 0x0000d368, 0x1fffffe4 },
+ { 0x0000d36c, 0x37ffffe3 },
+ { 0x0000d370, 0x3fffffe3 },
+ { 0x0000d374, 0x57ffffe3 },
+ { 0x0000d378, 0x5fffffe2 },
+ { 0x0000d37c, 0x7fffffe2 },
+ { 0x0000d380, 0x7f3c7bba },
+ { 0x0000d384, 0xf3307ff0 },
+ { 0x0000a388, 0x0c000000 },
+ { 0x0000a38c, 0x20202020 },
+ { 0x0000a390, 0x20202020 },
+ { 0x0000a394, 0x1ce739ce },
+ { 0x0000a398, 0x000001ce },
+ { 0x0000a39c, 0x00000001 },
+ { 0x0000a3a0, 0x00000000 },
+ { 0x0000a3a4, 0x00000000 },
+ { 0x0000a3a8, 0x00000000 },
+ { 0x0000a3ac, 0x00000000 },
+ { 0x0000a3b0, 0x00000000 },
+ { 0x0000a3b4, 0x00000000 },
+ { 0x0000a3b8, 0x00000000 },
+ { 0x0000a3bc, 0x00000000 },
+ { 0x0000a3c0, 0x00000000 },
+ { 0x0000a3c4, 0x00000000 },
+ { 0x0000a3c8, 0x00000246 },
+ { 0x0000a3cc, 0x20202020 },
+ { 0x0000a3d0, 0x20202020 },
+ { 0x0000a3d4, 0x20202020 },
+ { 0x0000a3dc, 0x1ce739ce },
+ { 0x0000a3e0, 0x000001ce },
+ { 0x0000a3e4, 0x00000000 },
+ { 0x0000a3e8, 0x18c43433 },
+ { 0x0000a3ec, 0x00f70081 },
+ { 0x00007800, 0x00040000 },
+ { 0x00007804, 0xdb005012 },
+ { 0x00007808, 0x04924914 },
+ { 0x0000780c, 0x21084210 },
+ { 0x00007810, 0x6d801300 },
+ { 0x00007818, 0x07e41000 },
+ { 0x0000781c, 0x00392000 },
+ { 0x00007820, 0x92592480 },
+ { 0x00007824, 0x00040000 },
+ { 0x00007828, 0xdb005012 },
+ { 0x0000782c, 0x04924914 },
+ { 0x00007830, 0x21084210 },
+ { 0x00007834, 0x6d801300 },
+ { 0x0000783c, 0x07e40000 },
+ { 0x00007840, 0x00392000 },
+ { 0x00007844, 0x92592480 },
+ { 0x00007848, 0x00100000 },
+ { 0x0000784c, 0x773f0567 },
+ { 0x00007850, 0x54214514 },
+ { 0x00007854, 0x12035828 },
+ { 0x00007858, 0x9259269a },
+ { 0x00007860, 0x52802000 },
+ { 0x00007864, 0x0a8e370e },
+ { 0x00007868, 0xc0102850 },
+ { 0x0000786c, 0x812d4000 },
+ { 0x00007870, 0x807ec400 },
+ { 0x00007874, 0x001b6db0 },
+ { 0x00007878, 0x00376b63 },
+ { 0x0000787c, 0x06db6db6 },
+ { 0x00007880, 0x006d8000 },
+ { 0x00007884, 0xffeffffe },
+ { 0x00007888, 0xffeffffe },
+ { 0x0000788c, 0x00010000 },
+ { 0x00007890, 0x02060aeb },
+ { 0x00007898, 0x2a850160 },
+};
+
+static const u32 ar9280Modes_fast_clock_9280_2[][3] = {
+ { 0x00001030, 0x00000268, 0x000004d0 },
+ { 0x00001070, 0x0000018c, 0x00000318 },
+ { 0x000010b0, 0x00000fd0, 0x00001fa0 },
+ { 0x00008014, 0x044c044c, 0x08980898 },
+ { 0x0000801c, 0x148ec02b, 0x148ec057 },
+ { 0x00008318, 0x000044c0, 0x00008980 },
+ { 0x00009820, 0x02020200, 0x02020200 },
+ { 0x00009824, 0x00000f0f, 0x00000f0f },
+ { 0x00009828, 0x0b020001, 0x0b020001 },
+ { 0x00009834, 0x00000f0f, 0x00000f0f },
+ { 0x00009844, 0x03721821, 0x03721821 },
+ { 0x00009914, 0x00000898, 0x00001130 },
+ { 0x00009918, 0x0000000b, 0x00000016 },
+ { 0x00009944, 0xdfbc1210, 0xdfbc1210 },
+};
+
+static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = {
+ { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 },
+ { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 },
+ { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 },
+ { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 },
+ { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c },
+ { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 },
+ { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 },
+ { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 },
+ { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c },
+ { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 },
+ { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 },
+ { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 },
+ { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c },
+ { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 },
+ { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 },
+ { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 },
+ { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c },
+ { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 },
+ { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 },
+ { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 },
+ { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 },
+ { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 },
+ { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c },
+ { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 },
+ { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
+ { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
+ { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
+ { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
+ { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
+ { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
+ { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
+ { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
+ { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
+ { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
+ { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
+ { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
+ { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
+ { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
+ { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
+ { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
+ { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
+ { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
+ { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
+ { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
+ { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
+ { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
+ { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
+ { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
+ { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10, 0x00008b10 },
+ { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b14, 0x00008b14, 0x00008b14 },
+ { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b01, 0x00008b01, 0x00008b01 },
+ { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b05, 0x00008b05, 0x00008b05 },
+ { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b09, 0x00008b09, 0x00008b09 },
+ { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b0d, 0x00008b0d, 0x00008b0d },
+ { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b11, 0x00008b11, 0x00008b11 },
+ { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008b15, 0x00008b15, 0x00008b15 },
+ { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008b02, 0x00008b02, 0x00008b02 },
+ { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008b06, 0x00008b06, 0x00008b06 },
+ { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00008b0a, 0x00008b0a, 0x00008b0a },
+ { 0x00009aec, 0x0000b784, 0x0000b784, 0x00008b0e, 0x00008b0e, 0x00008b0e },
+ { 0x00009af0, 0x0000b788, 0x0000b788, 0x00008b12, 0x00008b12, 0x00008b12 },
+ { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008b16, 0x00008b16, 0x00008b16 },
+ { 0x00009af8, 0x0000b790, 0x0000b790, 0x00008b03, 0x00008b03, 0x00008b03 },
+ { 0x00009afc, 0x0000b794, 0x0000b794, 0x00008b07, 0x00008b07, 0x00008b07 },
+ { 0x00009b00, 0x0000b798, 0x0000b798, 0x00008b0b, 0x00008b0b, 0x00008b0b },
+ { 0x00009b04, 0x0000d784, 0x0000d784, 0x00008b0f, 0x00008b0f, 0x00008b0f },
+ { 0x00009b08, 0x0000d788, 0x0000d788, 0x00008b13, 0x00008b13, 0x00008b13 },
+ { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008b17, 0x00008b17, 0x00008b17 },
+ { 0x00009b10, 0x0000d790, 0x0000d790, 0x00008b23, 0x00008b23, 0x00008b23 },
+ { 0x00009b14, 0x0000f780, 0x0000f780, 0x00008b27, 0x00008b27, 0x00008b27 },
+ { 0x00009b18, 0x0000f784, 0x0000f784, 0x00008b2b, 0x00008b2b, 0x00008b2b },
+ { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00008b2f, 0x00008b2f, 0x00008b2f },
+ { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008b33, 0x00008b33, 0x00008b33 },
+ { 0x00009b24, 0x0000f790, 0x0000f790, 0x00008b37, 0x00008b37, 0x00008b37 },
+ { 0x00009b28, 0x0000f794, 0x0000f794, 0x00008b43, 0x00008b43, 0x00008b43 },
+ { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008b47, 0x00008b47, 0x00008b47 },
+ { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008b4b, 0x00008b4b, 0x00008b4b },
+ { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008b4f, 0x00008b4f, 0x00008b4f },
+ { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008b53, 0x00008b53, 0x00008b53 },
+ { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008b57, 0x00008b57, 0x00008b57 },
+ { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b },
+ { 0x00009848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 },
+ { 0x0000a848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 },
+};
+
+static const u32 ar9280Modes_original_rxgain_9280_2[][6] = {
{ 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 },
{ 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 },
{ 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 },
@@ -2715,14 +3219,172 @@ static const u32 ar9280Modes_9280_2[][6] = {
{ 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
{ 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
{ 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db },
- { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 },
- { 0x0000a208, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788 },
- { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 },
- { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 },
- { 0x0000a21c, 0x1463800a, 0x1463800a, 0x1463800a, 0x1463800a, 0x1463800a },
- { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
- { 0x0000a250, 0x001ff000, 0x001ff000, 0x001da000, 0x001da000, 0x001da000 },
- { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 },
+ { 0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 },
+ { 0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 },
+};
+
+static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = {
+ { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 },
+ { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 },
+ { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 },
+ { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 },
+ { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c },
+ { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 },
+ { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 },
+ { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 },
+ { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c },
+ { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 },
+ { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 },
+ { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 },
+ { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c },
+ { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 },
+ { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 },
+ { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 },
+ { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c },
+ { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 },
+ { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 },
+ { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 },
+ { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 },
+ { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 },
+ { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c },
+ { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 },
+ { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 },
+ { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 },
+ { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c },
+ { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 },
+ { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 },
+ { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 },
+ { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 },
+ { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 },
+ { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 },
+ { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 },
+ { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 },
+ { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c },
+ { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 },
+ { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 },
+ { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 },
+ { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 },
+ { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 },
+ { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c },
+ { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 },
+ { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 },
+ { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 },
+ { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 },
+ { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 },
+ { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c },
+ { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 },
+ { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 },
+ { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 },
+ { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c },
+ { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 },
+ { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 },
+ { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 },
+ { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 },
+ { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c },
+ { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 },
+ { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310, 0x00009310 },
+ { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314, 0x00009314 },
+ { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320, 0x00009320 },
+ { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324, 0x00009324 },
+ { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328, 0x00009328 },
+ { 0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c, 0x0000932c },
+ { 0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330, 0x00009330 },
+ { 0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334, 0x00009334 },
+ { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321, 0x00009321 },
+ { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325, 0x00009325 },
+ { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329, 0x00009329 },
+ { 0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d, 0x0000932d },
+ { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331, 0x00009331 },
+ { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335, 0x00009335 },
+ { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322, 0x00009322 },
+ { 0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326, 0x00009326 },
+ { 0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a, 0x0000932a },
+ { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e, 0x0000932e },
+ { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332, 0x00009332 },
+ { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336, 0x00009336 },
+ { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323, 0x00009323 },
+ { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327, 0x00009327 },
+ { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b, 0x0000932b },
+ { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f, 0x0000932f },
+ { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333, 0x00009333 },
+ { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337, 0x00009337 },
+ { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343, 0x00009343 },
+ { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347, 0x00009347 },
+ { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b, 0x0000934b },
+ { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f, 0x0000934f },
+ { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353, 0x00009353 },
+ { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357, 0x00009357 },
+ { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b },
+ { 0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a },
+ { 0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a },
+};
+
+static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = {
+ { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002 },
+ { 0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008 },
+ { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010, 0x0000c010 },
+ { 0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012, 0x00010012 },
+ { 0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014, 0x00013014 },
+ { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a, 0x0001820a },
+ { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211, 0x0001b211 },
+ { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 },
+ { 0x0000a324, 0x00020092, 0x00020092, 0x00022411, 0x00022411, 0x00022411 },
+ { 0x0000a328, 0x0002410a, 0x0002410a, 0x00025413, 0x00025413, 0x00025413 },
+ { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00029811, 0x00029811, 0x00029811 },
+ { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002c813, 0x0002c813, 0x0002c813 },
+ { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030a14, 0x00030a14, 0x00030a14 },
+ { 0x0000a338, 0x000321ec, 0x000321ec, 0x00035a50, 0x00035a50, 0x00035a50 },
+ { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00039c4c, 0x00039c4c, 0x00039c4c },
+ { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003de8a, 0x0003de8a, 0x0003de8a },
+ { 0x0000a344, 0x000321ec, 0x000321ec, 0x00042e92, 0x00042e92, 0x00042e92 },
+ { 0x0000a348, 0x000321ec, 0x000321ec, 0x00046ed2, 0x00046ed2, 0x00046ed2 },
+ { 0x0000a34c, 0x000321ec, 0x000321ec, 0x0004bed5, 0x0004bed5, 0x0004bed5 },
+ { 0x0000a350, 0x000321ec, 0x000321ec, 0x0004ff54, 0x0004ff54, 0x0004ff54 },
+ { 0x0000a354, 0x000321ec, 0x000321ec, 0x00053fd5, 0x00053fd5, 0x00053fd5 },
+ { 0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff },
+ { 0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff },
+ { 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce },
+};
+
+static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = {
{ 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
{ 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 },
{ 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 },
@@ -2745,14 +3407,363 @@ static const u32 ar9280Modes_9280_2[][6] = {
{ 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a },
{ 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 },
{ 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 },
+ { 0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff },
+ { 0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff },
+ { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce },
+};
+
+static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = {
+ {0x00004040, 0x9248fd00 },
+ {0x00004040, 0x24924924 },
+ {0x00004040, 0xa8000019 },
+ {0x00004040, 0x13160820 },
+ {0x00004040, 0xe5980560 },
+ {0x00004040, 0xc01dcffc },
+ {0x00004040, 0x1aaabe41 },
+ {0x00004040, 0xbe105554 },
+ {0x00004040, 0x00043007 },
+ {0x00004044, 0x00000000 },
+};
+
+static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = {
+ {0x00004040, 0x9248fd00 },
+ {0x00004040, 0x24924924 },
+ {0x00004040, 0xa8000019 },
+ {0x00004040, 0x13160820 },
+ {0x00004040, 0xe5980560 },
+ {0x00004040, 0xc01dcffd },
+ {0x00004040, 0x1aaabe41 },
+ {0x00004040, 0xbe105554 },
+ {0x00004040, 0x00043007 },
+ {0x00004044, 0x00000000 },
+};
+
+/* AR9285 */
+static const u_int32_t ar9285Modes_9285[][6] = {
+ { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
+ { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
+ { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
+ { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 },
+ { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
+ { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f },
+ { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 },
+ { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
+ { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
+ { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+ { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
+ { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+ { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
+ { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e },
+ { 0x00009844, 0x0372161e, 0x0372161e, 0x03720020, 0x03720020, 0x037216a0 },
+ { 0x00009848, 0x00001066, 0x00001066, 0x0000004e, 0x0000004e, 0x00001059 },
+ { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 },
+ { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
+ { 0x0000985c, 0x3139605e, 0x3139605e, 0x3136605e, 0x3136605e, 0x3139605e },
+ { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 },
+ { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+ { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
+ { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
+ { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
+ { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
+ { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d },
+ { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1020, 0xdfbc1020, 0xdfbc1010 },
+ { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x000099b8, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c },
+ { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 },
+ { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
+ { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
+ { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 },
+ { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
+ { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
+ { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00009a00, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 },
+ { 0x00009a04, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 },
+ { 0x00009a08, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 },
+ { 0x00009a0c, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 },
+ { 0x00009a10, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 },
+ { 0x00009a14, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 },
+ { 0x00009a18, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 },
+ { 0x00009a1c, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 },
+ { 0x00009a20, 0x00000000, 0x00000000, 0x00068114, 0x00068114, 0x00000000 },
+ { 0x00009a24, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 },
+ { 0x00009a28, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 },
+ { 0x00009a2c, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 },
+ { 0x00009a30, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 },
+ { 0x00009a34, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 },
+ { 0x00009a38, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 },
+ { 0x00009a3c, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 },
+ { 0x00009a40, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 },
+ { 0x00009a44, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 },
+ { 0x00009a48, 0x00000000, 0x00000000, 0x00068284, 0x00068284, 0x00000000 },
+ { 0x00009a4c, 0x00000000, 0x00000000, 0x00068288, 0x00068288, 0x00000000 },
+ { 0x00009a50, 0x00000000, 0x00000000, 0x00068220, 0x00068220, 0x00000000 },
+ { 0x00009a54, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 },
+ { 0x00009a58, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 },
+ { 0x00009a5c, 0x00000000, 0x00000000, 0x00068304, 0x00068304, 0x00000000 },
+ { 0x00009a60, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 },
+ { 0x00009a64, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 },
+ { 0x00009a68, 0x00000000, 0x00000000, 0x00068380, 0x00068380, 0x00000000 },
+ { 0x00009a6c, 0x00000000, 0x00000000, 0x00068384, 0x00068384, 0x00000000 },
+ { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 },
+ { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 },
+ { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 },
+ { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 },
+ { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 },
+ { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 },
+ { 0x00009a88, 0x00000000, 0x00000000, 0x00068b04, 0x00068b04, 0x00000000 },
+ { 0x00009a8c, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 },
+ { 0x00009a90, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 },
+ { 0x00009a94, 0x00000000, 0x00000000, 0x00068b0c, 0x00068b0c, 0x00000000 },
+ { 0x00009a98, 0x00000000, 0x00000000, 0x00068b80, 0x00068b80, 0x00000000 },
+ { 0x00009a9c, 0x00000000, 0x00000000, 0x00068b84, 0x00068b84, 0x00000000 },
+ { 0x00009aa0, 0x00000000, 0x00000000, 0x00068b88, 0x00068b88, 0x00000000 },
+ { 0x00009aa4, 0x00000000, 0x00000000, 0x00068b8c, 0x00068b8c, 0x00000000 },
+ { 0x00009aa8, 0x00000000, 0x00000000, 0x000b8b90, 0x000b8b90, 0x00000000 },
+ { 0x00009aac, 0x00000000, 0x00000000, 0x000b8f80, 0x000b8f80, 0x00000000 },
+ { 0x00009ab0, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 },
+ { 0x00009ab4, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 },
+ { 0x00009ab8, 0x00000000, 0x00000000, 0x000b8f8c, 0x000b8f8c, 0x00000000 },
+ { 0x00009abc, 0x00000000, 0x00000000, 0x000b8f90, 0x000b8f90, 0x00000000 },
+ { 0x00009ac0, 0x00000000, 0x00000000, 0x000bb30c, 0x000bb30c, 0x00000000 },
+ { 0x00009ac4, 0x00000000, 0x00000000, 0x000bb310, 0x000bb310, 0x00000000 },
+ { 0x00009ac8, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 },
+ { 0x00009acc, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 },
+ { 0x00009ad0, 0x00000000, 0x00000000, 0x000bb324, 0x000bb324, 0x00000000 },
+ { 0x00009ad4, 0x00000000, 0x00000000, 0x000bb704, 0x000bb704, 0x00000000 },
+ { 0x00009ad8, 0x00000000, 0x00000000, 0x000f96a4, 0x000f96a4, 0x00000000 },
+ { 0x00009adc, 0x00000000, 0x00000000, 0x000f96a8, 0x000f96a8, 0x00000000 },
+ { 0x00009ae0, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 },
+ { 0x00009ae4, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 },
+ { 0x00009ae8, 0x00000000, 0x00000000, 0x000f9720, 0x000f9720, 0x00000000 },
+ { 0x00009aec, 0x00000000, 0x00000000, 0x000f9724, 0x000f9724, 0x00000000 },
+ { 0x00009af0, 0x00000000, 0x00000000, 0x000f9728, 0x000f9728, 0x00000000 },
+ { 0x00009af4, 0x00000000, 0x00000000, 0x000f972c, 0x000f972c, 0x00000000 },
+ { 0x00009af8, 0x00000000, 0x00000000, 0x000f97a0, 0x000f97a0, 0x00000000 },
+ { 0x00009afc, 0x00000000, 0x00000000, 0x000f97a4, 0x000f97a4, 0x00000000 },
+ { 0x00009b00, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 },
+ { 0x00009b04, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 },
+ { 0x00009b08, 0x00000000, 0x00000000, 0x000fb7b4, 0x000fb7b4, 0x00000000 },
+ { 0x00009b0c, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 },
+ { 0x00009b10, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 },
+ { 0x00009b14, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 },
+ { 0x00009b18, 0x00000000, 0x00000000, 0x000fb7ad, 0x000fb7ad, 0x00000000 },
+ { 0x00009b1c, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 },
+ { 0x00009b20, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 },
+ { 0x00009b24, 0x00000000, 0x00000000, 0x000fb7b9, 0x000fb7b9, 0x00000000 },
+ { 0x00009b28, 0x00000000, 0x00000000, 0x000fb7c5, 0x000fb7c5, 0x00000000 },
+ { 0x00009b2c, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 },
+ { 0x00009b30, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 },
+ { 0x00009b34, 0x00000000, 0x00000000, 0x000fb7d5, 0x000fb7d5, 0x00000000 },
+ { 0x00009b38, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 },
+ { 0x00009b3c, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 },
+ { 0x00009b40, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 },
+ { 0x00009b44, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 },
+ { 0x00009b48, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 },
+ { 0x00009b4c, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 },
+ { 0x00009b50, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 },
+ { 0x00009b54, 0x00000000, 0x00000000, 0x000fb7c7, 0x000fb7c7, 0x00000000 },
+ { 0x00009b58, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 },
+ { 0x00009b5c, 0x00000000, 0x00000000, 0x000fb7cf, 0x000fb7cf, 0x00000000 },
+ { 0x00009b60, 0x00000000, 0x00000000, 0x000fb7d7, 0x000fb7d7, 0x00000000 },
+ { 0x00009b64, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b68, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b6c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b70, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b74, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b78, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b7c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b80, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b84, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b88, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b8c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b90, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b94, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b98, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b9c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009ba0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009ba4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009ba8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bac, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bb0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bb4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bb8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bbc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bc0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bc4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bc8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bcc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bd0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bd4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bd8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bdc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009be0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009be4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009be8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bec, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bf0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bf4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bf8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bfc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x0000aa00, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c, 0x00000000 },
+ { 0x0000aa04, 0x00000000, 0x00000000, 0x00068080, 0x00068080, 0x00000000 },
+ { 0x0000aa08, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 },
+ { 0x0000aa0c, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 },
+ { 0x0000aa10, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 },
+ { 0x0000aa14, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 },
+ { 0x0000aa18, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 },
+ { 0x0000aa1c, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 },
+ { 0x0000aa20, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 },
+ { 0x0000aa24, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 },
+ { 0x0000aa28, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 },
+ { 0x0000aa2c, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 },
+ { 0x0000aa30, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 },
+ { 0x0000aa34, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 },
+ { 0x0000aa38, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 },
+ { 0x0000aa3c, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 },
+ { 0x0000aa40, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 },
+ { 0x0000aa44, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 },
+ { 0x0000aa48, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 },
+ { 0x0000aa4c, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 },
+ { 0x0000aa50, 0x00000000, 0x00000000, 0x000681ac, 0x000681ac, 0x00000000 },
+ { 0x0000aa54, 0x00000000, 0x00000000, 0x0006821c, 0x0006821c, 0x00000000 },
+ { 0x0000aa58, 0x00000000, 0x00000000, 0x00068224, 0x00068224, 0x00000000 },
+ { 0x0000aa5c, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 },
+ { 0x0000aa60, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 },
+ { 0x0000aa64, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 },
+ { 0x0000aa68, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 },
+ { 0x0000aa6c, 0x00000000, 0x00000000, 0x00068310, 0x00068310, 0x00000000 },
+ { 0x0000aa70, 0x00000000, 0x00000000, 0x00068788, 0x00068788, 0x00000000 },
+ { 0x0000aa74, 0x00000000, 0x00000000, 0x0006878c, 0x0006878c, 0x00000000 },
+ { 0x0000aa78, 0x00000000, 0x00000000, 0x00068790, 0x00068790, 0x00000000 },
+ { 0x0000aa7c, 0x00000000, 0x00000000, 0x00068794, 0x00068794, 0x00000000 },
+ { 0x0000aa80, 0x00000000, 0x00000000, 0x00068798, 0x00068798, 0x00000000 },
+ { 0x0000aa84, 0x00000000, 0x00000000, 0x0006879c, 0x0006879c, 0x00000000 },
+ { 0x0000aa88, 0x00000000, 0x00000000, 0x00068b89, 0x00068b89, 0x00000000 },
+ { 0x0000aa8c, 0x00000000, 0x00000000, 0x00068b8d, 0x00068b8d, 0x00000000 },
+ { 0x0000aa90, 0x00000000, 0x00000000, 0x00068b91, 0x00068b91, 0x00000000 },
+ { 0x0000aa94, 0x00000000, 0x00000000, 0x00068b95, 0x00068b95, 0x00000000 },
+ { 0x0000aa98, 0x00000000, 0x00000000, 0x00068b99, 0x00068b99, 0x00000000 },
+ { 0x0000aa9c, 0x00000000, 0x00000000, 0x00068ba5, 0x00068ba5, 0x00000000 },
+ { 0x0000aaa0, 0x00000000, 0x00000000, 0x00068ba9, 0x00068ba9, 0x00000000 },
+ { 0x0000aaa4, 0x00000000, 0x00000000, 0x00068bad, 0x00068bad, 0x00000000 },
+ { 0x0000aaa8, 0x00000000, 0x00000000, 0x000b8b0c, 0x000b8b0c, 0x00000000 },
+ { 0x0000aaac, 0x00000000, 0x00000000, 0x000b8f10, 0x000b8f10, 0x00000000 },
+ { 0x0000aab0, 0x00000000, 0x00000000, 0x000b8f14, 0x000b8f14, 0x00000000 },
+ { 0x0000aab4, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 },
+ { 0x0000aab8, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 },
+ { 0x0000aabc, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 },
+ { 0x0000aac0, 0x00000000, 0x00000000, 0x000bb380, 0x000bb380, 0x00000000 },
+ { 0x0000aac4, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 },
+ { 0x0000aac8, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 },
+ { 0x0000aacc, 0x00000000, 0x00000000, 0x000bb38c, 0x000bb38c, 0x00000000 },
+ { 0x0000aad0, 0x00000000, 0x00000000, 0x000bb394, 0x000bb394, 0x00000000 },
+ { 0x0000aad4, 0x00000000, 0x00000000, 0x000bb798, 0x000bb798, 0x00000000 },
+ { 0x0000aad8, 0x00000000, 0x00000000, 0x000f970c, 0x000f970c, 0x00000000 },
+ { 0x0000aadc, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 },
+ { 0x0000aae0, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 },
+ { 0x0000aae4, 0x00000000, 0x00000000, 0x000f9718, 0x000f9718, 0x00000000 },
+ { 0x0000aae8, 0x00000000, 0x00000000, 0x000f9705, 0x000f9705, 0x00000000 },
+ { 0x0000aaec, 0x00000000, 0x00000000, 0x000f9709, 0x000f9709, 0x00000000 },
+ { 0x0000aaf0, 0x00000000, 0x00000000, 0x000f970d, 0x000f970d, 0x00000000 },
+ { 0x0000aaf4, 0x00000000, 0x00000000, 0x000f9711, 0x000f9711, 0x00000000 },
+ { 0x0000aaf8, 0x00000000, 0x00000000, 0x000f9715, 0x000f9715, 0x00000000 },
+ { 0x0000aafc, 0x00000000, 0x00000000, 0x000f9719, 0x000f9719, 0x00000000 },
+ { 0x0000ab00, 0x00000000, 0x00000000, 0x000fb7a4, 0x000fb7a4, 0x00000000 },
+ { 0x0000ab04, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 },
+ { 0x0000ab08, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 },
+ { 0x0000ab0c, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 },
+ { 0x0000ab10, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 },
+ { 0x0000ab14, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 },
+ { 0x0000ab18, 0x00000000, 0x00000000, 0x000fb7bc, 0x000fb7bc, 0x00000000 },
+ { 0x0000ab1c, 0x00000000, 0x00000000, 0x000fb7a1, 0x000fb7a1, 0x00000000 },
+ { 0x0000ab20, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 },
+ { 0x0000ab24, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 },
+ { 0x0000ab28, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 },
+ { 0x0000ab2c, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 },
+ { 0x0000ab30, 0x00000000, 0x00000000, 0x000fb7bd, 0x000fb7bd, 0x00000000 },
+ { 0x0000ab34, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 },
+ { 0x0000ab38, 0x00000000, 0x00000000, 0x000fb7cd, 0x000fb7cd, 0x00000000 },
+ { 0x0000ab3c, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 },
+ { 0x0000ab40, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 },
+ { 0x0000ab44, 0x00000000, 0x00000000, 0x000fb7c2, 0x000fb7c2, 0x00000000 },
+ { 0x0000ab48, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 },
+ { 0x0000ab4c, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 },
+ { 0x0000ab50, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 },
+ { 0x0000ab54, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 },
+ { 0x0000ab58, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 },
+ { 0x0000ab5c, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 },
+ { 0x0000ab60, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 },
+ { 0x0000ab64, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab68, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab6c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab70, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab74, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab78, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab7c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab80, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab84, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab88, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab8c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab90, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab94, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab98, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab9c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000aba0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000aba4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000aba8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abac, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abb0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abb4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abb8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abbc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abc0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abc4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abc8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abcc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abd0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abd4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abd8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abdc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abe0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abe4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abe8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abec, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abf0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abf4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abf8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abfc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 },
+ { 0x0000a20c, 0x00000014, 0x00000014, 0x00000000, 0x00000000, 0x0001f000 },
+ { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
+ { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
+ { 0x0000a250, 0x001ff000, 0x001ff000, 0x001ca000, 0x001ca000, 0x001da000 },
+ { 0x0000a274, 0x0a81c652, 0x0a81c652, 0x0a820652, 0x0a820652, 0x0a82a652 },
+ { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000a304, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 },
+ { 0x0000a308, 0x00000000, 0x00000000, 0x00010408, 0x00010408, 0x00000000 },
+ { 0x0000a30c, 0x00000000, 0x00000000, 0x0001860a, 0x0001860a, 0x00000000 },
+ { 0x0000a310, 0x00000000, 0x00000000, 0x00020818, 0x00020818, 0x00000000 },
+ { 0x0000a314, 0x00000000, 0x00000000, 0x00024858, 0x00024858, 0x00000000 },
+ { 0x0000a318, 0x00000000, 0x00000000, 0x00026859, 0x00026859, 0x00000000 },
+ { 0x0000a31c, 0x00000000, 0x00000000, 0x0002985b, 0x0002985b, 0x00000000 },
+ { 0x0000a320, 0x00000000, 0x00000000, 0x0002c89a, 0x0002c89a, 0x00000000 },
+ { 0x0000a324, 0x00000000, 0x00000000, 0x0002e89b, 0x0002e89b, 0x00000000 },
+ { 0x0000a328, 0x00000000, 0x00000000, 0x0003089c, 0x0003089c, 0x00000000 },
+ { 0x0000a32c, 0x00000000, 0x00000000, 0x0003289d, 0x0003289d, 0x00000000 },
+ { 0x0000a330, 0x00000000, 0x00000000, 0x0003489e, 0x0003489e, 0x00000000 },
+ { 0x0000a334, 0x00000000, 0x00000000, 0x000388de, 0x000388de, 0x00000000 },
+ { 0x0000a338, 0x00000000, 0x00000000, 0x0003b91e, 0x0003b91e, 0x00000000 },
+ { 0x0000a33c, 0x00000000, 0x00000000, 0x0003d95e, 0x0003d95e, 0x00000000 },
+ { 0x0000a340, 0x00000000, 0x00000000, 0x000419df, 0x000419df, 0x00000000 },
+ { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
{ 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },
- { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
- { 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 },
};
-static const u32 ar9280Common_9280_2[][2] = {
+static const u_int32_t ar9285Common_9285[][2] = {
{ 0x0000000c, 0x00000000 },
- { 0x00000030, 0x00020015 },
+ { 0x00000030, 0x00020045 },
{ 0x00000034, 0x00000005 },
{ 0x00000040, 0x00000000 },
{ 0x00000044, 0x00000008 },
@@ -2837,7 +3848,7 @@ static const u32 ar9280Common_9280_2[][2] = {
{ 0x00004024, 0x0000001f },
{ 0x00004060, 0x00000000 },
{ 0x00004064, 0x00000000 },
- { 0x00007010, 0x00000033 },
+ { 0x00007010, 0x00000031 },
{ 0x00007034, 0x00000002 },
{ 0x00007038, 0x000004c2 },
{ 0x00008004, 0x00000000 },
@@ -2847,7 +3858,7 @@ static const u32 ar9280Common_9280_2[][2] = {
{ 0x00008020, 0x00000000 },
{ 0x00008038, 0x00000000 },
{ 0x0000803c, 0x00000000 },
- { 0x00008048, 0x40000000 },
+ { 0x00008048, 0x00000000 },
{ 0x00008054, 0x00000000 },
{ 0x00008058, 0x00000000 },
{ 0x0000805c, 0x000fc78f },
@@ -2923,6 +3934,7 @@ static const u32 ar9280Common_9280_2[][2] = {
{ 0x00008258, 0x00000000 },
{ 0x0000825c, 0x400000ff },
{ 0x00008260, 0x00080922 },
+ { 0x00008264, 0xa8a00010 },
{ 0x00008270, 0x00000000 },
{ 0x00008274, 0x40000000 },
{ 0x00008278, 0x003e4180 },
@@ -2936,15 +3948,15 @@ static const u32 ar9280Common_9280_2[][2] = {
{ 0x00008300, 0x00000040 },
{ 0x00008314, 0x00000000 },
{ 0x00008328, 0x00000000 },
- { 0x0000832c, 0x00000007 },
+ { 0x0000832c, 0x00000001 },
{ 0x00008330, 0x00000302 },
{ 0x00008334, 0x00000e00 },
{ 0x00008338, 0x00000000 },
{ 0x0000833c, 0x00000000 },
- { 0x00008340, 0x000107ff },
+ { 0x00008340, 0x00010380 },
{ 0x00008344, 0x00581043 },
{ 0x00009808, 0x00000000 },
- { 0x0000980c, 0xafa68e30 },
+ { 0x0000980c, 0xafe68e30 },
{ 0x00009810, 0xfd14e000 },
{ 0x00009814, 0x9c0a9f6b },
{ 0x0000981c, 0x00000000 },
@@ -2952,7 +3964,6 @@ static const u32 ar9280Common_9280_2[][2] = {
{ 0x00009830, 0x00000000 },
{ 0x0000983c, 0x00200400 },
{ 0x0000984c, 0x0040233c },
- { 0x0000a84c, 0x0040233c },
{ 0x00009854, 0x00000044 },
{ 0x00009900, 0x00000000 },
{ 0x00009904, 0x00000000 },
@@ -2961,20 +3972,18 @@ static const u32 ar9280Common_9280_2[][2] = {
{ 0x00009910, 0x01002310 },
{ 0x0000991c, 0x10000fff },
{ 0x00009920, 0x04900000 },
- { 0x0000a920, 0x04900000 },
{ 0x00009928, 0x00000001 },
{ 0x0000992c, 0x00000004 },
{ 0x00009934, 0x1e1f2022 },
{ 0x00009938, 0x0a0b0c0d },
{ 0x0000993c, 0x00000000 },
+ { 0x00009940, 0x14750604 },
{ 0x00009948, 0x9280c00a },
{ 0x0000994c, 0x00020028 },
{ 0x00009954, 0x5f3ca3de },
{ 0x00009958, 0x2108ecff },
- { 0x00009940, 0x14750604 },
- { 0x0000c95c, 0x004b6a8e },
- { 0x0000c968, 0x000003ce },
- { 0x00009970, 0x190fb515 },
+ { 0x00009968, 0x000003ce },
+ { 0x00009970, 0x1927b515 },
{ 0x00009974, 0x00000000 },
{ 0x00009978, 0x00000001 },
{ 0x0000997c, 0x00000000 },
@@ -2989,7 +3998,7 @@ static const u32 ar9280Common_9280_2[][2] = {
{ 0x000099a0, 0x00000000 },
{ 0x000099a4, 0x00000001 },
{ 0x000099a8, 0x201fff00 },
- { 0x000099ac, 0x006f0000 },
+ { 0x000099ac, 0x2def0a00 },
{ 0x000099b0, 0x03051000 },
{ 0x000099b4, 0x00000820 },
{ 0x000099dc, 0x00000000 },
@@ -2998,31 +4007,28 @@ static const u32 ar9280Common_9280_2[][2] = {
{ 0x000099e8, 0x3c466478 },
{ 0x000099ec, 0x0cc80caa },
{ 0x000099f0, 0x00000000 },
- { 0x000099fc, 0x00001042 },
+ { 0x0000a208, 0x803e6788 },
{ 0x0000a210, 0x4080a333 },
- { 0x0000a214, 0x40206c10 },
+ { 0x0000a214, 0x00206c10 },
{ 0x0000a218, 0x009c4060 },
{ 0x0000a220, 0x01834061 },
{ 0x0000a224, 0x00000400 },
{ 0x0000a228, 0x000003b5 },
- { 0x0000a22c, 0x233f71c0 },
+ { 0x0000a22c, 0x00000000 },
{ 0x0000a234, 0x20202020 },
{ 0x0000a238, 0x20202020 },
- { 0x0000a23c, 0x13c88000 },
- { 0x0000a240, 0x38490a20 },
- { 0x0000a244, 0x00007bb6 },
- { 0x0000a248, 0x0fff3ffc },
+ { 0x0000a244, 0x00000000 },
+ { 0x0000a248, 0xfffffffc },
{ 0x0000a24c, 0x00000000 },
{ 0x0000a254, 0x00000000 },
- { 0x0000a258, 0x0cdbd380 },
- { 0x0000a25c, 0x0f0f0f01 },
- { 0x0000a260, 0xdfa91f01 },
+ { 0x0000a258, 0x0ccb5380 },
+ { 0x0000a25c, 0x15151501 },
+ { 0x0000a260, 0xdfa90f01 },
{ 0x0000a268, 0x00000000 },
- { 0x0000a26c, 0x0ebae9c6 },
- { 0x0000b26c, 0x0ebae9c6 },
- { 0x0000d270, 0x00820820 },
- { 0x0000a278, 0x1ce739ce },
- { 0x0000a27c, 0x050701ce },
+ { 0x0000a26c, 0x0ebae9e6 },
+ { 0x0000d270, 0x0d820820 },
+ { 0x0000a278, 0x39ce739c },
+ { 0x0000a27c, 0x050e039c },
{ 0x0000d35c, 0x07ffffef },
{ 0x0000d360, 0x0fffffe7 },
{ 0x0000d364, 0x17ffffe5 },
@@ -3037,8 +4043,8 @@ static const u32 ar9280Common_9280_2[][2] = {
{ 0x0000a388, 0x0c000000 },
{ 0x0000a38c, 0x20202020 },
{ 0x0000a390, 0x20202020 },
- { 0x0000a394, 0x1ce739ce },
- { 0x0000a398, 0x000001ce },
+ { 0x0000a394, 0x39ce739c },
+ { 0x0000a398, 0x0000039c },
{ 0x0000a39c, 0x00000001 },
{ 0x0000a3a0, 0x00000000 },
{ 0x0000a3a4, 0x00000000 },
@@ -3050,96 +4056,746 @@ static const u32 ar9280Common_9280_2[][2] = {
{ 0x0000a3bc, 0x00000000 },
{ 0x0000a3c0, 0x00000000 },
{ 0x0000a3c4, 0x00000000 },
- { 0x0000a3c8, 0x00000246 },
{ 0x0000a3cc, 0x20202020 },
{ 0x0000a3d0, 0x20202020 },
{ 0x0000a3d4, 0x20202020 },
- { 0x0000a3dc, 0x1ce739ce },
- { 0x0000a3e0, 0x000001ce },
+ { 0x0000a3dc, 0x39ce739c },
+ { 0x0000a3e0, 0x0000039c },
{ 0x0000a3e4, 0x00000000 },
{ 0x0000a3e8, 0x18c43433 },
{ 0x0000a3ec, 0x00f70081 },
- { 0x00007800, 0x00040000 },
- { 0x00007804, 0xdb005012 },
- { 0x00007808, 0x04924914 },
- { 0x0000780c, 0x21084210 },
- { 0x00007810, 0x6d801300 },
- { 0x00007814, 0x0019beff },
- { 0x00007818, 0x07e41000 },
- { 0x0000781c, 0x00392000 },
- { 0x00007820, 0x92592480 },
- { 0x00007824, 0x00040000 },
- { 0x00007828, 0xdb005012 },
- { 0x0000782c, 0x04924914 },
- { 0x00007830, 0x21084210 },
- { 0x00007834, 0x6d801300 },
- { 0x00007838, 0x0019beff },
- { 0x0000783c, 0x07e40000 },
- { 0x00007840, 0x00392000 },
- { 0x00007844, 0x92592480 },
- { 0x00007848, 0x00100000 },
- { 0x0000784c, 0x773f0567 },
- { 0x00007850, 0x54214514 },
- { 0x00007854, 0x12035828 },
- { 0x00007858, 0x9259269a },
- { 0x00007860, 0x52802000 },
- { 0x00007864, 0x0a8e370e },
- { 0x00007868, 0xc0102850 },
- { 0x0000786c, 0x812d4000 },
- { 0x00007870, 0x807ec400 },
- { 0x00007874, 0x001b6db0 },
- { 0x00007878, 0x00376b63 },
- { 0x0000787c, 0x06db6db6 },
- { 0x00007880, 0x006d8000 },
- { 0x00007884, 0xffeffffe },
- { 0x00007888, 0xffeffffe },
- { 0x0000788c, 0x00010000 },
- { 0x00007890, 0x02060aeb },
- { 0x00007898, 0x2a850160 },
+ { 0x00007800, 0x00140000 },
+ { 0x00007804, 0x0e4548d8 },
+ { 0x00007808, 0x54214514 },
+ { 0x0000780c, 0x02025820 },
+ { 0x00007810, 0x71c0d388 },
+ { 0x00007814, 0x924934a8 },
+ { 0x0000781c, 0x00000000 },
+ { 0x00007820, 0x00000c04 },
+ { 0x00007824, 0x00d86fff },
+ { 0x00007828, 0x26d2491b },
+ { 0x0000782c, 0x6e36d97b },
+ { 0x00007830, 0xedb6d96c },
+ { 0x00007834, 0x71400086 },
+ { 0x00007838, 0xfac68800 },
+ { 0x0000783c, 0x0001fffe },
+ { 0x00007840, 0xffeb1a20 },
+ { 0x00007844, 0x000c0db6 },
+ { 0x00007848, 0x6db61b6f },
+ { 0x0000784c, 0x6d9b66db },
+ { 0x00007850, 0x6d8c6dba },
+ { 0x00007854, 0x00040000 },
+ { 0x00007858, 0xdb003012 },
+ { 0x0000785c, 0x04924914 },
+ { 0x00007860, 0x21084210 },
+ { 0x00007864, 0xf7d7ffde },
+ { 0x00007868, 0xc2034080 },
+ { 0x0000786c, 0x48609eb4 },
+ { 0x00007870, 0x10142c00 },
};
-static const u32 ar9280Modes_fast_clock_9280_2[][3] = {
- { 0x00001030, 0x00000268, 0x000004d0 },
- { 0x00001070, 0x0000018c, 0x00000318 },
- { 0x000010b0, 0x00000fd0, 0x00001fa0 },
- { 0x00008014, 0x044c044c, 0x08980898 },
- { 0x0000801c, 0x148ec02b, 0x148ec057 },
- { 0x00008318, 0x000044c0, 0x00008980 },
- { 0x00009820, 0x02020200, 0x02020200 },
- { 0x00009824, 0x00000f0f, 0x00000f0f },
- { 0x00009828, 0x0b020001, 0x0b020001 },
- { 0x00009834, 0x00000f0f, 0x00000f0f },
- { 0x00009844, 0x03721821, 0x03721821 },
- { 0x00009914, 0x00000898, 0x00000898 },
- { 0x00009918, 0x0000000b, 0x00000016 },
- { 0x00009944, 0xdfbc1210, 0xdfbc1210 },
+static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285[][2] = {
+ {0x00004040, 0x9248fd00 },
+ {0x00004040, 0x24924924 },
+ {0x00004040, 0xa8000019 },
+ {0x00004040, 0x13160820 },
+ {0x00004040, 0xe5980560 },
+ {0x00004040, 0xc01dcffd },
+ {0x00004040, 0x1aaabe41 },
+ {0x00004040, 0xbe105554 },
+ {0x00004040, 0x00043007 },
+ {0x00004044, 0x00000000 },
};
-
-
-static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = {
+static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285[][2] = {
{0x00004040, 0x9248fd00 },
{0x00004040, 0x24924924 },
{0x00004040, 0xa8000019 },
{0x00004040, 0x13160820 },
{0x00004040, 0xe5980560 },
- {0x00004040, 0x401dcffc },
- {0x00004040, 0x1aaabe40 },
+ {0x00004040, 0xc01dcffc },
+ {0x00004040, 0x1aaabe41 },
{0x00004040, 0xbe105554 },
{0x00004040, 0x00043007 },
{0x00004044, 0x00000000 },
};
+static const u_int32_t ar9285Modes_9285_1_2[][6] = {
+ { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 },
+ { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 },
+ { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 },
+ { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 },
+ { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 },
+ { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f },
+ { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 },
+ { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 },
+ { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 },
+ { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+ { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 },
+ { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e },
+ { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 },
+ { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e },
+ { 0x00009844, 0x0372161e, 0x0372161e, 0x03720020, 0x03720020, 0x037216a0 },
+ { 0x00009848, 0x00001066, 0x00001066, 0x00000057, 0x00000057, 0x00001059 },
+ { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 },
+ { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e },
+ { 0x0000985c, 0x3139605e, 0x3139605e, 0x3136605e, 0x3136605e, 0x3139605e },
+ { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 },
+ { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 },
+ { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 },
+ { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 },
+ { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 },
+ { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 },
+ { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d },
+ { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010 },
+ { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c },
+ { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 },
+ { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 },
+ { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 },
+ { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 },
+ { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 },
+ { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 },
+ { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x00009a00, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 },
+ { 0x00009a04, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 },
+ { 0x00009a08, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 },
+ { 0x00009a0c, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 },
+ { 0x00009a10, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 },
+ { 0x00009a14, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 },
+ { 0x00009a18, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 },
+ { 0x00009a1c, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 },
+ { 0x00009a20, 0x00000000, 0x00000000, 0x00068114, 0x00068114, 0x00000000 },
+ { 0x00009a24, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 },
+ { 0x00009a28, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 },
+ { 0x00009a2c, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 },
+ { 0x00009a30, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 },
+ { 0x00009a34, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 },
+ { 0x00009a38, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 },
+ { 0x00009a3c, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 },
+ { 0x00009a40, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 },
+ { 0x00009a44, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 },
+ { 0x00009a48, 0x00000000, 0x00000000, 0x00068284, 0x00068284, 0x00000000 },
+ { 0x00009a4c, 0x00000000, 0x00000000, 0x00068288, 0x00068288, 0x00000000 },
+ { 0x00009a50, 0x00000000, 0x00000000, 0x00068220, 0x00068220, 0x00000000 },
+ { 0x00009a54, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 },
+ { 0x00009a58, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 },
+ { 0x00009a5c, 0x00000000, 0x00000000, 0x00068304, 0x00068304, 0x00000000 },
+ { 0x00009a60, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 },
+ { 0x00009a64, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 },
+ { 0x00009a68, 0x00000000, 0x00000000, 0x00068380, 0x00068380, 0x00000000 },
+ { 0x00009a6c, 0x00000000, 0x00000000, 0x00068384, 0x00068384, 0x00000000 },
+ { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 },
+ { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 },
+ { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 },
+ { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 },
+ { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 },
+ { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 },
+ { 0x00009a88, 0x00000000, 0x00000000, 0x00068b04, 0x00068b04, 0x00000000 },
+ { 0x00009a8c, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 },
+ { 0x00009a90, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 },
+ { 0x00009a94, 0x00000000, 0x00000000, 0x00068b0c, 0x00068b0c, 0x00000000 },
+ { 0x00009a98, 0x00000000, 0x00000000, 0x00068b80, 0x00068b80, 0x00000000 },
+ { 0x00009a9c, 0x00000000, 0x00000000, 0x00068b84, 0x00068b84, 0x00000000 },
+ { 0x00009aa0, 0x00000000, 0x00000000, 0x00068b88, 0x00068b88, 0x00000000 },
+ { 0x00009aa4, 0x00000000, 0x00000000, 0x00068b8c, 0x00068b8c, 0x00000000 },
+ { 0x00009aa8, 0x00000000, 0x00000000, 0x000b8b90, 0x000b8b90, 0x00000000 },
+ { 0x00009aac, 0x00000000, 0x00000000, 0x000b8f80, 0x000b8f80, 0x00000000 },
+ { 0x00009ab0, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 },
+ { 0x00009ab4, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 },
+ { 0x00009ab8, 0x00000000, 0x00000000, 0x000b8f8c, 0x000b8f8c, 0x00000000 },
+ { 0x00009abc, 0x00000000, 0x00000000, 0x000b8f90, 0x000b8f90, 0x00000000 },
+ { 0x00009ac0, 0x00000000, 0x00000000, 0x000bb30c, 0x000bb30c, 0x00000000 },
+ { 0x00009ac4, 0x00000000, 0x00000000, 0x000bb310, 0x000bb310, 0x00000000 },
+ { 0x00009ac8, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 },
+ { 0x00009acc, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 },
+ { 0x00009ad0, 0x00000000, 0x00000000, 0x000bb324, 0x000bb324, 0x00000000 },
+ { 0x00009ad4, 0x00000000, 0x00000000, 0x000bb704, 0x000bb704, 0x00000000 },
+ { 0x00009ad8, 0x00000000, 0x00000000, 0x000f96a4, 0x000f96a4, 0x00000000 },
+ { 0x00009adc, 0x00000000, 0x00000000, 0x000f96a8, 0x000f96a8, 0x00000000 },
+ { 0x00009ae0, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 },
+ { 0x00009ae4, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 },
+ { 0x00009ae8, 0x00000000, 0x00000000, 0x000f9720, 0x000f9720, 0x00000000 },
+ { 0x00009aec, 0x00000000, 0x00000000, 0x000f9724, 0x000f9724, 0x00000000 },
+ { 0x00009af0, 0x00000000, 0x00000000, 0x000f9728, 0x000f9728, 0x00000000 },
+ { 0x00009af4, 0x00000000, 0x00000000, 0x000f972c, 0x000f972c, 0x00000000 },
+ { 0x00009af8, 0x00000000, 0x00000000, 0x000f97a0, 0x000f97a0, 0x00000000 },
+ { 0x00009afc, 0x00000000, 0x00000000, 0x000f97a4, 0x000f97a4, 0x00000000 },
+ { 0x00009b00, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 },
+ { 0x00009b04, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 },
+ { 0x00009b08, 0x00000000, 0x00000000, 0x000fb7b4, 0x000fb7b4, 0x00000000 },
+ { 0x00009b0c, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 },
+ { 0x00009b10, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 },
+ { 0x00009b14, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 },
+ { 0x00009b18, 0x00000000, 0x00000000, 0x000fb7ad, 0x000fb7ad, 0x00000000 },
+ { 0x00009b1c, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 },
+ { 0x00009b20, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 },
+ { 0x00009b24, 0x00000000, 0x00000000, 0x000fb7b9, 0x000fb7b9, 0x00000000 },
+ { 0x00009b28, 0x00000000, 0x00000000, 0x000fb7c5, 0x000fb7c5, 0x00000000 },
+ { 0x00009b2c, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 },
+ { 0x00009b30, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 },
+ { 0x00009b34, 0x00000000, 0x00000000, 0x000fb7d5, 0x000fb7d5, 0x00000000 },
+ { 0x00009b38, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 },
+ { 0x00009b3c, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 },
+ { 0x00009b40, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 },
+ { 0x00009b44, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 },
+ { 0x00009b48, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 },
+ { 0x00009b4c, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 },
+ { 0x00009b50, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 },
+ { 0x00009b54, 0x00000000, 0x00000000, 0x000fb7c7, 0x000fb7c7, 0x00000000 },
+ { 0x00009b58, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 },
+ { 0x00009b5c, 0x00000000, 0x00000000, 0x000fb7cf, 0x000fb7cf, 0x00000000 },
+ { 0x00009b60, 0x00000000, 0x00000000, 0x000fb7d7, 0x000fb7d7, 0x00000000 },
+ { 0x00009b64, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b68, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b6c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b70, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b74, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b78, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b7c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b80, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b84, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b88, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b8c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b90, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b94, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b98, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009b9c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009ba0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009ba4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009ba8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bac, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bb0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bb4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bb8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bbc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bc0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bc4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bc8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bcc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bd0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bd4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bd8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bdc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009be0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009be4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009be8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bec, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bf0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bf4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bf8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x00009bfc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 },
+ { 0x0000aa00, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c, 0x00000000 },
+ { 0x0000aa04, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c, 0x00000000 },
+ { 0x0000aa08, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c, 0x00000000 },
+ { 0x0000aa0c, 0x00000000, 0x00000000, 0x00068080, 0x00068080, 0x00000000 },
+ { 0x0000aa10, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 },
+ { 0x0000aa14, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 },
+ { 0x0000aa18, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 },
+ { 0x0000aa1c, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 },
+ { 0x0000aa20, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 },
+ { 0x0000aa24, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 },
+ { 0x0000aa28, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 },
+ { 0x0000aa2c, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 },
+ { 0x0000aa30, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 },
+ { 0x0000aa34, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 },
+ { 0x0000aa38, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 },
+ { 0x0000aa3c, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 },
+ { 0x0000aa40, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 },
+ { 0x0000aa44, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 },
+ { 0x0000aa48, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 },
+ { 0x0000aa4c, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 },
+ { 0x0000aa50, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 },
+ { 0x0000aa54, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 },
+ { 0x0000aa58, 0x00000000, 0x00000000, 0x000681ac, 0x000681ac, 0x00000000 },
+ { 0x0000aa5c, 0x00000000, 0x00000000, 0x0006821c, 0x0006821c, 0x00000000 },
+ { 0x0000aa60, 0x00000000, 0x00000000, 0x00068224, 0x00068224, 0x00000000 },
+ { 0x0000aa64, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 },
+ { 0x0000aa68, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 },
+ { 0x0000aa6c, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 },
+ { 0x0000aa70, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 },
+ { 0x0000aa74, 0x00000000, 0x00000000, 0x00068310, 0x00068310, 0x00000000 },
+ { 0x0000aa78, 0x00000000, 0x00000000, 0x00068788, 0x00068788, 0x00000000 },
+ { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006878c, 0x0006878c, 0x00000000 },
+ { 0x0000aa80, 0x00000000, 0x00000000, 0x00068790, 0x00068790, 0x00000000 },
+ { 0x0000aa84, 0x00000000, 0x00000000, 0x00068794, 0x00068794, 0x00000000 },
+ { 0x0000aa88, 0x00000000, 0x00000000, 0x00068798, 0x00068798, 0x00000000 },
+ { 0x0000aa8c, 0x00000000, 0x00000000, 0x0006879c, 0x0006879c, 0x00000000 },
+ { 0x0000aa90, 0x00000000, 0x00000000, 0x00068b89, 0x00068b89, 0x00000000 },
+ { 0x0000aa94, 0x00000000, 0x00000000, 0x00068b8d, 0x00068b8d, 0x00000000 },
+ { 0x0000aa98, 0x00000000, 0x00000000, 0x00068b91, 0x00068b91, 0x00000000 },
+ { 0x0000aa9c, 0x00000000, 0x00000000, 0x00068b95, 0x00068b95, 0x00000000 },
+ { 0x0000aaa0, 0x00000000, 0x00000000, 0x00068b99, 0x00068b99, 0x00000000 },
+ { 0x0000aaa4, 0x00000000, 0x00000000, 0x00068ba5, 0x00068ba5, 0x00000000 },
+ { 0x0000aaa8, 0x00000000, 0x00000000, 0x00068ba9, 0x00068ba9, 0x00000000 },
+ { 0x0000aaac, 0x00000000, 0x00000000, 0x00068bad, 0x00068bad, 0x00000000 },
+ { 0x0000aab0, 0x00000000, 0x00000000, 0x000b8b0c, 0x000b8b0c, 0x00000000 },
+ { 0x0000aab4, 0x00000000, 0x00000000, 0x000b8f10, 0x000b8f10, 0x00000000 },
+ { 0x0000aab8, 0x00000000, 0x00000000, 0x000b8f14, 0x000b8f14, 0x00000000 },
+ { 0x0000aabc, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 },
+ { 0x0000aac0, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 },
+ { 0x0000aac4, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 },
+ { 0x0000aac8, 0x00000000, 0x00000000, 0x000bb380, 0x000bb380, 0x00000000 },
+ { 0x0000aacc, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 },
+ { 0x0000aad0, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 },
+ { 0x0000aad4, 0x00000000, 0x00000000, 0x000bb38c, 0x000bb38c, 0x00000000 },
+ { 0x0000aad8, 0x00000000, 0x00000000, 0x000bb394, 0x000bb394, 0x00000000 },
+ { 0x0000aadc, 0x00000000, 0x00000000, 0x000bb798, 0x000bb798, 0x00000000 },
+ { 0x0000aae0, 0x00000000, 0x00000000, 0x000f970c, 0x000f970c, 0x00000000 },
+ { 0x0000aae4, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 },
+ { 0x0000aae8, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 },
+ { 0x0000aaec, 0x00000000, 0x00000000, 0x000f9718, 0x000f9718, 0x00000000 },
+ { 0x0000aaf0, 0x00000000, 0x00000000, 0x000f9705, 0x000f9705, 0x00000000 },
+ { 0x0000aaf4, 0x00000000, 0x00000000, 0x000f9709, 0x000f9709, 0x00000000 },
+ { 0x0000aaf8, 0x00000000, 0x00000000, 0x000f970d, 0x000f970d, 0x00000000 },
+ { 0x0000aafc, 0x00000000, 0x00000000, 0x000f9711, 0x000f9711, 0x00000000 },
+ { 0x0000ab00, 0x00000000, 0x00000000, 0x000f9715, 0x000f9715, 0x00000000 },
+ { 0x0000ab04, 0x00000000, 0x00000000, 0x000f9719, 0x000f9719, 0x00000000 },
+ { 0x0000ab08, 0x00000000, 0x00000000, 0x000fb7a4, 0x000fb7a4, 0x00000000 },
+ { 0x0000ab0c, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 },
+ { 0x0000ab10, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 },
+ { 0x0000ab14, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 },
+ { 0x0000ab18, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 },
+ { 0x0000ab1c, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 },
+ { 0x0000ab20, 0x00000000, 0x00000000, 0x000fb7bc, 0x000fb7bc, 0x00000000 },
+ { 0x0000ab24, 0x00000000, 0x00000000, 0x000fb7a1, 0x000fb7a1, 0x00000000 },
+ { 0x0000ab28, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 },
+ { 0x0000ab2c, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 },
+ { 0x0000ab30, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 },
+ { 0x0000ab34, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 },
+ { 0x0000ab38, 0x00000000, 0x00000000, 0x000fb7bd, 0x000fb7bd, 0x00000000 },
+ { 0x0000ab3c, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 },
+ { 0x0000ab40, 0x00000000, 0x00000000, 0x000fb7cd, 0x000fb7cd, 0x00000000 },
+ { 0x0000ab44, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 },
+ { 0x0000ab48, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 },
+ { 0x0000ab4c, 0x00000000, 0x00000000, 0x000fb7c2, 0x000fb7c2, 0x00000000 },
+ { 0x0000ab50, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 },
+ { 0x0000ab54, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 },
+ { 0x0000ab58, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 },
+ { 0x0000ab5c, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 },
+ { 0x0000ab60, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 },
+ { 0x0000ab64, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 },
+ { 0x0000ab68, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 },
+ { 0x0000ab6c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab70, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab74, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab78, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab7c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab80, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab84, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab88, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab8c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab90, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab94, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab98, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000ab9c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000aba0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000aba4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000aba8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abac, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abb0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abb4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abb8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abbc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abc0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abc4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abc8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abcc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abd0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abd4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abd8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abdc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abe0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abe4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abe8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abec, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abf0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abf4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abf8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000abfc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 },
+ { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 },
+ { 0x0000a20c, 0x00000014, 0x00000014, 0x00000000, 0x00000000, 0x0001f000 },
+ { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a },
+ { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 },
+ { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 },
+ { 0x0000a274, 0x0a81c652, 0x0a81c652, 0x0a820652, 0x0a820652, 0x0a82a652 },
+ { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 },
+ { 0x0000a304, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 },
+ { 0x0000a308, 0x00000000, 0x00000000, 0x00010408, 0x00010408, 0x00000000 },
+ { 0x0000a30c, 0x00000000, 0x00000000, 0x0001860a, 0x0001860a, 0x00000000 },
+ { 0x0000a310, 0x00000000, 0x00000000, 0x00020818, 0x00020818, 0x00000000 },
+ { 0x0000a314, 0x00000000, 0x00000000, 0x00024858, 0x00024858, 0x00000000 },
+ { 0x0000a318, 0x00000000, 0x00000000, 0x00026859, 0x00026859, 0x00000000 },
+ { 0x0000a31c, 0x00000000, 0x00000000, 0x0002985b, 0x0002985b, 0x00000000 },
+ { 0x0000a320, 0x00000000, 0x00000000, 0x0002b89a, 0x0002b89a, 0x00000000 },
+ { 0x0000a324, 0x00000000, 0x00000000, 0x0002d89b, 0x0002d89b, 0x00000000 },
+ { 0x0000a328, 0x00000000, 0x00000000, 0x0002f89c, 0x0002f89c, 0x00000000 },
+ { 0x0000a32c, 0x00000000, 0x00000000, 0x0003189d, 0x0003189d, 0x00000000 },
+ { 0x0000a330, 0x00000000, 0x00000000, 0x0003389e, 0x0003389e, 0x00000000 },
+ { 0x0000a334, 0x00000000, 0x00000000, 0x000368de, 0x000368de, 0x00000000 },
+ { 0x0000a338, 0x00000000, 0x00000000, 0x0003891e, 0x0003891e, 0x00000000 },
+ { 0x0000a33c, 0x00000000, 0x00000000, 0x0003a95e, 0x0003a95e, 0x00000000 },
+ { 0x0000a340, 0x00000000, 0x00000000, 0x0003e9df, 0x0003e9df, 0x00000000 },
+ { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 },
+ { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e },
+};
+static const u_int32_t ar9285Common_9285_1_2[][2] = {
+ { 0x0000000c, 0x00000000 },
+ { 0x00000030, 0x00020045 },
+ { 0x00000034, 0x00000005 },
+ { 0x00000040, 0x00000000 },
+ { 0x00000044, 0x00000008 },
+ { 0x00000048, 0x00000008 },
+ { 0x0000004c, 0x00000010 },
+ { 0x00000050, 0x00000000 },
+ { 0x00000054, 0x0000001f },
+ { 0x00000800, 0x00000000 },
+ { 0x00000804, 0x00000000 },
+ { 0x00000808, 0x00000000 },
+ { 0x0000080c, 0x00000000 },
+ { 0x00000810, 0x00000000 },
+ { 0x00000814, 0x00000000 },
+ { 0x00000818, 0x00000000 },
+ { 0x0000081c, 0x00000000 },
+ { 0x00000820, 0x00000000 },
+ { 0x00000824, 0x00000000 },
+ { 0x00001040, 0x002ffc0f },
+ { 0x00001044, 0x002ffc0f },
+ { 0x00001048, 0x002ffc0f },
+ { 0x0000104c, 0x002ffc0f },
+ { 0x00001050, 0x002ffc0f },
+ { 0x00001054, 0x002ffc0f },
+ { 0x00001058, 0x002ffc0f },
+ { 0x0000105c, 0x002ffc0f },
+ { 0x00001060, 0x002ffc0f },
+ { 0x00001064, 0x002ffc0f },
+ { 0x00001230, 0x00000000 },
+ { 0x00001270, 0x00000000 },
+ { 0x00001038, 0x00000000 },
+ { 0x00001078, 0x00000000 },
+ { 0x000010b8, 0x00000000 },
+ { 0x000010f8, 0x00000000 },
+ { 0x00001138, 0x00000000 },
+ { 0x00001178, 0x00000000 },
+ { 0x000011b8, 0x00000000 },
+ { 0x000011f8, 0x00000000 },
+ { 0x00001238, 0x00000000 },
+ { 0x00001278, 0x00000000 },
+ { 0x000012b8, 0x00000000 },
+ { 0x000012f8, 0x00000000 },
+ { 0x00001338, 0x00000000 },
+ { 0x00001378, 0x00000000 },
+ { 0x000013b8, 0x00000000 },
+ { 0x000013f8, 0x00000000 },
+ { 0x00001438, 0x00000000 },
+ { 0x00001478, 0x00000000 },
+ { 0x000014b8, 0x00000000 },
+ { 0x000014f8, 0x00000000 },
+ { 0x00001538, 0x00000000 },
+ { 0x00001578, 0x00000000 },
+ { 0x000015b8, 0x00000000 },
+ { 0x000015f8, 0x00000000 },
+ { 0x00001638, 0x00000000 },
+ { 0x00001678, 0x00000000 },
+ { 0x000016b8, 0x00000000 },
+ { 0x000016f8, 0x00000000 },
+ { 0x00001738, 0x00000000 },
+ { 0x00001778, 0x00000000 },
+ { 0x000017b8, 0x00000000 },
+ { 0x000017f8, 0x00000000 },
+ { 0x0000103c, 0x00000000 },
+ { 0x0000107c, 0x00000000 },
+ { 0x000010bc, 0x00000000 },
+ { 0x000010fc, 0x00000000 },
+ { 0x0000113c, 0x00000000 },
+ { 0x0000117c, 0x00000000 },
+ { 0x000011bc, 0x00000000 },
+ { 0x000011fc, 0x00000000 },
+ { 0x0000123c, 0x00000000 },
+ { 0x0000127c, 0x00000000 },
+ { 0x000012bc, 0x00000000 },
+ { 0x000012fc, 0x00000000 },
+ { 0x0000133c, 0x00000000 },
+ { 0x0000137c, 0x00000000 },
+ { 0x000013bc, 0x00000000 },
+ { 0x000013fc, 0x00000000 },
+ { 0x0000143c, 0x00000000 },
+ { 0x0000147c, 0x00000000 },
+ { 0x00004030, 0x00000002 },
+ { 0x0000403c, 0x00000002 },
+ { 0x00004024, 0x0000001f },
+ { 0x00004060, 0x00000000 },
+ { 0x00004064, 0x00000000 },
+ { 0x00007010, 0x00000031 },
+ { 0x00007034, 0x00000002 },
+ { 0x00007038, 0x000004c2 },
+ { 0x00008004, 0x00000000 },
+ { 0x00008008, 0x00000000 },
+ { 0x0000800c, 0x00000000 },
+ { 0x00008018, 0x00000700 },
+ { 0x00008020, 0x00000000 },
+ { 0x00008038, 0x00000000 },
+ { 0x0000803c, 0x00000000 },
+ { 0x00008048, 0x00000000 },
+ { 0x00008054, 0x00000000 },
+ { 0x00008058, 0x00000000 },
+ { 0x0000805c, 0x000fc78f },
+ { 0x00008060, 0x0000000f },
+ { 0x00008064, 0x00000000 },
+ { 0x00008070, 0x00000000 },
+ { 0x000080c0, 0x2a80001a },
+ { 0x000080c4, 0x05dc01e0 },
+ { 0x000080c8, 0x1f402710 },
+ { 0x000080cc, 0x01f40000 },
+ { 0x000080d0, 0x00001e00 },
+ { 0x000080d4, 0x00000000 },
+ { 0x000080d8, 0x00400000 },
+ { 0x000080e0, 0xffffffff },
+ { 0x000080e4, 0x0000ffff },
+ { 0x000080e8, 0x003f3f3f },
+ { 0x000080ec, 0x00000000 },
+ { 0x000080f0, 0x00000000 },
+ { 0x000080f4, 0x00000000 },
+ { 0x000080f8, 0x00000000 },
+ { 0x000080fc, 0x00020000 },
+ { 0x00008100, 0x00020000 },
+ { 0x00008104, 0x00000001 },
+ { 0x00008108, 0x00000052 },
+ { 0x0000810c, 0x00000000 },
+ { 0x00008110, 0x00000168 },
+ { 0x00008118, 0x000100aa },
+ { 0x0000811c, 0x00003210 },
+ { 0x00008120, 0x08f04800 },
+ { 0x00008124, 0x00000000 },
+ { 0x00008128, 0x00000000 },
+ { 0x0000812c, 0x00000000 },
+ { 0x00008130, 0x00000000 },
+ { 0x00008134, 0x00000000 },
+ { 0x00008138, 0x00000000 },
+ { 0x0000813c, 0x00000000 },
+ { 0x00008144, 0xffffffff },
+ { 0x00008168, 0x00000000 },
+ { 0x0000816c, 0x00000000 },
+ { 0x00008170, 0x32143320 },
+ { 0x00008174, 0xfaa4fa50 },
+ { 0x00008178, 0x00000100 },
+ { 0x0000817c, 0x00000000 },
+ { 0x000081c0, 0x00000000 },
+ { 0x000081d0, 0x00003210 },
+ { 0x000081ec, 0x00000000 },
+ { 0x000081f0, 0x00000000 },
+ { 0x000081f4, 0x00000000 },
+ { 0x000081f8, 0x00000000 },
+ { 0x000081fc, 0x00000000 },
+ { 0x00008200, 0x00000000 },
+ { 0x00008204, 0x00000000 },
+ { 0x00008208, 0x00000000 },
+ { 0x0000820c, 0x00000000 },
+ { 0x00008210, 0x00000000 },
+ { 0x00008214, 0x00000000 },
+ { 0x00008218, 0x00000000 },
+ { 0x0000821c, 0x00000000 },
+ { 0x00008220, 0x00000000 },
+ { 0x00008224, 0x00000000 },
+ { 0x00008228, 0x00000000 },
+ { 0x0000822c, 0x00000000 },
+ { 0x00008230, 0x00000000 },
+ { 0x00008234, 0x00000000 },
+ { 0x00008238, 0x00000000 },
+ { 0x0000823c, 0x00000000 },
+ { 0x00008240, 0x00100000 },
+ { 0x00008244, 0x0010f400 },
+ { 0x00008248, 0x00000100 },
+ { 0x0000824c, 0x0001e800 },
+ { 0x00008250, 0x00000000 },
+ { 0x00008254, 0x00000000 },
+ { 0x00008258, 0x00000000 },
+ { 0x0000825c, 0x400000ff },
+ { 0x00008260, 0x00080922 },
+ { 0x00008264, 0xa8a00010 },
+ { 0x00008270, 0x00000000 },
+ { 0x00008274, 0x40000000 },
+ { 0x00008278, 0x003e4180 },
+ { 0x0000827c, 0x00000000 },
+ { 0x00008284, 0x0000002c },
+ { 0x00008288, 0x0000002c },
+ { 0x0000828c, 0x00000000 },
+ { 0x00008294, 0x00000000 },
+ { 0x00008298, 0x00000000 },
+ { 0x0000829c, 0x00000000 },
+ { 0x00008300, 0x00000040 },
+ { 0x00008314, 0x00000000 },
+ { 0x00008328, 0x00000000 },
+ { 0x0000832c, 0x00000001 },
+ { 0x00008330, 0x00000302 },
+ { 0x00008334, 0x00000e00 },
+ { 0x00008338, 0x00ff0000 },
+ { 0x0000833c, 0x00000000 },
+ { 0x00008340, 0x00010380 },
+ { 0x00008344, 0x00581043 },
+ { 0x00009808, 0x00000000 },
+ { 0x0000980c, 0xafe68e30 },
+ { 0x00009810, 0xfd14e000 },
+ { 0x00009814, 0x9c0a9f6b },
+ { 0x0000981c, 0x00000000 },
+ { 0x0000982c, 0x0000a000 },
+ { 0x00009830, 0x00000000 },
+ { 0x0000983c, 0x00200400 },
+ { 0x0000984c, 0x0040233c },
+ { 0x00009854, 0x00000044 },
+ { 0x00009900, 0x00000000 },
+ { 0x00009904, 0x00000000 },
+ { 0x00009908, 0x00000000 },
+ { 0x0000990c, 0x00000000 },
+ { 0x00009910, 0x01002310 },
+ { 0x0000991c, 0x10000fff },
+ { 0x00009920, 0x04900000 },
+ { 0x00009928, 0x00000001 },
+ { 0x0000992c, 0x00000004 },
+ { 0x00009934, 0x1e1f2022 },
+ { 0x00009938, 0x0a0b0c0d },
+ { 0x0000993c, 0x00000000 },
+ { 0x00009940, 0x14750604 },
+ { 0x00009948, 0x9280c00a },
+ { 0x0000994c, 0x00020028 },
+ { 0x00009954, 0x5f3ca3de },
+ { 0x00009958, 0x2108ecff },
+ { 0x00009968, 0x000003ce },
+ { 0x00009970, 0x192bb515 },
+ { 0x00009974, 0x00000000 },
+ { 0x00009978, 0x00000001 },
+ { 0x0000997c, 0x00000000 },
+ { 0x00009980, 0x00000000 },
+ { 0x00009984, 0x00000000 },
+ { 0x00009988, 0x00000000 },
+ { 0x0000998c, 0x00000000 },
+ { 0x00009990, 0x00000000 },
+ { 0x00009994, 0x00000000 },
+ { 0x00009998, 0x00000000 },
+ { 0x0000999c, 0x00000000 },
+ { 0x000099a0, 0x00000000 },
+ { 0x000099a4, 0x00000001 },
+ { 0x000099a8, 0x201fff00 },
+ { 0x000099ac, 0x2def1000 },
+ { 0x000099b0, 0x03051000 },
+ { 0x000099b4, 0x00000820 },
+ { 0x000099dc, 0x00000000 },
+ { 0x000099e0, 0x00000000 },
+ { 0x000099e4, 0xaaaaaaaa },
+ { 0x000099e8, 0x3c466478 },
+ { 0x000099ec, 0x0cc80caa },
+ { 0x000099f0, 0x00000000 },
+ { 0x0000a208, 0x803e6788 },
+ { 0x0000a210, 0x4080a333 },
+ { 0x0000a214, 0x00206c10 },
+ { 0x0000a218, 0x009c4060 },
+ { 0x0000a220, 0x01834061 },
+ { 0x0000a224, 0x00000400 },
+ { 0x0000a228, 0x000003b5 },
+ { 0x0000a22c, 0x00000000 },
+ { 0x0000a234, 0x20202020 },
+ { 0x0000a238, 0x20202020 },
+ { 0x0000a244, 0x00000000 },
+ { 0x0000a248, 0xfffffffc },
+ { 0x0000a24c, 0x00000000 },
+ { 0x0000a254, 0x00000000 },
+ { 0x0000a258, 0x0ccb5380 },
+ { 0x0000a25c, 0x15151501 },
+ { 0x0000a260, 0xdfa90f01 },
+ { 0x0000a268, 0x00000000 },
+ { 0x0000a26c, 0x0ebae9e6 },
+ { 0x0000d270, 0x0d820820 },
+ { 0x0000a278, 0x318c6318 },
+ { 0x0000a27c, 0x050c0318 },
+ { 0x0000d35c, 0x07ffffef },
+ { 0x0000d360, 0x0fffffe7 },
+ { 0x0000d364, 0x17ffffe5 },
+ { 0x0000d368, 0x1fffffe4 },
+ { 0x0000d36c, 0x37ffffe3 },
+ { 0x0000d370, 0x3fffffe3 },
+ { 0x0000d374, 0x57ffffe3 },
+ { 0x0000d378, 0x5fffffe2 },
+ { 0x0000d37c, 0x7fffffe2 },
+ { 0x0000d380, 0x7f3c7bba },
+ { 0x0000d384, 0xf3307ff0 },
+ { 0x0000a388, 0x0c000000 },
+ { 0x0000a38c, 0x20202020 },
+ { 0x0000a390, 0x20202020 },
+ { 0x0000a394, 0x318c6318 },
+ { 0x0000a398, 0x00000318 },
+ { 0x0000a39c, 0x00000001 },
+ { 0x0000a3a0, 0x00000000 },
+ { 0x0000a3a4, 0x00000000 },
+ { 0x0000a3a8, 0x00000000 },
+ { 0x0000a3ac, 0x00000000 },
+ { 0x0000a3b0, 0x00000000 },
+ { 0x0000a3b4, 0x00000000 },
+ { 0x0000a3b8, 0x00000000 },
+ { 0x0000a3bc, 0x00000000 },
+ { 0x0000a3c0, 0x00000000 },
+ { 0x0000a3c4, 0x00000000 },
+ { 0x0000a3cc, 0x20202020 },
+ { 0x0000a3d0, 0x20202020 },
+ { 0x0000a3d4, 0x20202020 },
+ { 0x0000a3dc, 0x318c6318 },
+ { 0x0000a3e0, 0x00000318 },
+ { 0x0000a3e4, 0x00000000 },
+ { 0x0000a3e8, 0x18c43433 },
+ { 0x0000a3ec, 0x00f70081 },
+ { 0x00007800, 0x00140000 },
+ { 0x00007804, 0x0e4548d8 },
+ { 0x00007808, 0x54214514 },
+ { 0x0000780c, 0x02025820 },
+ { 0x00007810, 0x71c0d388 },
+ { 0x00007814, 0x924934a8 },
+ { 0x0000781c, 0x00000000 },
+ { 0x00007820, 0x00000c04 },
+ { 0x00007824, 0x00d86fff },
+ { 0x00007828, 0x26d2491b },
+ { 0x0000782c, 0x6e36d97b },
+ { 0x00007830, 0xedb6d96e },
+ { 0x00007834, 0x71400087 },
+ { 0x00007838, 0xfac68801 },
+ { 0x0000783c, 0x0001fffe },
+ { 0x00007840, 0xffeb1a20 },
+ { 0x00007844, 0x000c0db6 },
+ { 0x00007848, 0x6db61b6f },
+ { 0x0000784c, 0x6d9b66db },
+ { 0x00007850, 0x6d8c6dba },
+ { 0x00007854, 0x00040000 },
+ { 0x00007858, 0xdb003012 },
+ { 0x0000785c, 0x04924914 },
+ { 0x00007860, 0x21084210 },
+ { 0x00007864, 0xf7d7ffde },
+ { 0x00007868, 0xc2034080 },
+ { 0x0000786c, 0x48609eb4 },
+ { 0x00007870, 0x10142c00 },
+};
-static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = {
+static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = {
+ {0x00004040, 0x9248fd00 },
+ {0x00004040, 0x24924924 },
+ {0x00004040, 0xa8000019 },
+ {0x00004040, 0x13160820 },
+ {0x00004040, 0xe5980560 },
+ {0x00004040, 0xc01dcffd },
+ {0x00004040, 0x1aaabe41 },
+ {0x00004040, 0xbe105554 },
+ {0x00004040, 0x00043007 },
+ {0x00004044, 0x00000000 },
+};
+
+static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = {
{0x00004040, 0x9248fd00 },
{0x00004040, 0x24924924 },
{0x00004040, 0xa8000019 },
{0x00004040, 0x13160820 },
{0x00004040, 0xe5980560 },
- {0x00004040, 0x401dcffd },
- {0x00004040, 0x1aaabe40 },
+ {0x00004040, 0xc01dcffc },
+ {0x00004040, 0x1aaabe41 },
{0x00004040, 0xbe105554 },
{0x00004040, 0x00043007 },
{0x00004044, 0x00000000 },
diff --git a/drivers/net/wireless/ath9k/mac.c b/drivers/net/wireless/ath9k/mac.c
new file mode 100644
index 000000000000..af32d091dc38
--- /dev/null
+++ b/drivers/net/wireless/ath9k/mac.c
@@ -0,0 +1,946 @@
+/*
+ * Copyright (c) 2008 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "core.h"
+#include "hw.h"
+#include "reg.h"
+#include "phy.h"
+
+static void ath9k_hw_set_txq_interrupts(struct ath_hal *ah,
+ struct ath9k_tx_queue_info *qi)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT,
+ "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n",
+ ahp->ah_txOkInterruptMask, ahp->ah_txErrInterruptMask,
+ ahp->ah_txDescInterruptMask, ahp->ah_txEolInterruptMask,
+ ahp->ah_txUrnInterruptMask);
+
+ REG_WRITE(ah, AR_IMR_S0,
+ SM(ahp->ah_txOkInterruptMask, AR_IMR_S0_QCU_TXOK)
+ | SM(ahp->ah_txDescInterruptMask, AR_IMR_S0_QCU_TXDESC));
+ REG_WRITE(ah, AR_IMR_S1,
+ SM(ahp->ah_txErrInterruptMask, AR_IMR_S1_QCU_TXERR)
+ | SM(ahp->ah_txEolInterruptMask, AR_IMR_S1_QCU_TXEOL));
+ REG_RMW_FIELD(ah, AR_IMR_S2,
+ AR_IMR_S2_QCU_TXURN, ahp->ah_txUrnInterruptMask);
+}
+
+u32 ath9k_hw_gettxbuf(struct ath_hal *ah, u32 q)
+{
+ return REG_READ(ah, AR_QTXDP(q));
+}
+
+bool ath9k_hw_puttxbuf(struct ath_hal *ah, u32 q, u32 txdp)
+{
+ REG_WRITE(ah, AR_QTXDP(q), txdp);
+
+ return true;
+}
+
+bool ath9k_hw_txstart(struct ath_hal *ah, u32 q)
+{
+ DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %u\n", q);
+
+ REG_WRITE(ah, AR_Q_TXE, 1 << q);
+
+ return true;
+}
+
+u32 ath9k_hw_numtxpending(struct ath_hal *ah, u32 q)
+{
+ u32 npend;
+
+ npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT;
+ if (npend == 0) {
+
+ if (REG_READ(ah, AR_Q_TXE) & (1 << q))
+ npend = 1;
+ }
+
+ return npend;
+}
+
+bool ath9k_hw_updatetxtriglevel(struct ath_hal *ah, bool bIncTrigLevel)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ u32 txcfg, curLevel, newLevel;
+ enum ath9k_int omask;
+
+ if (ah->ah_txTrigLevel >= MAX_TX_FIFO_THRESHOLD)
+ return false;
+
+ omask = ath9k_hw_set_interrupts(ah, ahp->ah_maskReg & ~ATH9K_INT_GLOBAL);
+
+ txcfg = REG_READ(ah, AR_TXCFG);
+ curLevel = MS(txcfg, AR_FTRIG);
+ newLevel = curLevel;
+ if (bIncTrigLevel) {
+ if (curLevel < MAX_TX_FIFO_THRESHOLD)
+ newLevel++;
+ } else if (curLevel > MIN_TX_FIFO_THRESHOLD)
+ newLevel--;
+ if (newLevel != curLevel)
+ REG_WRITE(ah, AR_TXCFG,
+ (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG));
+
+ ath9k_hw_set_interrupts(ah, omask);
+
+ ah->ah_txTrigLevel = newLevel;
+
+ return newLevel != curLevel;
+}
+
+bool ath9k_hw_stoptxdma(struct ath_hal *ah, u32 q)
+{
+ u32 tsfLow, j, wait;
+
+ REG_WRITE(ah, AR_Q_TXD, 1 << q);
+
+ for (wait = 1000; wait != 0; wait--) {
+ if (ath9k_hw_numtxpending(ah, q) == 0)
+ break;
+ udelay(100);
+ }
+
+ if (ath9k_hw_numtxpending(ah, q)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
+ "%s: Num of pending TX Frames %d on Q %d\n",
+ __func__, ath9k_hw_numtxpending(ah, q), q);
+
+ for (j = 0; j < 2; j++) {
+ tsfLow = REG_READ(ah, AR_TSF_L32);
+ REG_WRITE(ah, AR_QUIET2,
+ SM(10, AR_QUIET2_QUIET_DUR));
+ REG_WRITE(ah, AR_QUIET_PERIOD, 100);
+ REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
+ REG_SET_BIT(ah, AR_TIMER_MODE,
+ AR_QUIET_TIMER_EN);
+
+ if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
+ break;
+
+ DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
+ "TSF have moved while trying to set "
+ "quiet time TSF: 0x%08x\n", tsfLow);
+ }
+
+ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+
+ udelay(200);
+ REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
+
+ wait = 1000;
+
+ while (ath9k_hw_numtxpending(ah, q)) {
+ if ((--wait) == 0) {
+ DPRINTF(ah->ah_sc, ATH_DBG_XMIT,
+ "Failed to stop Tx DMA in 100 "
+ "msec after killing last frame\n");
+ break;
+ }
+ udelay(100);
+ }
+
+ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+ }
+
+ REG_WRITE(ah, AR_Q_TXD, 0);
+
+ return wait != 0;
+}
+
+bool ath9k_hw_filltxdesc(struct ath_hal *ah, struct ath_desc *ds,
+ u32 segLen, bool firstSeg,
+ bool lastSeg, const struct ath_desc *ds0)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ if (firstSeg) {
+ ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore);
+ } else if (lastSeg) {
+ ads->ds_ctl0 = 0;
+ ads->ds_ctl1 = segLen;
+ ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
+ ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
+ } else {
+ ads->ds_ctl0 = 0;
+ ads->ds_ctl1 = segLen | AR_TxMore;
+ ads->ds_ctl2 = 0;
+ ads->ds_ctl3 = 0;
+ }
+ ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
+ ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
+ ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
+ ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
+ ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
+
+ return true;
+}
+
+void ath9k_hw_cleartxdesc(struct ath_hal *ah, struct ath_desc *ds)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ ads->ds_txstatus0 = ads->ds_txstatus1 = 0;
+ ads->ds_txstatus2 = ads->ds_txstatus3 = 0;
+ ads->ds_txstatus4 = ads->ds_txstatus5 = 0;
+ ads->ds_txstatus6 = ads->ds_txstatus7 = 0;
+ ads->ds_txstatus8 = ads->ds_txstatus9 = 0;
+}
+
+int ath9k_hw_txprocdesc(struct ath_hal *ah, struct ath_desc *ds)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ if ((ads->ds_txstatus9 & AR_TxDone) == 0)
+ return -EINPROGRESS;
+
+ ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum);
+ ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp;
+ ds->ds_txstat.ts_status = 0;
+ ds->ds_txstat.ts_flags = 0;
+
+ if (ads->ds_txstatus1 & AR_ExcessiveRetries)
+ ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY;
+ if (ads->ds_txstatus1 & AR_Filtered)
+ ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT;
+ if (ads->ds_txstatus1 & AR_FIFOUnderrun) {
+ ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO;
+ ath9k_hw_updatetxtriglevel(ah, true);
+ }
+ if (ads->ds_txstatus9 & AR_TxOpExceeded)
+ ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP;
+ if (ads->ds_txstatus1 & AR_TxTimerExpired)
+ ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED;
+
+ if (ads->ds_txstatus1 & AR_DescCfgErr)
+ ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR;
+ if (ads->ds_txstatus1 & AR_TxDataUnderrun) {
+ ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN;
+ ath9k_hw_updatetxtriglevel(ah, true);
+ }
+ if (ads->ds_txstatus1 & AR_TxDelimUnderrun) {
+ ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN;
+ ath9k_hw_updatetxtriglevel(ah, true);
+ }
+ if (ads->ds_txstatus0 & AR_TxBaStatus) {
+ ds->ds_txstat.ts_flags |= ATH9K_TX_BA;
+ ds->ds_txstat.ba_low = ads->AR_BaBitmapLow;
+ ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh;
+ }
+
+ ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx);
+ switch (ds->ds_txstat.ts_rateindex) {
+ case 0:
+ ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0);
+ break;
+ case 1:
+ ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1);
+ break;
+ case 2:
+ ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2);
+ break;
+ case 3:
+ ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3);
+ break;
+ }
+
+ ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined);
+ ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00);
+ ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01);
+ ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02);
+ ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10);
+ ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11);
+ ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12);
+ ds->ds_txstat.evm0 = ads->AR_TxEVM0;
+ ds->ds_txstat.evm1 = ads->AR_TxEVM1;
+ ds->ds_txstat.evm2 = ads->AR_TxEVM2;
+ ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt);
+ ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt);
+ ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt);
+ ds->ds_txstat.ts_antenna = 1;
+
+ return 0;
+}
+
+void ath9k_hw_set11n_txdesc(struct ath_hal *ah, struct ath_desc *ds,
+ u32 pktLen, enum ath9k_pkt_type type, u32 txPower,
+ u32 keyIx, enum ath9k_key_type keyType, u32 flags)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ txPower += ahp->ah_txPowerIndexOffset;
+ if (txPower > 63)
+ txPower = 63;
+
+ ads->ds_ctl0 = (pktLen & AR_FrameLen)
+ | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
+ | SM(txPower, AR_XmitPower)
+ | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
+ | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0)
+ | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
+ | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0);
+
+ ads->ds_ctl1 =
+ (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0)
+ | SM(type, AR_FrameType)
+ | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0)
+ | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0)
+ | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0);
+
+ ads->ds_ctl6 = SM(keyType, AR_EncrType);
+
+ if (AR_SREV_9285(ah)) {
+ ads->ds_ctl8 = 0;
+ ads->ds_ctl9 = 0;
+ ads->ds_ctl10 = 0;
+ ads->ds_ctl11 = 0;
+ }
+}
+
+void ath9k_hw_set11n_ratescenario(struct ath_hal *ah, struct ath_desc *ds,
+ struct ath_desc *lastds,
+ u32 durUpdateEn, u32 rtsctsRate,
+ u32 rtsctsDuration,
+ struct ath9k_11n_rate_series series[],
+ u32 nseries, u32 flags)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+ struct ar5416_desc *last_ads = AR5416DESC(lastds);
+ u32 ds_ctl0;
+
+ (void) nseries;
+ (void) rtsctsDuration;
+
+ if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) {
+ ds_ctl0 = ads->ds_ctl0;
+
+ if (flags & ATH9K_TXDESC_RTSENA) {
+ ds_ctl0 &= ~AR_CTSEnable;
+ ds_ctl0 |= AR_RTSEnable;
+ } else {
+ ds_ctl0 &= ~AR_RTSEnable;
+ ds_ctl0 |= AR_CTSEnable;
+ }
+
+ ads->ds_ctl0 = ds_ctl0;
+ } else {
+ ads->ds_ctl0 =
+ (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable));
+ }
+
+ ads->ds_ctl2 = set11nTries(series, 0)
+ | set11nTries(series, 1)
+ | set11nTries(series, 2)
+ | set11nTries(series, 3)
+ | (durUpdateEn ? AR_DurUpdateEna : 0)
+ | SM(0, AR_BurstDur);
+
+ ads->ds_ctl3 = set11nRate(series, 0)
+ | set11nRate(series, 1)
+ | set11nRate(series, 2)
+ | set11nRate(series, 3);
+
+ ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0)
+ | set11nPktDurRTSCTS(series, 1);
+
+ ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2)
+ | set11nPktDurRTSCTS(series, 3);
+
+ ads->ds_ctl7 = set11nRateFlags(series, 0)
+ | set11nRateFlags(series, 1)
+ | set11nRateFlags(series, 2)
+ | set11nRateFlags(series, 3)
+ | SM(rtsctsRate, AR_RTSCTSRate);
+ last_ads->ds_ctl2 = ads->ds_ctl2;
+ last_ads->ds_ctl3 = ads->ds_ctl3;
+}
+
+void ath9k_hw_set11n_aggr_first(struct ath_hal *ah, struct ath_desc *ds,
+ u32 aggrLen)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
+ ads->ds_ctl6 &= ~AR_AggrLen;
+ ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
+}
+
+void ath9k_hw_set11n_aggr_middle(struct ath_hal *ah, struct ath_desc *ds,
+ u32 numDelims)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+ unsigned int ctl6;
+
+ ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
+
+ ctl6 = ads->ds_ctl6;
+ ctl6 &= ~AR_PadDelim;
+ ctl6 |= SM(numDelims, AR_PadDelim);
+ ads->ds_ctl6 = ctl6;
+}
+
+void ath9k_hw_set11n_aggr_last(struct ath_hal *ah, struct ath_desc *ds)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ ads->ds_ctl1 |= AR_IsAggr;
+ ads->ds_ctl1 &= ~AR_MoreAggr;
+ ads->ds_ctl6 &= ~AR_PadDelim;
+}
+
+void ath9k_hw_clr11n_aggr(struct ath_hal *ah, struct ath_desc *ds)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr);
+}
+
+void ath9k_hw_set11n_burstduration(struct ath_hal *ah, struct ath_desc *ds,
+ u32 burstDuration)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ ads->ds_ctl2 &= ~AR_BurstDur;
+ ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
+}
+
+void ath9k_hw_set11n_virtualmorefrag(struct ath_hal *ah, struct ath_desc *ds,
+ u32 vmf)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+
+ if (vmf)
+ ads->ds_ctl0 |= AR_VirtMoreFrag;
+ else
+ ads->ds_ctl0 &= ~AR_VirtMoreFrag;
+}
+
+void ath9k_hw_gettxintrtxqs(struct ath_hal *ah, u32 *txqs)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+
+ *txqs &= ahp->ah_intrTxqs;
+ ahp->ah_intrTxqs &= ~(*txqs);
+}
+
+bool ath9k_hw_set_txq_props(struct ath_hal *ah, int q,
+ const struct ath9k_tx_queue_info *qinfo)
+{
+ u32 cw;
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+ struct ath9k_tx_queue_info *qi;
+
+ if (q >= pCap->total_queues) {
+ DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
+ return false;
+ }
+
+ qi = &ahp->ah_txq[q];
+ if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+ DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n");
+ return false;
+ }
+
+ DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %p\n", qi);
+
+ qi->tqi_ver = qinfo->tqi_ver;
+ qi->tqi_subtype = qinfo->tqi_subtype;
+ qi->tqi_qflags = qinfo->tqi_qflags;
+ qi->tqi_priority = qinfo->tqi_priority;
+ if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT)
+ qi->tqi_aifs = min(qinfo->tqi_aifs, 255U);
+ else
+ qi->tqi_aifs = INIT_AIFS;
+ if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) {
+ cw = min(qinfo->tqi_cwmin, 1024U);
+ qi->tqi_cwmin = 1;
+ while (qi->tqi_cwmin < cw)
+ qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1;
+ } else
+ qi->tqi_cwmin = qinfo->tqi_cwmin;
+ if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) {
+ cw = min(qinfo->tqi_cwmax, 1024U);
+ qi->tqi_cwmax = 1;
+ while (qi->tqi_cwmax < cw)
+ qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1;
+ } else
+ qi->tqi_cwmax = INIT_CWMAX;
+
+ if (qinfo->tqi_shretry != 0)
+ qi->tqi_shretry = min((u32) qinfo->tqi_shretry, 15U);
+ else
+ qi->tqi_shretry = INIT_SH_RETRY;
+ if (qinfo->tqi_lgretry != 0)
+ qi->tqi_lgretry = min((u32) qinfo->tqi_lgretry, 15U);
+ else
+ qi->tqi_lgretry = INIT_LG_RETRY;
+ qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod;
+ qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit;
+ qi->tqi_burstTime = qinfo->tqi_burstTime;
+ qi->tqi_readyTime = qinfo->tqi_readyTime;
+
+ switch (qinfo->tqi_subtype) {
+ case ATH9K_WME_UPSD:
+ if (qi->tqi_type == ATH9K_TX_QUEUE_DATA)
+ qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS;
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+bool ath9k_hw_get_txq_props(struct ath_hal *ah, int q,
+ struct ath9k_tx_queue_info *qinfo)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+ struct ath9k_tx_queue_info *qi;
+
+ if (q >= pCap->total_queues) {
+ DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
+ return false;
+ }
+
+ qi = &ahp->ah_txq[q];
+ if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+ DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue\n");
+ return false;
+ }
+
+ qinfo->tqi_qflags = qi->tqi_qflags;
+ qinfo->tqi_ver = qi->tqi_ver;
+ qinfo->tqi_subtype = qi->tqi_subtype;
+ qinfo->tqi_qflags = qi->tqi_qflags;
+ qinfo->tqi_priority = qi->tqi_priority;
+ qinfo->tqi_aifs = qi->tqi_aifs;
+ qinfo->tqi_cwmin = qi->tqi_cwmin;
+ qinfo->tqi_cwmax = qi->tqi_cwmax;
+ qinfo->tqi_shretry = qi->tqi_shretry;
+ qinfo->tqi_lgretry = qi->tqi_lgretry;
+ qinfo->tqi_cbrPeriod = qi->tqi_cbrPeriod;
+ qinfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit;
+ qinfo->tqi_burstTime = qi->tqi_burstTime;
+ qinfo->tqi_readyTime = qi->tqi_readyTime;
+
+ return true;
+}
+
+int ath9k_hw_setuptxqueue(struct ath_hal *ah, enum ath9k_tx_queue type,
+ const struct ath9k_tx_queue_info *qinfo)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_tx_queue_info *qi;
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+ int q;
+
+ switch (type) {
+ case ATH9K_TX_QUEUE_BEACON:
+ q = pCap->total_queues - 1;
+ break;
+ case ATH9K_TX_QUEUE_CAB:
+ q = pCap->total_queues - 2;
+ break;
+ case ATH9K_TX_QUEUE_PSPOLL:
+ q = 1;
+ break;
+ case ATH9K_TX_QUEUE_UAPSD:
+ q = pCap->total_queues - 3;
+ break;
+ case ATH9K_TX_QUEUE_DATA:
+ for (q = 0; q < pCap->total_queues; q++)
+ if (ahp->ah_txq[q].tqi_type ==
+ ATH9K_TX_QUEUE_INACTIVE)
+ break;
+ if (q == pCap->total_queues) {
+ DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
+ "no available tx queue\n");
+ return -1;
+ }
+ break;
+ default:
+ DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "bad tx queue type %u\n", type);
+ return -1;
+ }
+
+ DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "queue %u\n", q);
+
+ qi = &ahp->ah_txq[q];
+ if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) {
+ DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
+ "tx queue %u already active\n", q);
+ return -1;
+ }
+ memset(qi, 0, sizeof(struct ath9k_tx_queue_info));
+ qi->tqi_type = type;
+ if (qinfo == NULL) {
+ qi->tqi_qflags =
+ TXQ_FLAG_TXOKINT_ENABLE
+ | TXQ_FLAG_TXERRINT_ENABLE
+ | TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE;
+ qi->tqi_aifs = INIT_AIFS;
+ qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT;
+ qi->tqi_cwmax = INIT_CWMAX;
+ qi->tqi_shretry = INIT_SH_RETRY;
+ qi->tqi_lgretry = INIT_LG_RETRY;
+ qi->tqi_physCompBuf = 0;
+ } else {
+ qi->tqi_physCompBuf = qinfo->tqi_physCompBuf;
+ (void) ath9k_hw_set_txq_props(ah, q, qinfo);
+ }
+
+ return q;
+}
+
+bool ath9k_hw_releasetxqueue(struct ath_hal *ah, u32 q)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+ struct ath9k_tx_queue_info *qi;
+
+ if (q >= pCap->total_queues) {
+ DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
+ return false;
+ }
+ qi = &ahp->ah_txq[q];
+ if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+ DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue %u\n", q);
+ return false;
+ }
+
+ DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "release queue %u\n", q);
+
+ qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE;
+ ahp->ah_txOkInterruptMask &= ~(1 << q);
+ ahp->ah_txErrInterruptMask &= ~(1 << q);
+ ahp->ah_txDescInterruptMask &= ~(1 << q);
+ ahp->ah_txEolInterruptMask &= ~(1 << q);
+ ahp->ah_txUrnInterruptMask &= ~(1 << q);
+ ath9k_hw_set_txq_interrupts(ah, qi);
+
+ return true;
+}
+
+bool ath9k_hw_resettxqueue(struct ath_hal *ah, u32 q)
+{
+ struct ath_hal_5416 *ahp = AH5416(ah);
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+ struct ath9k_channel *chan = ah->ah_curchan;
+ struct ath9k_tx_queue_info *qi;
+ u32 cwMin, chanCwMin, value;
+
+ if (q >= pCap->total_queues) {
+ DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "invalid queue num %u\n", q);
+ return false;
+ }
+
+ qi = &ahp->ah_txq[q];
+ if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
+ DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "inactive queue %u\n", q);
+ return true;
+ }
+
+ DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "reset queue %u\n", q);
+
+ if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) {
+ if (chan && IS_CHAN_B(chan))
+ chanCwMin = INIT_CWMIN_11B;
+ else
+ chanCwMin = INIT_CWMIN;
+
+ for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1);
+ } else
+ cwMin = qi->tqi_cwmin;
+
+ REG_WRITE(ah, AR_DLCL_IFS(q),
+ SM(cwMin, AR_D_LCL_IFS_CWMIN) |
+ SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) |
+ SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS));
+
+ REG_WRITE(ah, AR_DRETRY_LIMIT(q),
+ SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) |
+ SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) |
+ SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH));
+
+ REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ);
+ REG_WRITE(ah, AR_DMISC(q),
+ AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2);
+
+ if (qi->tqi_cbrPeriod) {
+ REG_WRITE(ah, AR_QCBRCFG(q),
+ SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) |
+ SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH));
+ REG_WRITE(ah, AR_QMISC(q),
+ REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_CBR |
+ (qi->tqi_cbrOverflowLimit ?
+ AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0));
+ }
+ if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) {
+ REG_WRITE(ah, AR_QRDYTIMECFG(q),
+ SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) |
+ AR_Q_RDYTIMECFG_EN);
+ }
+
+ REG_WRITE(ah, AR_DCHNTIME(q),
+ SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) |
+ (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0));
+
+ if (qi->tqi_burstTime
+ && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) {
+ REG_WRITE(ah, AR_QMISC(q),
+ REG_READ(ah, AR_QMISC(q)) |
+ AR_Q_MISC_RDYTIME_EXP_POLICY);
+
+ }
+
+ if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) {
+ REG_WRITE(ah, AR_DMISC(q),
+ REG_READ(ah, AR_DMISC(q)) |
+ AR_D_MISC_POST_FR_BKOFF_DIS);
+ }
+ if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) {
+ REG_WRITE(ah, AR_DMISC(q),
+ REG_READ(ah, AR_DMISC(q)) |
+ AR_D_MISC_FRAG_BKOFF_EN);
+ }
+ switch (qi->tqi_type) {
+ case ATH9K_TX_QUEUE_BEACON:
+ REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
+ | AR_Q_MISC_FSP_DBA_GATED
+ | AR_Q_MISC_BEACON_USE
+ | AR_Q_MISC_CBR_INCR_DIS1);
+
+ REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
+ | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
+ AR_D_MISC_ARB_LOCKOUT_CNTRL_S)
+ | AR_D_MISC_BEACON_USE
+ | AR_D_MISC_POST_FR_BKOFF_DIS);
+ break;
+ case ATH9K_TX_QUEUE_CAB:
+ REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q))
+ | AR_Q_MISC_FSP_DBA_GATED
+ | AR_Q_MISC_CBR_INCR_DIS1
+ | AR_Q_MISC_CBR_INCR_DIS0);
+ value = (qi->tqi_readyTime -
+ (ah->ah_config.sw_beacon_response_time -
+ ah->ah_config.dma_beacon_response_time) -
+ ah->ah_config.additional_swba_backoff) * 1024;
+ REG_WRITE(ah, AR_QRDYTIMECFG(q),
+ value | AR_Q_RDYTIMECFG_EN);
+ REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q))
+ | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL <<
+ AR_D_MISC_ARB_LOCKOUT_CNTRL_S));
+ break;
+ case ATH9K_TX_QUEUE_PSPOLL:
+ REG_WRITE(ah, AR_QMISC(q),
+ REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1);
+ break;
+ case ATH9K_TX_QUEUE_UAPSD:
+ REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) |
+ AR_D_MISC_POST_FR_BKOFF_DIS);
+ break;
+ default:
+ break;
+ }
+
+ if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) {
+ REG_WRITE(ah, AR_DMISC(q),
+ REG_READ(ah, AR_DMISC(q)) |
+ SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL,
+ AR_D_MISC_ARB_LOCKOUT_CNTRL) |
+ AR_D_MISC_POST_FR_BKOFF_DIS);
+ }
+
+ if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE)
+ ahp->ah_txOkInterruptMask |= 1 << q;
+ else
+ ahp->ah_txOkInterruptMask &= ~(1 << q);
+ if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE)
+ ahp->ah_txErrInterruptMask |= 1 << q;
+ else
+ ahp->ah_txErrInterruptMask &= ~(1 << q);
+ if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE)
+ ahp->ah_txDescInterruptMask |= 1 << q;
+ else
+ ahp->ah_txDescInterruptMask &= ~(1 << q);
+ if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE)
+ ahp->ah_txEolInterruptMask |= 1 << q;
+ else
+ ahp->ah_txEolInterruptMask &= ~(1 << q);
+ if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE)
+ ahp->ah_txUrnInterruptMask |= 1 << q;
+ else
+ ahp->ah_txUrnInterruptMask &= ~(1 << q);
+ ath9k_hw_set_txq_interrupts(ah, qi);
+
+ return true;
+}
+
+int ath9k_hw_rxprocdesc(struct ath_hal *ah, struct ath_desc *ds,
+ u32 pa, struct ath_desc *nds, u64 tsf)
+{
+ struct ar5416_desc ads;
+ struct ar5416_desc *adsp = AR5416DESC(ds);
+ u32 phyerr;
+
+ if ((adsp->ds_rxstatus8 & AR_RxDone) == 0)
+ return -EINPROGRESS;
+
+ ads.u.rx = adsp->u.rx;
+
+ ds->ds_rxstat.rs_status = 0;
+ ds->ds_rxstat.rs_flags = 0;
+
+ ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen;
+ ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp;
+
+ ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined);
+ ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt00);
+ ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt01);
+ ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, AR_RxRSSIAnt02);
+ ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt10);
+ ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt11);
+ ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, AR_RxRSSIAnt12);
+ if (ads.ds_rxstatus8 & AR_RxKeyIdxValid)
+ ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx);
+ else
+ ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID;
+
+ ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads));
+ ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0;
+
+ ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0;
+ ds->ds_rxstat.rs_moreaggr =
+ (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0;
+ ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna);
+ ds->ds_rxstat.rs_flags =
+ (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0;
+ ds->ds_rxstat.rs_flags |=
+ (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0;
+
+ if (ads.ds_rxstatus8 & AR_PreDelimCRCErr)
+ ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE;
+ if (ads.ds_rxstatus8 & AR_PostDelimCRCErr)
+ ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST;
+ if (ads.ds_rxstatus8 & AR_DecryptBusyErr)
+ ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY;
+
+ if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
+ if (ads.ds_rxstatus8 & AR_CRCErr)
+ ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC;
+ else if (ads.ds_rxstatus8 & AR_PHYErr) {
+ ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY;
+ phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
+ ds->ds_rxstat.rs_phyerr = phyerr;
+ } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
+ ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT;
+ else if (ads.ds_rxstatus8 & AR_MichaelErr)
+ ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC;
+ }
+
+ return 0;
+}
+
+bool ath9k_hw_setuprxdesc(struct ath_hal *ah, struct ath_desc *ds,
+ u32 size, u32 flags)
+{
+ struct ar5416_desc *ads = AR5416DESC(ds);
+ struct ath9k_hw_capabilities *pCap = &ah->ah_caps;
+
+ ads->ds_ctl1 = size & AR_BufLen;
+ if (flags & ATH9K_RXDESC_INTREQ)
+ ads->ds_ctl1 |= AR_RxIntrReq;
+
+ ads->ds_rxstatus8 &= ~AR_RxDone;
+ if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
+ memset(&(ads->u), 0, sizeof(ads->u));
+
+ return true;
+}
+
+bool ath9k_hw_setrxabort(struct ath_hal *ah, bool set)
+{
+ u32 reg;
+
+ if (set) {
+ REG_SET_BIT(ah, AR_DIAG_SW,
+ (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+
+ if (!ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, 0)) {
+ REG_CLR_BIT(ah, AR_DIAG_SW,
+ (AR_DIAG_RX_DIS |
+ AR_DIAG_RX_ABORT));
+
+ reg = REG_READ(ah, AR_OBS_BUS_1);
+ DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
+ "rx failed to go idle in 10 ms RXSM=0x%x\n", reg);
+
+ return false;
+ }
+ } else {
+ REG_CLR_BIT(ah, AR_DIAG_SW,
+ (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+ }
+
+ return true;
+}
+
+void ath9k_hw_putrxbuf(struct ath_hal *ah, u32 rxdp)
+{
+ REG_WRITE(ah, AR_RXDP, rxdp);
+}
+
+void ath9k_hw_rxena(struct ath_hal *ah)
+{
+ REG_WRITE(ah, AR_CR, AR_CR_RXE);
+}
+
+void ath9k_hw_startpcureceive(struct ath_hal *ah)
+{
+ ath9k_enable_mib_counters(ah);
+
+ ath9k_ani_reset(ah);
+
+ REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
+}
+
+void ath9k_hw_stoppcurecv(struct ath_hal *ah)
+{
+ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
+
+ ath9k_hw_disable_mib_counters(ah);
+}
+
+bool ath9k_hw_stopdmarecv(struct ath_hal *ah)
+{
+ REG_WRITE(ah, AR_CR, AR_CR_RXD);
+
+ if (!ath9k_hw_wait(ah, AR_CR, AR_CR_RXE, 0)) {
+ DPRINTF(ah->ah_sc, ATH_DBG_QUEUE,
+ "dma failed to stop in 10ms\n"
+ "AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n",
+ REG_READ(ah, AR_CR), REG_READ(ah, AR_DIAG_SW));
+ return false;
+ } else {
+ return true;
+ }
+}
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c
index f05f584ab7bc..191eec50dc75 100644
--- a/drivers/net/wireless/ath9k/main.c
+++ b/drivers/net/wireless/ath9k/main.c
@@ -14,15 +14,13 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* mac80211 and PCI callbacks */
-
#include <linux/nl80211.h>
#include "core.h"
+#include "reg.h"
+#include "hw.h"
#define ATH_PCI_VERSION "0.1"
-#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13
-
static char *dev_info = "ath9k";
MODULE_AUTHOR("Atheros Communications");
@@ -36,9 +34,581 @@ static struct pci_device_id ath_pci_id_table[] __devinitdata = {
{ PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
+ { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */
{ 0 }
};
+static void ath_detach(struct ath_softc *sc);
+
+/* return bus cachesize in 4B word units */
+
+static void bus_read_cachesize(struct ath_softc *sc, int *csz)
+{
+ u8 u8tmp;
+
+ pci_read_config_byte(sc->pdev, PCI_CACHE_LINE_SIZE, (u8 *)&u8tmp);
+ *csz = (int)u8tmp;
+
+ /*
+ * This check was put in to avoid "unplesant" consequences if
+ * the bootrom has not fully initialized all PCI devices.
+ * Sometimes the cache line size register is not set
+ */
+
+ if (*csz == 0)
+ *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */
+}
+
+static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode)
+{
+ sc->cur_rate_table = sc->hw_rate_table[mode];
+ /*
+ * All protection frames are transmited at 2Mb/s for
+ * 11g, otherwise at 1Mb/s.
+ * XXX select protection rate index from rate table.
+ */
+ sc->sc_protrix = (mode == ATH9K_MODE_11G ? 1 : 0);
+}
+
+static enum wireless_mode ath_chan2mode(struct ath9k_channel *chan)
+{
+ if (chan->chanmode == CHANNEL_A)
+ return ATH9K_MODE_11A;
+ else if (chan->chanmode == CHANNEL_G)
+ return ATH9K_MODE_11G;
+ else if (chan->chanmode == CHANNEL_B)
+ return ATH9K_MODE_11B;
+ else if (chan->chanmode == CHANNEL_A_HT20)
+ return ATH9K_MODE_11NA_HT20;
+ else if (chan->chanmode == CHANNEL_G_HT20)
+ return ATH9K_MODE_11NG_HT20;
+ else if (chan->chanmode == CHANNEL_A_HT40PLUS)
+ return ATH9K_MODE_11NA_HT40PLUS;
+ else if (chan->chanmode == CHANNEL_A_HT40MINUS)
+ return ATH9K_MODE_11NA_HT40MINUS;
+ else if (chan->chanmode == CHANNEL_G_HT40PLUS)
+ return ATH9K_MODE_11NG_HT40PLUS;
+ else if (chan->chanmode == CHANNEL_G_HT40MINUS)
+ return ATH9K_MODE_11NG_HT40MINUS;
+
+ WARN_ON(1); /* should not get here */
+
+ return ATH9K_MODE_11B;
+}
+
+static void ath_update_txpow(struct ath_softc *sc)
+{
+ struct ath_hal *ah = sc->sc_ah;
+ u32 txpow;
+
+ if (sc->sc_curtxpow != sc->sc_config.txpowlimit) {
+ ath9k_hw_set_txpowerlimit(ah, sc->sc_config.txpowlimit);
+ /* read back in case value is clamped */
+ ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow);
+ sc->sc_curtxpow = txpow;
+ }
+}
+
+static u8 parse_mpdudensity(u8 mpdudensity)
+{
+ /*
+ * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
+ * 0 for no restriction
+ * 1 for 1/4 us
+ * 2 for 1/2 us
+ * 3 for 1 us
+ * 4 for 2 us
+ * 5 for 4 us
+ * 6 for 8 us
+ * 7 for 16 us
+ */
+ switch (mpdudensity) {
+ case 0:
+ return 0;
+ case 1:
+ case 2:
+ case 3:
+ /* Our lower layer calculations limit our precision to
+ 1 microsecond */
+ return 1;
+ case 4:
+ return 2;
+ case 5:
+ return 4;
+ case 6:
+ return 8;
+ case 7:
+ return 16;
+ default:
+ return 0;
+ }
+}
+
+static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band)
+{
+ struct ath_rate_table *rate_table = NULL;
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_rate *rate;
+ int i, maxrates;
+
+ switch (band) {
+ case IEEE80211_BAND_2GHZ:
+ rate_table = sc->hw_rate_table[ATH9K_MODE_11G];
+ break;
+ case IEEE80211_BAND_5GHZ:
+ rate_table = sc->hw_rate_table[ATH9K_MODE_11A];
+ break;
+ default:
+ break;
+ }
+
+ if (rate_table == NULL)
+ return;
+
+ sband = &sc->sbands[band];
+ rate = sc->rates[band];
+
+ if (rate_table->rate_cnt > ATH_RATE_MAX)
+ maxrates = ATH_RATE_MAX;
+ else
+ maxrates = rate_table->rate_cnt;
+
+ for (i = 0; i < maxrates; i++) {
+ rate[i].bitrate = rate_table->info[i].ratekbps / 100;
+ rate[i].hw_value = rate_table->info[i].ratecode;
+ sband->n_bitrates++;
+ DPRINTF(sc, ATH_DBG_CONFIG, "Rate: %2dMbps, ratecode: %2d\n",
+ rate[i].bitrate / 10, rate[i].hw_value);
+ }
+}
+
+static int ath_setup_channels(struct ath_softc *sc)
+{
+ struct ath_hal *ah = sc->sc_ah;
+ int nchan, i, a = 0, b = 0;
+ u8 regclassids[ATH_REGCLASSIDS_MAX];
+ u32 nregclass = 0;
+ struct ieee80211_supported_band *band_2ghz;
+ struct ieee80211_supported_band *band_5ghz;
+ struct ieee80211_channel *chan_2ghz;
+ struct ieee80211_channel *chan_5ghz;
+ struct ath9k_channel *c;
+
+ /* Fill in ah->ah_channels */
+ if (!ath9k_regd_init_channels(ah, ATH_CHAN_MAX, (u32 *)&nchan,
+ regclassids, ATH_REGCLASSIDS_MAX,
+ &nregclass, CTRY_DEFAULT, false, 1)) {
+ u32 rd = ah->ah_currentRD;
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "Unable to collect channel list; "
+ "regdomain likely %u country code %u\n",
+ rd, CTRY_DEFAULT);
+ return -EINVAL;
+ }
+
+ band_2ghz = &sc->sbands[IEEE80211_BAND_2GHZ];
+ band_5ghz = &sc->sbands[IEEE80211_BAND_5GHZ];
+ chan_2ghz = sc->channels[IEEE80211_BAND_2GHZ];
+ chan_5ghz = sc->channels[IEEE80211_BAND_5GHZ];
+
+ for (i = 0; i < nchan; i++) {
+ c = &ah->ah_channels[i];
+ if (IS_CHAN_2GHZ(c)) {
+ chan_2ghz[a].band = IEEE80211_BAND_2GHZ;
+ chan_2ghz[a].center_freq = c->channel;
+ chan_2ghz[a].max_power = c->maxTxPower;
+
+ if (c->privFlags & CHANNEL_DISALLOW_ADHOC)
+ chan_2ghz[a].flags |= IEEE80211_CHAN_NO_IBSS;
+ if (c->channelFlags & CHANNEL_PASSIVE)
+ chan_2ghz[a].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
+
+ band_2ghz->n_channels = ++a;
+
+ DPRINTF(sc, ATH_DBG_CONFIG, "2MHz channel: %d, "
+ "channelFlags: 0x%x\n",
+ c->channel, c->channelFlags);
+ } else if (IS_CHAN_5GHZ(c)) {
+ chan_5ghz[b].band = IEEE80211_BAND_5GHZ;
+ chan_5ghz[b].center_freq = c->channel;
+ chan_5ghz[b].max_power = c->maxTxPower;
+
+ if (c->privFlags & CHANNEL_DISALLOW_ADHOC)
+ chan_5ghz[b].flags |= IEEE80211_CHAN_NO_IBSS;
+ if (c->channelFlags & CHANNEL_PASSIVE)
+ chan_5ghz[b].flags |= IEEE80211_CHAN_PASSIVE_SCAN;
+
+ band_5ghz->n_channels = ++b;
+
+ DPRINTF(sc, ATH_DBG_CONFIG, "5MHz channel: %d, "
+ "channelFlags: 0x%x\n",
+ c->channel, c->channelFlags);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Set/change channels. If the channel is really being changed, it's done
+ * by reseting the chip. To accomplish this we must first cleanup any pending
+ * DMA, then restart stuff.
+*/
+static int ath_set_channel(struct ath_softc *sc, struct ath9k_channel *hchan)
+{
+ struct ath_hal *ah = sc->sc_ah;
+ bool fastcc = true, stopped;
+
+ if (sc->sc_flags & SC_OP_INVALID)
+ return -EIO;
+
+ if (hchan->channel != sc->sc_ah->ah_curchan->channel ||
+ hchan->channelFlags != sc->sc_ah->ah_curchan->channelFlags ||
+ (sc->sc_flags & SC_OP_CHAINMASK_UPDATE) ||
+ (sc->sc_flags & SC_OP_FULL_RESET)) {
+ int status;
+ /*
+ * This is only performed if the channel settings have
+ * actually changed.
+ *
+ * To switch channels clear any pending DMA operations;
+ * wait long enough for the RX fifo to drain, reset the
+ * hardware at the new frequency, and then re-enable
+ * the relevant bits of the h/w.
+ */
+ ath9k_hw_set_interrupts(ah, 0);
+ ath_draintxq(sc, false);
+ stopped = ath_stoprecv(sc);
+
+ /* XXX: do not flush receive queue here. We don't want
+ * to flush data frames already in queue because of
+ * changing channel. */
+
+ if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET))
+ fastcc = false;
+
+ DPRINTF(sc, ATH_DBG_CONFIG,
+ "(%u MHz) -> (%u MHz), cflags:%x, chanwidth: %d\n",
+ sc->sc_ah->ah_curchan->channel,
+ hchan->channel, hchan->channelFlags, sc->tx_chan_width);
+
+ spin_lock_bh(&sc->sc_resetlock);
+ if (!ath9k_hw_reset(ah, hchan, sc->tx_chan_width,
+ sc->sc_tx_chainmask, sc->sc_rx_chainmask,
+ sc->sc_ht_extprotspacing, fastcc, &status)) {
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "Unable to reset channel %u (%uMhz) "
+ "flags 0x%x hal status %u\n",
+ ath9k_hw_mhz2ieee(ah, hchan->channel,
+ hchan->channelFlags),
+ hchan->channel, hchan->channelFlags, status);
+ spin_unlock_bh(&sc->sc_resetlock);
+ return -EIO;
+ }
+ spin_unlock_bh(&sc->sc_resetlock);
+
+ sc->sc_flags &= ~SC_OP_CHAINMASK_UPDATE;
+ sc->sc_flags &= ~SC_OP_FULL_RESET;
+
+ if (ath_startrecv(sc) != 0) {
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "Unable to restart recv logic\n");
+ return -EIO;
+ }
+
+ ath_setcurmode(sc, ath_chan2mode(hchan));
+ ath_update_txpow(sc);
+ ath9k_hw_set_interrupts(ah, sc->sc_imask);
+ }
+ return 0;
+}
+
+/*
+ * This routine performs the periodic noise floor calibration function
+ * that is used to adjust and optimize the chip performance. This
+ * takes environmental changes (location, temperature) into account.
+ * When the task is complete, it reschedules itself depending on the
+ * appropriate interval that was calculated.
+ */
+static void ath_ani_calibrate(unsigned long data)
+{
+ struct ath_softc *sc;
+ struct ath_hal *ah;
+ bool longcal = false;
+ bool shortcal = false;
+ bool aniflag = false;
+ unsigned int timestamp = jiffies_to_msecs(jiffies);
+ u32 cal_interval;
+
+ sc = (struct ath_softc *)data;
+ ah = sc->sc_ah;
+
+ /*
+ * don't calibrate when we're scanning.
+ * we are most likely not on our home channel.
+ */
+ if (sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC)
+ return;
+
+ /* Long calibration runs independently of short calibration. */
+ if ((timestamp - sc->sc_ani.sc_longcal_timer) >= ATH_LONG_CALINTERVAL) {
+ longcal = true;
+ DPRINTF(sc, ATH_DBG_ANI, "longcal @%lu\n", jiffies);
+ sc->sc_ani.sc_longcal_timer = timestamp;
+ }
+
+ /* Short calibration applies only while sc_caldone is false */
+ if (!sc->sc_ani.sc_caldone) {
+ if ((timestamp - sc->sc_ani.sc_shortcal_timer) >=
+ ATH_SHORT_CALINTERVAL) {
+ shortcal = true;
+ DPRINTF(sc, ATH_DBG_ANI, "shortcal @%lu\n", jiffies);
+ sc->sc_ani.sc_shortcal_timer = timestamp;
+ sc->sc_ani.sc_resetcal_timer = timestamp;
+ }
+ } else {
+ if ((timestamp - sc->sc_ani.sc_resetcal_timer) >=
+ ATH_RESTART_CALINTERVAL) {
+ ath9k_hw_reset_calvalid(ah, ah->ah_curchan,
+ &sc->sc_ani.sc_caldone);
+ if (sc->sc_ani.sc_caldone)
+ sc->sc_ani.sc_resetcal_timer = timestamp;
+ }
+ }
+
+ /* Verify whether we must check ANI */
+ if ((timestamp - sc->sc_ani.sc_checkani_timer) >=
+ ATH_ANI_POLLINTERVAL) {
+ aniflag = true;
+ sc->sc_ani.sc_checkani_timer = timestamp;
+ }
+
+ /* Skip all processing if there's nothing to do. */
+ if (longcal || shortcal || aniflag) {
+ /* Call ANI routine if necessary */
+ if (aniflag)
+ ath9k_hw_ani_monitor(ah, &sc->sc_halstats,
+ ah->ah_curchan);
+
+ /* Perform calibration if necessary */
+ if (longcal || shortcal) {
+ bool iscaldone = false;
+
+ if (ath9k_hw_calibrate(ah, ah->ah_curchan,
+ sc->sc_rx_chainmask, longcal,
+ &iscaldone)) {
+ if (longcal)
+ sc->sc_ani.sc_noise_floor =
+ ath9k_hw_getchan_noise(ah,
+ ah->ah_curchan);
+
+ DPRINTF(sc, ATH_DBG_ANI,
+ "calibrate chan %u/%x nf: %d\n",
+ ah->ah_curchan->channel,
+ ah->ah_curchan->channelFlags,
+ sc->sc_ani.sc_noise_floor);
+ } else {
+ DPRINTF(sc, ATH_DBG_ANY,
+ "calibrate chan %u/%x failed\n",
+ ah->ah_curchan->channel,
+ ah->ah_curchan->channelFlags);
+ }
+ sc->sc_ani.sc_caldone = iscaldone;
+ }
+ }
+
+ /*
+ * Set timer interval based on previous results.
+ * The interval must be the shortest necessary to satisfy ANI,
+ * short calibration and long calibration.
+ */
+ cal_interval = ATH_LONG_CALINTERVAL;
+ if (sc->sc_ah->ah_config.enable_ani)
+ cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL);
+ if (!sc->sc_ani.sc_caldone)
+ cal_interval = min(cal_interval, (u32)ATH_SHORT_CALINTERVAL);
+
+ mod_timer(&sc->sc_ani.timer, jiffies + msecs_to_jiffies(cal_interval));
+}
+
+/*
+ * Update tx/rx chainmask. For legacy association,
+ * hard code chainmask to 1x1, for 11n association, use
+ * the chainmask configuration.
+ */
+static void ath_update_chainmask(struct ath_softc *sc, int is_ht)
+{
+ sc->sc_flags |= SC_OP_CHAINMASK_UPDATE;
+ if (is_ht) {
+ sc->sc_tx_chainmask = sc->sc_ah->ah_caps.tx_chainmask;
+ sc->sc_rx_chainmask = sc->sc_ah->ah_caps.rx_chainmask;
+ } else {
+ sc->sc_tx_chainmask = 1;
+ sc->sc_rx_chainmask = 1;
+ }
+
+ DPRINTF(sc, ATH_DBG_CONFIG, "tx chmask: %d, rx chmask: %d\n",
+ sc->sc_tx_chainmask, sc->sc_rx_chainmask);
+}
+
+static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
+{
+ struct ath_node *an;
+
+ an = (struct ath_node *)sta->drv_priv;
+
+ if (sc->sc_flags & SC_OP_TXAGGR)
+ ath_tx_node_init(sc, an);
+
+ an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
+ sta->ht_cap.ampdu_factor);
+ an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
+}
+
+static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
+{
+ struct ath_node *an = (struct ath_node *)sta->drv_priv;
+
+ if (sc->sc_flags & SC_OP_TXAGGR)
+ ath_tx_node_cleanup(sc, an);
+}
+
+static void ath9k_tasklet(unsigned long data)
+{
+ struct ath_softc *sc = (struct ath_softc *)data;
+ u32 status = sc->sc_intrstatus;
+
+ if (status & ATH9K_INT_FATAL) {
+ /* need a chip reset */
+ ath_reset(sc, false);
+ return;
+ } else {
+
+ if (status &
+ (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) {
+ spin_lock_bh(&sc->rx.rxflushlock);
+ ath_rx_tasklet(sc, 0);
+ spin_unlock_bh(&sc->rx.rxflushlock);
+ }
+ /* XXX: optimize this */
+ if (status & ATH9K_INT_TX)
+ ath_tx_tasklet(sc);
+ }
+
+ /* re-enable hardware interrupt */
+ ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask);
+}
+
+static irqreturn_t ath_isr(int irq, void *dev)
+{
+ struct ath_softc *sc = dev;
+ struct ath_hal *ah = sc->sc_ah;
+ enum ath9k_int status;
+ bool sched = false;
+
+ do {
+ if (sc->sc_flags & SC_OP_INVALID) {
+ /*
+ * The hardware is not ready/present, don't
+ * touch anything. Note this can happen early
+ * on if the IRQ is shared.
+ */
+ return IRQ_NONE;
+ }
+ if (!ath9k_hw_intrpend(ah)) { /* shared irq, not for us */
+ return IRQ_NONE;
+ }
+
+ /*
+ * Figure out the reason(s) for the interrupt. Note
+ * that the hal returns a pseudo-ISR that may include
+ * bits we haven't explicitly enabled so we mask the
+ * value to insure we only process bits we requested.
+ */
+ ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */
+
+ status &= sc->sc_imask; /* discard unasked-for bits */
+
+ /*
+ * If there are no status bits set, then this interrupt was not
+ * for me (should have been caught above).
+ */
+ if (!status)
+ return IRQ_NONE;
+
+ sc->sc_intrstatus = status;
+
+ if (status & ATH9K_INT_FATAL) {
+ /* need a chip reset */
+ sched = true;
+ } else if (status & ATH9K_INT_RXORN) {
+ /* need a chip reset */
+ sched = true;
+ } else {
+ if (status & ATH9K_INT_SWBA) {
+ /* schedule a tasklet for beacon handling */
+ tasklet_schedule(&sc->bcon_tasklet);
+ }
+ if (status & ATH9K_INT_RXEOL) {
+ /*
+ * NB: the hardware should re-read the link when
+ * RXE bit is written, but it doesn't work
+ * at least on older hardware revs.
+ */
+ sched = true;
+ }
+
+ if (status & ATH9K_INT_TXURN)
+ /* bump tx trigger level */
+ ath9k_hw_updatetxtriglevel(ah, true);
+ /* XXX: optimize this */
+ if (status & ATH9K_INT_RX)
+ sched = true;
+ if (status & ATH9K_INT_TX)
+ sched = true;
+ if (status & ATH9K_INT_BMISS)
+ sched = true;
+ /* carrier sense timeout */
+ if (status & ATH9K_INT_CST)
+ sched = true;
+ if (status & ATH9K_INT_MIB) {
+ /*
+ * Disable interrupts until we service the MIB
+ * interrupt; otherwise it will continue to
+ * fire.
+ */
+ ath9k_hw_set_interrupts(ah, 0);
+ /*
+ * Let the hal handle the event. We assume
+ * it will clear whatever condition caused
+ * the interrupt.
+ */
+ ath9k_hw_procmibevent(ah, &sc->sc_halstats);
+ ath9k_hw_set_interrupts(ah, sc->sc_imask);
+ }
+ if (status & ATH9K_INT_TIM_TIMER) {
+ if (!(ah->ah_caps.hw_caps &
+ ATH9K_HW_CAP_AUTOSLEEP)) {
+ /* Clear RxAbort bit so that we can
+ * receive frames */
+ ath9k_hw_setrxabort(ah, 0);
+ sched = true;
+ }
+ }
+ }
+ } while (0);
+
+ ath_debug_stat_interrupt(sc, status);
+
+ if (sched) {
+ /* turn off every interrupt except SWBA */
+ ath9k_hw_set_interrupts(ah, (sc->sc_imask & ATH9K_INT_SWBA));
+ tasklet_schedule(&sc->intr_tq);
+ }
+
+ return IRQ_HANDLED;
+}
+
static int ath_get_channel(struct ath_softc *sc,
struct ieee80211_channel *chan)
{
@@ -53,34 +623,39 @@ static int ath_get_channel(struct ath_softc *sc,
}
static u32 ath_get_extchanmode(struct ath_softc *sc,
- struct ieee80211_channel *chan)
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type)
{
u32 chanmode = 0;
- u8 ext_chan_offset = sc->sc_ht_info.ext_chan_offset;
- enum ath9k_ht_macmode tx_chan_width = sc->sc_ht_info.tx_chan_width;
switch (chan->band) {
case IEEE80211_BAND_2GHZ:
- if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE) &&
- (tx_chan_width == ATH9K_HT_MACMODE_20))
+ switch(channel_type) {
+ case NL80211_CHAN_NO_HT:
+ case NL80211_CHAN_HT20:
chanmode = CHANNEL_G_HT20;
- if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE) &&
- (tx_chan_width == ATH9K_HT_MACMODE_2040))
+ break;
+ case NL80211_CHAN_HT40PLUS:
chanmode = CHANNEL_G_HT40PLUS;
- if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW) &&
- (tx_chan_width == ATH9K_HT_MACMODE_2040))
+ break;
+ case NL80211_CHAN_HT40MINUS:
chanmode = CHANNEL_G_HT40MINUS;
+ break;
+ }
break;
case IEEE80211_BAND_5GHZ:
- if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE) &&
- (tx_chan_width == ATH9K_HT_MACMODE_20))
+ switch(channel_type) {
+ case NL80211_CHAN_NO_HT:
+ case NL80211_CHAN_HT20:
chanmode = CHANNEL_A_HT20;
- if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE) &&
- (tx_chan_width == ATH9K_HT_MACMODE_2040))
+ break;
+ case NL80211_CHAN_HT40PLUS:
chanmode = CHANNEL_A_HT40PLUS;
- if ((ext_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW) &&
- (tx_chan_width == ATH9K_HT_MACMODE_2040))
+ break;
+ case NL80211_CHAN_HT40MINUS:
chanmode = CHANNEL_A_HT40MINUS;
+ break;
+ }
break;
default:
break;
@@ -89,22 +664,31 @@ static u32 ath_get_extchanmode(struct ath_softc *sc,
return chanmode;
}
+static int ath_keyset(struct ath_softc *sc, u16 keyix,
+ struct ath9k_keyval *hk, const u8 mac[ETH_ALEN])
+{
+ bool status;
+
+ status = ath9k_hw_set_keycache_entry(sc->sc_ah,
+ keyix, hk, mac, false);
+
+ return status != false;
+}
-static int ath_setkey_tkip(struct ath_softc *sc,
- struct ieee80211_key_conf *key,
+static int ath_setkey_tkip(struct ath_softc *sc, u16 keyix, const u8 *key,
struct ath9k_keyval *hk,
const u8 *addr)
{
- u8 *key_rxmic = NULL;
- u8 *key_txmic = NULL;
+ const u8 *key_rxmic;
+ const u8 *key_txmic;
- key_txmic = key->key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
- key_rxmic = key->key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
+ key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY;
+ key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY;
if (addr == NULL) {
/* Group key installation */
- memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
- return ath_keyset(sc, key->keyidx, hk, addr);
+ memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
+ return ath_keyset(sc, keyix, hk, addr);
}
if (!sc->sc_splitmic) {
/*
@@ -113,34 +697,113 @@ static int ath_setkey_tkip(struct ath_softc *sc,
*/
memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic));
- return ath_keyset(sc, key->keyidx, hk, addr);
+ return ath_keyset(sc, keyix, hk, addr);
}
/*
* TX key goes at first index, RX key at +32.
* The hal handles the MIC keys at index+64.
*/
memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic));
- if (!ath_keyset(sc, key->keyidx, hk, NULL)) {
+ if (!ath_keyset(sc, keyix, hk, NULL)) {
/* Txmic entry failed. No need to proceed further */
DPRINTF(sc, ATH_DBG_KEYCACHE,
- "%s Setting TX MIC Key Failed\n", __func__);
+ "Setting TX MIC Key Failed\n");
return 0;
}
memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic));
/* XXX delete tx key on failure? */
- return ath_keyset(sc, key->keyidx+32, hk, addr);
+ return ath_keyset(sc, keyix + 32, hk, addr);
+}
+
+static int ath_reserve_key_cache_slot_tkip(struct ath_softc *sc)
+{
+ int i;
+
+ for (i = IEEE80211_WEP_NKID; i < sc->sc_keymax / 2; i++) {
+ if (test_bit(i, sc->sc_keymap) ||
+ test_bit(i + 64, sc->sc_keymap))
+ continue; /* At least one part of TKIP key allocated */
+ if (sc->sc_splitmic &&
+ (test_bit(i + 32, sc->sc_keymap) ||
+ test_bit(i + 64 + 32, sc->sc_keymap)))
+ continue; /* At least one part of TKIP key allocated */
+
+ /* Found a free slot for a TKIP key */
+ return i;
+ }
+ return -1;
+}
+
+static int ath_reserve_key_cache_slot(struct ath_softc *sc)
+{
+ int i;
+
+ /* First, try to find slots that would not be available for TKIP. */
+ if (sc->sc_splitmic) {
+ for (i = IEEE80211_WEP_NKID; i < sc->sc_keymax / 4; i++) {
+ if (!test_bit(i, sc->sc_keymap) &&
+ (test_bit(i + 32, sc->sc_keymap) ||
+ test_bit(i + 64, sc->sc_keymap) ||
+ test_bit(i + 64 + 32, sc->sc_keymap)))
+ return i;
+ if (!test_bit(i + 32, sc->sc_keymap) &&
+ (test_bit(i, sc->sc_keymap) ||
+ test_bit(i + 64, sc->sc_keymap) ||
+ test_bit(i + 64 + 32, sc->sc_keymap)))
+ return i + 32;
+ if (!test_bit(i + 64, sc->sc_keymap) &&
+ (test_bit(i , sc->sc_keymap) ||
+ test_bit(i + 32, sc->sc_keymap) ||
+ test_bit(i + 64 + 32, sc->sc_keymap)))
+ return i + 64;
+ if (!test_bit(i + 64 + 32, sc->sc_keymap) &&
+ (test_bit(i, sc->sc_keymap) ||
+ test_bit(i + 32, sc->sc_keymap) ||
+ test_bit(i + 64, sc->sc_keymap)))
+ return i + 64 + 32;
+ }
+ } else {
+ for (i = IEEE80211_WEP_NKID; i < sc->sc_keymax / 2; i++) {
+ if (!test_bit(i, sc->sc_keymap) &&
+ test_bit(i + 64, sc->sc_keymap))
+ return i;
+ if (test_bit(i, sc->sc_keymap) &&
+ !test_bit(i + 64, sc->sc_keymap))
+ return i + 64;
+ }
+ }
+
+ /* No partially used TKIP slots, pick any available slot */
+ for (i = IEEE80211_WEP_NKID; i < sc->sc_keymax; i++) {
+ /* Do not allow slots that could be needed for TKIP group keys
+ * to be used. This limitation could be removed if we know that
+ * TKIP will not be used. */
+ if (i >= 64 && i < 64 + IEEE80211_WEP_NKID)
+ continue;
+ if (sc->sc_splitmic) {
+ if (i >= 32 && i < 32 + IEEE80211_WEP_NKID)
+ continue;
+ if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID)
+ continue;
+ }
+
+ if (!test_bit(i, sc->sc_keymap))
+ return i; /* Found a free slot for a key */
+ }
+
+ /* No free slot found */
+ return -1;
}
static int ath_key_config(struct ath_softc *sc,
const u8 *addr,
struct ieee80211_key_conf *key)
{
- struct ieee80211_vif *vif;
struct ath9k_keyval hk;
const u8 *mac = NULL;
int ret = 0;
- enum nl80211_iftype opmode;
+ int idx;
memset(&hk, 0, sizeof(hk));
@@ -158,226 +821,103 @@ static int ath_key_config(struct ath_softc *sc,
return -EINVAL;
}
- hk.kv_len = key->keylen;
+ hk.kv_len = key->keylen;
memcpy(hk.kv_val, key->key, key->keylen);
- if (!sc->sc_vaps[0])
- return -EIO;
+ if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
+ /* For now, use the default keys for broadcast keys. This may
+ * need to change with virtual interfaces. */
+ idx = key->keyidx;
+ } else if (key->keyidx) {
+ struct ieee80211_vif *vif;
- vif = sc->sc_vaps[0]->av_if_data;
- opmode = vif->type;
-
- /*
- * Strategy:
- * For _M_STA mc tx, we will not setup a key at all since we never
- * tx mc.
- * _M_STA mc rx, we will use the keyID.
- * for _M_IBSS mc tx, we will use the keyID, and no macaddr.
- * for _M_IBSS mc rx, we will alloc a slot and plumb the mac of the
- * peer node. BUT we will plumb a cleartext key so that we can do
- * perSta default key table lookup in software.
- */
- if (is_broadcast_ether_addr(addr)) {
- switch (opmode) {
- case NL80211_IFTYPE_STATION:
- /* default key: could be group WPA key
- * or could be static WEP key */
- mac = NULL;
- break;
- case NL80211_IFTYPE_ADHOC:
- break;
- case NL80211_IFTYPE_AP:
- break;
- default:
- ASSERT(0);
- break;
- }
+ mac = addr;
+ vif = sc->sc_vaps[0];
+ if (vif->type != NL80211_IFTYPE_AP) {
+ /* Only keyidx 0 should be used with unicast key, but
+ * allow this for client mode for now. */
+ idx = key->keyidx;
+ } else
+ return -EIO;
} else {
mac = addr;
+ if (key->alg == ALG_TKIP)
+ idx = ath_reserve_key_cache_slot_tkip(sc);
+ else
+ idx = ath_reserve_key_cache_slot(sc);
+ if (idx < 0)
+ return -EIO; /* no free key cache entries */
}
if (key->alg == ALG_TKIP)
- ret = ath_setkey_tkip(sc, key, &hk, mac);
+ ret = ath_setkey_tkip(sc, idx, key->key, &hk, mac);
else
- ret = ath_keyset(sc, key->keyidx, &hk, mac);
+ ret = ath_keyset(sc, idx, &hk, mac);
if (!ret)
return -EIO;
- return 0;
+ set_bit(idx, sc->sc_keymap);
+ if (key->alg == ALG_TKIP) {
+ set_bit(idx + 64, sc->sc_keymap);
+ if (sc->sc_splitmic) {
+ set_bit(idx + 32, sc->sc_keymap);
+ set_bit(idx + 64 + 32, sc->sc_keymap);
+ }
+ }
+
+ return idx;
}
static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key)
{
- int freeslot;
+ ath9k_hw_keyreset(sc->sc_ah, key->hw_key_idx);
+ if (key->hw_key_idx < IEEE80211_WEP_NKID)
+ return;
- freeslot = (key->keyidx >= 4) ? 1 : 0;
- ath_key_reset(sc, key->keyidx, freeslot);
+ clear_bit(key->hw_key_idx, sc->sc_keymap);
+ if (key->alg != ALG_TKIP)
+ return;
+
+ clear_bit(key->hw_key_idx + 64, sc->sc_keymap);
+ if (sc->sc_splitmic) {
+ clear_bit(key->hw_key_idx + 32, sc->sc_keymap);
+ clear_bit(key->hw_key_idx + 64 + 32, sc->sc_keymap);
+ }
}
-static void setup_ht_cap(struct ieee80211_ht_info *ht_info)
+static void setup_ht_cap(struct ieee80211_sta_ht_cap *ht_info)
{
#define ATH9K_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */
#define ATH9K_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */
- ht_info->ht_supported = 1;
- ht_info->cap = (u16)IEEE80211_HT_CAP_SUP_WIDTH
- |(u16)IEEE80211_HT_CAP_SM_PS
- |(u16)IEEE80211_HT_CAP_SGI_40
- |(u16)IEEE80211_HT_CAP_DSSSCCK40;
+ ht_info->ht_supported = true;
+ ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+ IEEE80211_HT_CAP_SM_PS |
+ IEEE80211_HT_CAP_SGI_40 |
+ IEEE80211_HT_CAP_DSSSCCK40;
ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536;
ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8;
- /* setup supported mcs set */
- memset(ht_info->supp_mcs_set, 0, 16);
- ht_info->supp_mcs_set[0] = 0xff;
- ht_info->supp_mcs_set[1] = 0xff;
- ht_info->supp_mcs_set[12] = IEEE80211_HT_CAP_MCS_TX_DEFINED;
-}
-
-static int ath_rate2idx(struct ath_softc *sc, int rate)
-{
- int i = 0, cur_band, n_rates;
- struct ieee80211_hw *hw = sc->hw;
-
- cur_band = hw->conf.channel->band;
- n_rates = sc->sbands[cur_band].n_bitrates;
-
- for (i = 0; i < n_rates; i++) {
- if (sc->sbands[cur_band].bitrates[i].bitrate == rate)
- break;
- }
-
- /*
- * NB:mac80211 validates rx rate index against the supported legacy rate
- * index only (should be done against ht rates also), return the highest
- * legacy rate index for rx rate which does not match any one of the
- * supported basic and extended rates to make mac80211 happy.
- * The following hack will be cleaned up once the issue with
- * the rx rate index validation in mac80211 is fixed.
- */
- if (i == n_rates)
- return n_rates - 1;
- return i;
-}
-
-static void ath9k_rx_prepare(struct ath_softc *sc,
- struct sk_buff *skb,
- struct ath_recv_status *status,
- struct ieee80211_rx_status *rx_status)
-{
- struct ieee80211_hw *hw = sc->hw;
- struct ieee80211_channel *curchan = hw->conf.channel;
-
- memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
-
- rx_status->mactime = status->tsf;
- rx_status->band = curchan->band;
- rx_status->freq = curchan->center_freq;
- rx_status->noise = sc->sc_ani.sc_noise_floor;
- rx_status->signal = rx_status->noise + status->rssi;
- rx_status->rate_idx = ath_rate2idx(sc, (status->rateKbps / 100));
- rx_status->antenna = status->antenna;
-
- /* XXX Fix me, 64 cannot be the max rssi value, rigure it out */
- rx_status->qual = status->rssi * 100 / 64;
-
- if (status->flags & ATH_RX_MIC_ERROR)
- rx_status->flag |= RX_FLAG_MMIC_ERROR;
- if (status->flags & ATH_RX_FCS_ERROR)
- rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
-
- rx_status->flag |= RX_FLAG_TSFT;
-}
-
-static u8 parse_mpdudensity(u8 mpdudensity)
-{
- /*
- * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing":
- * 0 for no restriction
- * 1 for 1/4 us
- * 2 for 1/2 us
- * 3 for 1 us
- * 4 for 2 us
- * 5 for 4 us
- * 6 for 8 us
- * 7 for 16 us
- */
- switch (mpdudensity) {
- case 0:
- return 0;
- case 1:
- case 2:
- case 3:
- /* Our lower layer calculations limit our precision to
- 1 microsecond */
- return 1;
- case 4:
- return 2;
- case 5:
- return 4;
- case 6:
- return 8;
- case 7:
- return 16;
- default:
- return 0;
- }
-}
-
-static void ath9k_ht_conf(struct ath_softc *sc,
- struct ieee80211_bss_conf *bss_conf)
-{
-#define IEEE80211_HT_CAP_40MHZ_INTOLERANT BIT(14)
- struct ath_ht_info *ht_info = &sc->sc_ht_info;
-
- if (bss_conf->assoc_ht) {
- ht_info->ext_chan_offset =
- bss_conf->ht_bss_conf->bss_cap &
- IEEE80211_HT_IE_CHA_SEC_OFFSET;
-
- if (!(bss_conf->ht_conf->cap &
- IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
- (bss_conf->ht_bss_conf->bss_cap &
- IEEE80211_HT_IE_CHA_WIDTH))
- ht_info->tx_chan_width = ATH9K_HT_MACMODE_2040;
- else
- ht_info->tx_chan_width = ATH9K_HT_MACMODE_20;
-
- ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width);
- ht_info->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
- bss_conf->ht_conf->ampdu_factor);
- ht_info->mpdudensity =
- parse_mpdudensity(bss_conf->ht_conf->ampdu_density);
-
- }
-
-#undef IEEE80211_HT_CAP_40MHZ_INTOLERANT
+ /* set up supported mcs set */
+ memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
+ ht_info->mcs.rx_mask[0] = 0xff;
+ ht_info->mcs.rx_mask[1] = 0xff;
+ ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
}
static void ath9k_bss_assoc_info(struct ath_softc *sc,
+ struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf)
{
- struct ieee80211_hw *hw = sc->hw;
- struct ieee80211_channel *curchan = hw->conf.channel;
- struct ath_vap *avp;
- int pos;
- DECLARE_MAC_BUF(mac);
+ struct ath_vap *avp = (void *)vif->drv_priv;
if (bss_conf->assoc) {
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: Bss Info ASSOC %d\n",
- __func__,
- bss_conf->aid);
-
- avp = sc->sc_vaps[0];
- if (avp == NULL) {
- DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
- __func__);
- return;
- }
+ DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info ASSOC %d, bssid: %pM\n",
+ bss_conf->aid, sc->sc_curbssid);
/* New association, store aid */
- if (avp->av_opmode == ATH9K_M_STA) {
+ if (avp->av_opmode == NL80211_IFTYPE_STATION) {
sc->sc_curaid = bss_conf->aid;
ath9k_hw_write_associd(sc->sc_ah, sc->sc_curbssid,
sc->sc_curaid);
@@ -393,175 +933,16 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER;
- /* Update chainmask */
- ath_update_chainmask(sc, bss_conf->assoc_ht);
-
- DPRINTF(sc, ATH_DBG_CONFIG,
- "%s: bssid %s aid 0x%x\n",
- __func__,
- print_mac(mac, sc->sc_curbssid), sc->sc_curaid);
-
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n",
- __func__,
- curchan->center_freq);
-
- pos = ath_get_channel(sc, curchan);
- if (pos == -1) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: Invalid channel\n", __func__);
- return;
- }
-
- if (hw->conf.ht_conf.ht_supported)
- sc->sc_ah->ah_channels[pos].chanmode =
- ath_get_extchanmode(sc, curchan);
- else
- sc->sc_ah->ah_channels[pos].chanmode =
- (curchan->band == IEEE80211_BAND_2GHZ) ?
- CHANNEL_G : CHANNEL_A;
-
- /* set h/w channel */
- if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0)
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: Unable to set channel\n",
- __func__);
-
- ath_rate_newstate(sc, avp);
- /* Update ratectrl about the new state */
- ath_rc_node_update(hw, avp->rc_node);
-
/* Start ANI */
mod_timer(&sc->sc_ani.timer,
jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
} else {
- DPRINTF(sc, ATH_DBG_CONFIG,
- "%s: Bss Info DISSOC\n", __func__);
+ DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info DISSOC\n");
sc->sc_curaid = 0;
}
}
-void ath_get_beaconconfig(struct ath_softc *sc,
- int if_id,
- struct ath_beacon_config *conf)
-{
- struct ieee80211_hw *hw = sc->hw;
-
- /* fill in beacon config data */
-
- conf->beacon_interval = hw->conf.beacon_int;
- conf->listen_interval = 100;
- conf->dtim_count = 1;
- conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval;
-}
-
-void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
- struct ath_xmit_status *tx_status, struct ath_node *an)
-{
- struct ieee80211_hw *hw = sc->hw;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-
- DPRINTF(sc, ATH_DBG_XMIT,
- "%s: TX complete: skb: %p\n", __func__, skb);
-
- if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK ||
- tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
- /* free driver's private data area of tx_info */
- if (tx_info->driver_data[0] != NULL)
- kfree(tx_info->driver_data[0]);
- tx_info->driver_data[0] = NULL;
- }
-
- if (tx_status->flags & ATH_TX_BAR) {
- tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
- tx_status->flags &= ~ATH_TX_BAR;
- }
-
- if (tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY)) {
- if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
- /* Frame was not ACKed, but an ACK was expected */
- tx_info->status.excessive_retries = 1;
- }
- } else {
- /* Frame was ACKed */
- tx_info->flags |= IEEE80211_TX_STAT_ACK;
- }
-
- tx_info->status.retry_count = tx_status->retries;
-
- ieee80211_tx_status(hw, skb);
- if (an)
- ath_node_put(sc, an, ATH9K_BH_STATUS_CHANGE);
-}
-
-int _ath_rx_indicate(struct ath_softc *sc,
- struct sk_buff *skb,
- struct ath_recv_status *status,
- u16 keyix)
-{
- struct ieee80211_hw *hw = sc->hw;
- struct ath_node *an = NULL;
- struct ieee80211_rx_status rx_status;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
- int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
- int padsize;
- enum ATH_RX_TYPE st;
-
- /* see if any padding is done by the hw and remove it */
- if (hdrlen & 3) {
- padsize = hdrlen % 4;
- memmove(skb->data + padsize, skb->data, hdrlen);
- skb_pull(skb, padsize);
- }
-
- /* Prepare rx status */
- ath9k_rx_prepare(sc, skb, status, &rx_status);
-
- if (!(keyix == ATH9K_RXKEYIX_INVALID) &&
- !(status->flags & ATH_RX_DECRYPT_ERROR)) {
- rx_status.flag |= RX_FLAG_DECRYPTED;
- } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED)
- && !(status->flags & ATH_RX_DECRYPT_ERROR)
- && skb->len >= hdrlen + 4) {
- keyix = skb->data[hdrlen + 3] >> 6;
-
- if (test_bit(keyix, sc->sc_keymap))
- rx_status.flag |= RX_FLAG_DECRYPTED;
- }
-
- spin_lock_bh(&sc->node_lock);
- an = ath_node_find(sc, hdr->addr2);
- spin_unlock_bh(&sc->node_lock);
-
- if (an) {
- ath_rx_input(sc, an,
- hw->conf.ht_conf.ht_supported,
- skb, status, &st);
- }
- if (!an || (st != ATH_RX_CONSUMED))
- __ieee80211_rx(hw, skb, &rx_status);
-
- return 0;
-}
-
-int ath_rx_subframe(struct ath_node *an,
- struct sk_buff *skb,
- struct ath_recv_status *status)
-{
- struct ath_softc *sc = an->an_sc;
- struct ieee80211_hw *hw = sc->hw;
- struct ieee80211_rx_status rx_status;
-
- /* Prepare rx status */
- ath9k_rx_prepare(sc, skb, status, &rx_status);
- if (!(status->flags & ATH_RX_DECRYPT_ERROR))
- rx_status.flag |= RX_FLAG_DECRYPTED;
-
- __ieee80211_rx(hw, skb, &rx_status);
-
- return 0;
-}
-
/********************************/
/* LED functions */
/********************************/
@@ -677,7 +1058,8 @@ fail:
ath_deinit_leds(sc);
}
-#ifdef CONFIG_RFKILL
+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
+
/*******************/
/* Rfkill */
/*******************/
@@ -689,14 +1071,14 @@ static void ath_radio_enable(struct ath_softc *sc)
spin_lock_bh(&sc->sc_resetlock);
if (!ath9k_hw_reset(ah, ah->ah_curchan,
- sc->sc_ht_info.tx_chan_width,
+ sc->tx_chan_width,
sc->sc_tx_chainmask,
sc->sc_rx_chainmask,
sc->sc_ht_extprotspacing,
false, &status)) {
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to reset channel %u (%uMhz) "
- "flags 0x%x hal status %u\n", __func__,
+ "Unable to reset channel %u (%uMhz) "
+ "flags 0x%x hal status %u\n",
ath9k_hw_mhz2ieee(ah,
ah->ah_curchan->channel,
ah->ah_curchan->channelFlags),
@@ -708,7 +1090,7 @@ static void ath_radio_enable(struct ath_softc *sc)
ath_update_txpow(sc);
if (ath_startrecv(sc) != 0) {
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to restart recv logic\n", __func__);
+ "Unable to restart recv logic\n");
return;
}
@@ -747,14 +1129,14 @@ static void ath_radio_disable(struct ath_softc *sc)
spin_lock_bh(&sc->sc_resetlock);
if (!ath9k_hw_reset(ah, ah->ah_curchan,
- sc->sc_ht_info.tx_chan_width,
+ sc->tx_chan_width,
sc->sc_tx_chainmask,
sc->sc_rx_chainmask,
sc->sc_ht_extprotspacing,
false, &status)) {
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to reset channel %u (%uMhz) "
- "flags 0x%x hal status %u\n", __func__,
+ "Unable to reset channel %u (%uMhz) "
+ "flags 0x%x hal status %u\n",
ath9k_hw_mhz2ieee(ah,
ah->ah_curchan->channel,
ah->ah_curchan->channelFlags),
@@ -834,7 +1216,7 @@ static int ath_sw_toggle_radio(void *data, enum rfkill_state state)
sc->sc_flags &= ~SC_OP_RFKILL_SW_BLOCKED;
if (sc->sc_flags & SC_OP_RFKILL_HW_BLOCKED) {
DPRINTF(sc, ATH_DBG_FATAL, "Can't turn on the"
- "radio as it is disabled by h/w \n");
+ "radio as it is disabled by h/w\n");
return -EPERM;
}
ath_radio_enable(sc);
@@ -878,61 +1260,258 @@ static void ath_deinit_rfkill(struct ath_softc *sc)
sc->rf_kill.rfkill = NULL;
}
}
+
+static int ath_start_rfkill_poll(struct ath_softc *sc)
+{
+ if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
+ queue_delayed_work(sc->hw->workqueue,
+ &sc->rf_kill.rfkill_poll, 0);
+
+ if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) {
+ if (rfkill_register(sc->rf_kill.rfkill)) {
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "Unable to register rfkill\n");
+ rfkill_free(sc->rf_kill.rfkill);
+
+ /* Deinitialize the device */
+ ath_detach(sc);
+ if (sc->pdev->irq)
+ free_irq(sc->pdev->irq, sc);
+ pci_iounmap(sc->pdev, sc->mem);
+ pci_release_region(sc->pdev, 0);
+ pci_disable_device(sc->pdev);
+ ieee80211_free_hw(sc->hw);
+ return -EIO;
+ } else {
+ sc->sc_flags |= SC_OP_RFKILL_REGISTERED;
+ }
+ }
+
+ return 0;
+}
#endif /* CONFIG_RFKILL */
-static int ath_detach(struct ath_softc *sc)
+static void ath_detach(struct ath_softc *sc)
{
struct ieee80211_hw *hw = sc->hw;
+ int i = 0;
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach ATH hw\n", __func__);
-
- /* Deinit LED control */
- ath_deinit_leds(sc);
+ DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n");
-#ifdef CONFIG_RFKILL
- /* deinit rfkill */
+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
ath_deinit_rfkill(sc);
#endif
-
- /* Unregister hw */
+ ath_deinit_leds(sc);
ieee80211_unregister_hw(hw);
-
- /* unregister Rate control */
- ath_rate_control_unregister();
-
- /* tx/rx cleanup */
-
ath_rx_cleanup(sc);
ath_tx_cleanup(sc);
- /* Deinit */
+ tasklet_kill(&sc->intr_tq);
+ tasklet_kill(&sc->bcon_tasklet);
- ath_deinit(sc);
+ if (!(sc->sc_flags & SC_OP_INVALID))
+ ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
- return 0;
+ /* cleanup tx queues */
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+ if (ATH_TXQ_SETUP(sc, i))
+ ath_tx_cleanupq(sc, &sc->tx.txq[i]);
+
+ ath9k_hw_detach(sc->sc_ah);
+ ath9k_exit_debug(sc);
}
-static int ath_attach(u16 devid,
- struct ath_softc *sc)
+static int ath_init(u16 devid, struct ath_softc *sc)
{
- struct ieee80211_hw *hw = sc->hw;
- int error = 0;
+ struct ath_hal *ah = NULL;
+ int status;
+ int error = 0, i;
+ int csz = 0;
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach ATH hw\n", __func__);
+ /* XXX: hardware will not be ready until ath_open() being called */
+ sc->sc_flags |= SC_OP_INVALID;
- error = ath_init(devid, sc);
- if (error != 0)
- return error;
+ if (ath9k_init_debug(sc) < 0)
+ printk(KERN_ERR "Unable to create debugfs files\n");
- /* Init nodes */
+ spin_lock_init(&sc->sc_resetlock);
+ mutex_init(&sc->mutex);
+ tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
+ tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet,
+ (unsigned long)sc);
- INIT_LIST_HEAD(&sc->node_list);
- spin_lock_init(&sc->node_lock);
+ /*
+ * Cache line size is used to size and align various
+ * structures used to communicate with the hardware.
+ */
+ bus_read_cachesize(sc, &csz);
+ /* XXX assert csz is non-zero */
+ sc->sc_cachelsz = csz << 2; /* convert to bytes */
- /* get mac address from hardware and set in mac80211 */
+ ah = ath9k_hw_attach(devid, sc, sc->mem, &status);
+ if (ah == NULL) {
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "Unable to attach hardware; HAL status %u\n", status);
+ error = -ENXIO;
+ goto bad;
+ }
+ sc->sc_ah = ah;
- SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr);
+ /* Get the hardware key cache size. */
+ sc->sc_keymax = ah->ah_caps.keycache_size;
+ if (sc->sc_keymax > ATH_KEYMAX) {
+ DPRINTF(sc, ATH_DBG_KEYCACHE,
+ "Warning, using only %u entries in %u key cache\n",
+ ATH_KEYMAX, sc->sc_keymax);
+ sc->sc_keymax = ATH_KEYMAX;
+ }
+
+ /*
+ * Reset the key cache since some parts do not
+ * reset the contents on initial power up.
+ */
+ for (i = 0; i < sc->sc_keymax; i++)
+ ath9k_hw_keyreset(ah, (u16) i);
+
+ /* Collect the channel list using the default country code */
+
+ error = ath_setup_channels(sc);
+ if (error)
+ goto bad;
+
+ /* default to MONITOR mode */
+ sc->sc_ah->ah_opmode = NL80211_IFTYPE_MONITOR;
+
+
+ /* Setup rate tables */
+
+ ath_rate_attach(sc);
+ ath_setup_rates(sc, IEEE80211_BAND_2GHZ);
+ ath_setup_rates(sc, IEEE80211_BAND_5GHZ);
+
+ /*
+ * Allocate hardware transmit queues: one queue for
+ * beacon frames and one data queue for each QoS
+ * priority. Note that the hal handles reseting
+ * these queues at the needed time.
+ */
+ sc->beacon.beaconq = ath_beaconq_setup(ah);
+ if (sc->beacon.beaconq == -1) {
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "Unable to setup a beacon xmit queue\n");
+ error = -EIO;
+ goto bad2;
+ }
+ sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0);
+ if (sc->beacon.cabq == NULL) {
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "Unable to setup CAB xmit queue\n");
+ error = -EIO;
+ goto bad2;
+ }
+
+ sc->sc_config.cabqReadytime = ATH_CABQ_READY_TIME;
+ ath_cabq_update(sc);
+
+ for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++)
+ sc->tx.hwq_map[i] = -1;
+
+ /* Setup data queues */
+ /* NB: ensure BK queue is the lowest priority h/w queue */
+ if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) {
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "Unable to setup xmit queue for BK traffic\n");
+ error = -EIO;
+ goto bad2;
+ }
+
+ if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) {
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "Unable to setup xmit queue for BE traffic\n");
+ error = -EIO;
+ goto bad2;
+ }
+ if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) {
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "Unable to setup xmit queue for VI traffic\n");
+ error = -EIO;
+ goto bad2;
+ }
+ if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) {
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "Unable to setup xmit queue for VO traffic\n");
+ error = -EIO;
+ goto bad2;
+ }
+
+ /* Initializes the noise floor to a reasonable default value.
+ * Later on this will be updated during ANI processing. */
+
+ sc->sc_ani.sc_noise_floor = ATH_DEFAULT_NOISE_FLOOR;
+ setup_timer(&sc->sc_ani.timer, ath_ani_calibrate, (unsigned long)sc);
+
+ if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
+ ATH9K_CIPHER_TKIP, NULL)) {
+ /*
+ * Whether we should enable h/w TKIP MIC.
+ * XXX: if we don't support WME TKIP MIC, then we wouldn't
+ * report WMM capable, so it's always safe to turn on
+ * TKIP MIC in this case.
+ */
+ ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC,
+ 0, 1, NULL);
+ }
+
+ /*
+ * Check whether the separate key cache entries
+ * are required to handle both tx+rx MIC keys.
+ * With split mic keys the number of stations is limited
+ * to 27 otherwise 59.
+ */
+ if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
+ ATH9K_CIPHER_TKIP, NULL)
+ && ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER,
+ ATH9K_CIPHER_MIC, NULL)
+ && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT,
+ 0, NULL))
+ sc->sc_splitmic = 1;
+
+ /* turn on mcast key search if possible */
+ if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL))
+ (void)ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1,
+ 1, NULL);
+
+ sc->sc_config.txpowlimit = ATH_TXPOWER_MAX;
+ sc->sc_config.txpowlimit_override = 0;
+
+ /* 11n Capabilities */
+ if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) {
+ sc->sc_flags |= SC_OP_TXAGGR;
+ sc->sc_flags |= SC_OP_RXAGGR;
+ }
+
+ sc->sc_tx_chainmask = ah->ah_caps.tx_chainmask;
+ sc->sc_rx_chainmask = ah->ah_caps.rx_chainmask;
+
+ ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL);
+ sc->rx.defant = ath9k_hw_getdefantenna(ah);
+
+ ath9k_hw_getmac(ah, sc->sc_myaddr);
+ if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) {
+ ath9k_hw_getbssidmask(ah, sc->sc_bssidmask);
+ ATH_SET_VAP_BSSID_MASK(sc->sc_bssidmask);
+ ath9k_hw_setbssidmask(ah, sc->sc_bssidmask);
+ }
+
+ sc->beacon.slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */
+
+ /* initialize beacon slots */
+ for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++)
+ sc->beacon.bslot[i] = ATH_IF_ID_ANY;
+
+ /* save MISC configurations */
+ sc->sc_config.swBeaconProcess = 1;
/* setup channels and rates */
@@ -942,55 +1521,81 @@ static int ath_attach(u16 devid,
sc->rates[IEEE80211_BAND_2GHZ];
sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
- if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
- /* Setup HT capabilities for 2.4Ghz*/
- setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_info);
-
- hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
- &sc->sbands[IEEE80211_BAND_2GHZ];
-
if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes)) {
sc->sbands[IEEE80211_BAND_5GHZ].channels =
sc->channels[IEEE80211_BAND_5GHZ];
sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
sc->rates[IEEE80211_BAND_5GHZ];
- sc->sbands[IEEE80211_BAND_5GHZ].band =
- IEEE80211_BAND_5GHZ;
+ sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
+ }
- if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
- /* Setup HT capabilities for 5Ghz*/
- setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_info);
+ return 0;
+bad2:
+ /* cleanup tx queues */
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
+ if (ATH_TXQ_SETUP(sc, i))
+ ath_tx_cleanupq(sc, &sc->tx.txq[i]);
+bad:
+ if (ah)
+ ath9k_hw_detach(ah);
- hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
- &sc->sbands[IEEE80211_BAND_5GHZ];
- }
+ return error;
+}
+
+static int ath_attach(u16 devid, struct ath_softc *sc)
+{
+ struct ieee80211_hw *hw = sc->hw;
+ int error = 0;
+
+ DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n");
+
+ error = ath_init(devid, sc);
+ if (error != 0)
+ return error;
+
+ /* get mac address from hardware and set in mac80211 */
+
+ SET_IEEE80211_PERM_ADDR(hw, sc->sc_myaddr);
+
+ hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
+ IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+ IEEE80211_HW_SIGNAL_DBM |
+ IEEE80211_HW_AMPDU_AGGREGATION;
- /* FIXME: Have to figure out proper hw init values later */
+ hw->wiphy->interface_modes =
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC);
hw->queues = 4;
- hw->ampdu_queues = 1;
+ hw->max_rates = 4;
+ hw->max_rate_tries = ATH_11N_TXMAXTRY;
+ hw->sta_data_size = sizeof(struct ath_node);
+ hw->vif_data_size = sizeof(struct ath_vap);
- /* Register rate control */
hw->rate_control_algorithm = "ath9k_rate_control";
- error = ath_rate_control_register();
- if (error != 0) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: Unable to register rate control "
- "algorithm:%d\n", __func__, error);
- ath_rate_control_unregister();
- goto bad;
- }
- error = ieee80211_register_hw(hw);
- if (error != 0) {
- ath_rate_control_unregister();
- goto bad;
+ if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) {
+ setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
+ if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes))
+ setup_ht_cap(&sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
}
- /* Initialize LED control */
- ath_init_leds(sc);
+ hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &sc->sbands[IEEE80211_BAND_2GHZ];
+ if (test_bit(ATH9K_MODE_11A, sc->sc_ah->ah_caps.wireless_modes))
+ hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+ &sc->sbands[IEEE80211_BAND_5GHZ];
-#ifdef CONFIG_RFKILL
+ /* initialize tx/rx engine */
+ error = ath_tx_init(sc, ATH_TXBUF);
+ if (error != 0)
+ goto detach;
+
+ error = ath_rx_init(sc, ATH_RXBUF);
+ if (error != 0)
+ goto detach;
+
+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
/* Initialze h/w Rfkill */
if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
INIT_DELAYED_WORK(&sc->rf_kill.rfkill_poll, ath_rfkill_poll);
@@ -1000,88 +1605,371 @@ static int ath_attach(u16 devid,
goto detach;
#endif
- /* initialize tx/rx engine */
-
- error = ath_tx_init(sc, ATH_TXBUF);
- if (error != 0)
- goto detach;
+ error = ieee80211_register_hw(hw);
- error = ath_rx_init(sc, ATH_RXBUF);
- if (error != 0)
- goto detach;
+ /* Initialize LED control */
+ ath_init_leds(sc);
return 0;
detach:
ath_detach(sc);
-bad:
return error;
}
+int ath_reset(struct ath_softc *sc, bool retry_tx)
+{
+ struct ath_hal *ah = sc->sc_ah;
+ int status;
+ int error = 0;
+
+ ath9k_hw_set_interrupts(ah, 0);
+ ath_draintxq(sc, retry_tx);
+ ath_stoprecv(sc);
+ ath_flushrecv(sc);
+
+ spin_lock_bh(&sc->sc_resetlock);
+ if (!ath9k_hw_reset(ah, sc->sc_ah->ah_curchan,
+ sc->tx_chan_width,
+ sc->sc_tx_chainmask, sc->sc_rx_chainmask,
+ sc->sc_ht_extprotspacing, false, &status)) {
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "Unable to reset hardware; hal status %u\n", status);
+ error = -EIO;
+ }
+ spin_unlock_bh(&sc->sc_resetlock);
+
+ if (ath_startrecv(sc) != 0)
+ DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n");
+
+ /*
+ * We may be doing a reset in response to a request
+ * that changes the channel so update any state that
+ * might change as a result.
+ */
+ ath_setcurmode(sc, ath_chan2mode(sc->sc_ah->ah_curchan));
+
+ ath_update_txpow(sc);
+
+ if (sc->sc_flags & SC_OP_BEACONS)
+ ath_beacon_config(sc, ATH_IF_ID_ANY); /* restart beacons */
+
+ ath9k_hw_set_interrupts(ah, sc->sc_imask);
+
+ if (retry_tx) {
+ int i;
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+ if (ATH_TXQ_SETUP(sc, i)) {
+ spin_lock_bh(&sc->tx.txq[i].axq_lock);
+ ath_txq_schedule(sc, &sc->tx.txq[i]);
+ spin_unlock_bh(&sc->tx.txq[i].axq_lock);
+ }
+ }
+ }
+
+ return error;
+}
+
+/*
+ * This function will allocate both the DMA descriptor structure, and the
+ * buffers it contains. These are used to contain the descriptors used
+ * by the system.
+*/
+int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd,
+ struct list_head *head, const char *name,
+ int nbuf, int ndesc)
+{
+#define DS2PHYS(_dd, _ds) \
+ ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc))
+#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0)
+#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096)
+
+ struct ath_desc *ds;
+ struct ath_buf *bf;
+ int i, bsize, error;
+
+ DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n",
+ name, nbuf, ndesc);
+
+ /* ath_desc must be a multiple of DWORDs */
+ if ((sizeof(struct ath_desc) % 4) != 0) {
+ DPRINTF(sc, ATH_DBG_FATAL, "ath_desc not DWORD aligned\n");
+ ASSERT((sizeof(struct ath_desc) % 4) == 0);
+ error = -ENOMEM;
+ goto fail;
+ }
+
+ dd->dd_name = name;
+ dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc;
+
+ /*
+ * Need additional DMA memory because we can't use
+ * descriptors that cross the 4K page boundary. Assume
+ * one skipped descriptor per 4K page.
+ */
+ if (!(sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) {
+ u32 ndesc_skipped =
+ ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len);
+ u32 dma_len;
+
+ while (ndesc_skipped) {
+ dma_len = ndesc_skipped * sizeof(struct ath_desc);
+ dd->dd_desc_len += dma_len;
+
+ ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len);
+ };
+ }
+
+ /* allocate descriptors */
+ dd->dd_desc = pci_alloc_consistent(sc->pdev,
+ dd->dd_desc_len,
+ &dd->dd_desc_paddr);
+ if (dd->dd_desc == NULL) {
+ error = -ENOMEM;
+ goto fail;
+ }
+ ds = dd->dd_desc;
+ DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n",
+ dd->dd_name, ds, (u32) dd->dd_desc_len,
+ ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len);
+
+ /* allocate buffers */
+ bsize = sizeof(struct ath_buf) * nbuf;
+ bf = kmalloc(bsize, GFP_KERNEL);
+ if (bf == NULL) {
+ error = -ENOMEM;
+ goto fail2;
+ }
+ memset(bf, 0, bsize);
+ dd->dd_bufptr = bf;
+
+ INIT_LIST_HEAD(head);
+ for (i = 0; i < nbuf; i++, bf++, ds += ndesc) {
+ bf->bf_desc = ds;
+ bf->bf_daddr = DS2PHYS(dd, ds);
+
+ if (!(sc->sc_ah->ah_caps.hw_caps &
+ ATH9K_HW_CAP_4KB_SPLITTRANS)) {
+ /*
+ * Skip descriptor addresses which can cause 4KB
+ * boundary crossing (addr + length) with a 32 dword
+ * descriptor fetch.
+ */
+ while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) {
+ ASSERT((caddr_t) bf->bf_desc <
+ ((caddr_t) dd->dd_desc +
+ dd->dd_desc_len));
+
+ ds += ndesc;
+ bf->bf_desc = ds;
+ bf->bf_daddr = DS2PHYS(dd, ds);
+ }
+ }
+ list_add_tail(&bf->list, head);
+ }
+ return 0;
+fail2:
+ pci_free_consistent(sc->pdev,
+ dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr);
+fail:
+ memset(dd, 0, sizeof(*dd));
+ return error;
+#undef ATH_DESC_4KB_BOUND_CHECK
+#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED
+#undef DS2PHYS
+}
+
+void ath_descdma_cleanup(struct ath_softc *sc,
+ struct ath_descdma *dd,
+ struct list_head *head)
+{
+ pci_free_consistent(sc->pdev,
+ dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr);
+
+ INIT_LIST_HEAD(head);
+ kfree(dd->dd_bufptr);
+ memset(dd, 0, sizeof(*dd));
+}
+
+int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
+{
+ int qnum;
+
+ switch (queue) {
+ case 0:
+ qnum = sc->tx.hwq_map[ATH9K_WME_AC_VO];
+ break;
+ case 1:
+ qnum = sc->tx.hwq_map[ATH9K_WME_AC_VI];
+ break;
+ case 2:
+ qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE];
+ break;
+ case 3:
+ qnum = sc->tx.hwq_map[ATH9K_WME_AC_BK];
+ break;
+ default:
+ qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE];
+ break;
+ }
+
+ return qnum;
+}
+
+int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc)
+{
+ int qnum;
+
+ switch (queue) {
+ case ATH9K_WME_AC_VO:
+ qnum = 0;
+ break;
+ case ATH9K_WME_AC_VI:
+ qnum = 1;
+ break;
+ case ATH9K_WME_AC_BE:
+ qnum = 2;
+ break;
+ case ATH9K_WME_AC_BK:
+ qnum = 3;
+ break;
+ default:
+ qnum = -1;
+ break;
+ }
+
+ return qnum;
+}
+
+/**********************/
+/* mac80211 callbacks */
+/**********************/
+
static int ath9k_start(struct ieee80211_hw *hw)
{
struct ath_softc *sc = hw->priv;
struct ieee80211_channel *curchan = hw->conf.channel;
- int error = 0, pos;
+ struct ath9k_channel *init_channel;
+ int error = 0, pos, status;
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: Starting driver with "
- "initial channel: %d MHz\n", __func__, curchan->center_freq);
+ DPRINTF(sc, ATH_DBG_CONFIG, "Starting driver with "
+ "initial channel: %d MHz\n", curchan->center_freq);
/* setup initial channel */
pos = ath_get_channel(sc, curchan);
if (pos == -1) {
- DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__);
- return -EINVAL;
+ DPRINTF(sc, ATH_DBG_FATAL, "Invalid channel: %d\n", curchan->center_freq);
+ error = -EINVAL;
+ goto error;
}
+ sc->tx_chan_width = ATH9K_HT_MACMODE_20;
sc->sc_ah->ah_channels[pos].chanmode =
(curchan->band == IEEE80211_BAND_2GHZ) ? CHANNEL_G : CHANNEL_A;
+ init_channel = &sc->sc_ah->ah_channels[pos];
- /* open ath_dev */
- error = ath_open(sc, &sc->sc_ah->ah_channels[pos]);
- if (error) {
+ /* Reset SERDES registers */
+ ath9k_hw_configpcipowersave(sc->sc_ah, 0);
+
+ /*
+ * The basic interface to setting the hardware in a good
+ * state is ``reset''. On return the hardware is known to
+ * be powered up and with interrupts disabled. This must
+ * be followed by initialization of the appropriate bits
+ * and then setup of the interrupt mask.
+ */
+ spin_lock_bh(&sc->sc_resetlock);
+ if (!ath9k_hw_reset(sc->sc_ah, init_channel,
+ sc->tx_chan_width,
+ sc->sc_tx_chainmask, sc->sc_rx_chainmask,
+ sc->sc_ht_extprotspacing, false, &status)) {
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: Unable to complete ath_open\n", __func__);
- return error;
+ "Unable to reset hardware; hal status %u "
+ "(freq %u flags 0x%x)\n", status,
+ init_channel->channel, init_channel->channelFlags);
+ error = -EIO;
+ spin_unlock_bh(&sc->sc_resetlock);
+ goto error;
}
+ spin_unlock_bh(&sc->sc_resetlock);
-#ifdef CONFIG_RFKILL
- /* Start rfkill polling */
- if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
- queue_delayed_work(sc->hw->workqueue,
- &sc->rf_kill.rfkill_poll, 0);
-
- if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) {
- if (rfkill_register(sc->rf_kill.rfkill)) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "Unable to register rfkill\n");
- rfkill_free(sc->rf_kill.rfkill);
+ /*
+ * This is needed only to setup initial state
+ * but it's best done after a reset.
+ */
+ ath_update_txpow(sc);
- /* Deinitialize the device */
- if (sc->pdev->irq)
- free_irq(sc->pdev->irq, sc);
- ath_detach(sc);
- pci_iounmap(sc->pdev, sc->mem);
- pci_release_region(sc->pdev, 0);
- pci_disable_device(sc->pdev);
- ieee80211_free_hw(hw);
- return -EIO;
- } else {
- sc->sc_flags |= SC_OP_RFKILL_REGISTERED;
- }
+ /*
+ * Setup the hardware after reset:
+ * The receive engine is set going.
+ * Frame transmit is handled entirely
+ * in the frame output path; there's nothing to do
+ * here except setup the interrupt mask.
+ */
+ if (ath_startrecv(sc) != 0) {
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "Unable to start recv logic\n");
+ error = -EIO;
+ goto error;
}
+
+ /* Setup our intr mask. */
+ sc->sc_imask = ATH9K_INT_RX | ATH9K_INT_TX
+ | ATH9K_INT_RXEOL | ATH9K_INT_RXORN
+ | ATH9K_INT_FATAL | ATH9K_INT_GLOBAL;
+
+ if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_GTT)
+ sc->sc_imask |= ATH9K_INT_GTT;
+
+ if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)
+ sc->sc_imask |= ATH9K_INT_CST;
+
+ /*
+ * Enable MIB interrupts when there are hardware phy counters.
+ * Note we only do this (at the moment) for station mode.
+ */
+ if (ath9k_hw_phycounters(sc->sc_ah) &&
+ ((sc->sc_ah->ah_opmode == NL80211_IFTYPE_STATION) ||
+ (sc->sc_ah->ah_opmode == NL80211_IFTYPE_ADHOC)))
+ sc->sc_imask |= ATH9K_INT_MIB;
+ /*
+ * Some hardware processes the TIM IE and fires an
+ * interrupt when the TIM bit is set. For hardware
+ * that does, if not overridden by configuration,
+ * enable the TIM interrupt when operating as station.
+ */
+ if ((sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_ENHANCEDPM) &&
+ (sc->sc_ah->ah_opmode == NL80211_IFTYPE_STATION) &&
+ !sc->sc_config.swBeaconProcess)
+ sc->sc_imask |= ATH9K_INT_TIM;
+
+ ath_setcurmode(sc, ath_chan2mode(init_channel));
+
+ sc->sc_flags &= ~SC_OP_INVALID;
+
+ /* Disable BMISS interrupt when we're not associated */
+ sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
+ ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask);
+
+ ieee80211_wake_queues(sc->hw);
+
+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
+ error = ath_start_rfkill_poll(sc);
#endif
- ieee80211_wake_queues(hw);
- return 0;
+error:
+ return error;
}
static int ath9k_tx(struct ieee80211_hw *hw,
struct sk_buff *skb)
{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ath_softc *sc = hw->priv;
+ struct ath_tx_control txctl;
int hdrlen, padsize;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+ memset(&txctl, 0, sizeof(struct ath_tx_control));
/*
* As a temporary workaround, assign seq# here; this will likely need
@@ -1091,9 +1979,9 @@ static int ath9k_tx(struct ieee80211_hw *hw,
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
- sc->seq_no += 0x10;
+ sc->tx.seq_no += 0x10;
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
- hdr->seq_ctrl |= cpu_to_le16(sc->seq_no);
+ hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
}
/* Add the padding after the header if this is not already done */
@@ -1106,45 +1994,68 @@ static int ath9k_tx(struct ieee80211_hw *hw,
memmove(skb->data, skb->data + padsize, hdrlen);
}
- DPRINTF(sc, ATH_DBG_XMIT, "%s: transmitting packet, skb: %p\n",
- __func__,
- skb);
+ /* Check if a tx queue is available */
- if (ath_tx_start(sc, skb) != 0) {
- DPRINTF(sc, ATH_DBG_XMIT, "%s: TX failed\n", __func__);
- dev_kfree_skb_any(skb);
- /* FIXME: Check for proper return value from ATH_DEV */
- return 0;
+ txctl.txq = ath_test_get_txq(sc, skb);
+ if (!txctl.txq)
+ goto exit;
+
+ DPRINTF(sc, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
+
+ if (ath_tx_start(sc, skb, &txctl) != 0) {
+ DPRINTF(sc, ATH_DBG_XMIT, "TX failed\n");
+ goto exit;
}
return 0;
+exit:
+ dev_kfree_skb_any(skb);
+ return 0;
}
static void ath9k_stop(struct ieee80211_hw *hw)
{
struct ath_softc *sc = hw->priv;
- int error;
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: Driver halt\n", __func__);
+ if (sc->sc_flags & SC_OP_INVALID) {
+ DPRINTF(sc, ATH_DBG_ANY, "Device not present\n");
+ return;
+ }
- error = ath_suspend(sc);
- if (error)
- DPRINTF(sc, ATH_DBG_CONFIG,
- "%s: Device is no longer present\n", __func__);
+ DPRINTF(sc, ATH_DBG_CONFIG, "Cleaning up\n");
+
+ ieee80211_stop_queues(sc->hw);
+
+ /* make sure h/w will not generate any interrupt
+ * before setting the invalid flag. */
+ ath9k_hw_set_interrupts(sc->sc_ah, 0);
- ieee80211_stop_queues(hw);
+ if (!(sc->sc_flags & SC_OP_INVALID)) {
+ ath_draintxq(sc, false);
+ ath_stoprecv(sc);
+ ath9k_hw_phy_disable(sc->sc_ah);
+ } else
+ sc->rx.rxlink = NULL;
-#ifdef CONFIG_RFKILL
+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
#endif
+ /* disable HAL and put h/w to sleep */
+ ath9k_hw_disable(sc->sc_ah);
+ ath9k_hw_configpcipowersave(sc->sc_ah, 1);
+
+ sc->sc_flags |= SC_OP_INVALID;
+
+ DPRINTF(sc, ATH_DBG_CONFIG, "Driver halt\n");
}
static int ath9k_add_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
{
struct ath_softc *sc = hw->priv;
- int error, ic_opmode = 0;
+ struct ath_vap *avp = (void *)conf->vif->drv_priv;
+ enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED;
/* Support only vap for now */
@@ -1153,32 +2064,34 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
switch (conf->type) {
case NL80211_IFTYPE_STATION:
- ic_opmode = ATH9K_M_STA;
+ ic_opmode = NL80211_IFTYPE_STATION;
break;
case NL80211_IFTYPE_ADHOC:
- ic_opmode = ATH9K_M_IBSS;
+ ic_opmode = NL80211_IFTYPE_ADHOC;
break;
case NL80211_IFTYPE_AP:
- ic_opmode = ATH9K_M_HOSTAP;
+ ic_opmode = NL80211_IFTYPE_AP;
break;
default:
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: Interface type %d not yet supported\n",
- __func__, conf->type);
+ "Interface type %d not yet supported\n", conf->type);
return -EOPNOTSUPP;
}
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a VAP of type: %d\n",
- __func__,
- ic_opmode);
+ DPRINTF(sc, ATH_DBG_CONFIG, "Attach a VAP of type: %d\n", ic_opmode);
- error = ath_vap_attach(sc, 0, conf->vif, ic_opmode);
- if (error) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: Unable to attach vap, error: %d\n",
- __func__, error);
- return error;
- }
+ /* Set the VAP opmode */
+ avp->av_opmode = ic_opmode;
+ avp->av_bslot = -1;
+
+ if (ic_opmode == NL80211_IFTYPE_AP)
+ ath9k_hw_set_tsfadjust(sc->sc_ah, 1);
+
+ sc->sc_vaps[0] = conf->vif;
+ sc->sc_nvaps++;
+
+ /* Set the device opmode */
+ sc->sc_ah->ah_opmode = ic_opmode;
if (conf->type == NL80211_IFTYPE_AP) {
/* TODO: is this a suitable place to start ANI for AP mode? */
@@ -1194,78 +2107,76 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
{
struct ath_softc *sc = hw->priv;
- struct ath_vap *avp;
- int error;
-
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: Detach VAP\n", __func__);
+ struct ath_vap *avp = (void *)conf->vif->drv_priv;
- avp = sc->sc_vaps[0];
- if (avp == NULL) {
- DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
- __func__);
- return;
- }
+ DPRINTF(sc, ATH_DBG_CONFIG, "Detach Interface\n");
-#ifdef CONFIG_SLOW_ANT_DIV
- ath_slow_ant_div_stop(&sc->sc_antdiv);
-#endif
/* Stop ANI */
del_timer_sync(&sc->sc_ani.timer);
- /* Update ratectrl */
- ath_rate_newstate(sc, avp);
-
/* Reclaim beacon resources */
- if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP ||
- sc->sc_ah->ah_opmode == ATH9K_M_IBSS) {
- ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq);
+ if (sc->sc_ah->ah_opmode == NL80211_IFTYPE_AP ||
+ sc->sc_ah->ah_opmode == NL80211_IFTYPE_ADHOC) {
+ ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
ath_beacon_return(sc, avp);
}
- /* Set interrupt mask */
- sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
- ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_imask & ~ATH9K_INT_GLOBAL);
sc->sc_flags &= ~SC_OP_BEACONS;
- error = ath_vap_detach(sc, 0);
- if (error)
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: Unable to detach vap, error: %d\n",
- __func__, error);
+ sc->sc_vaps[0] = NULL;
+ sc->sc_nvaps--;
}
-static int ath9k_config(struct ieee80211_hw *hw,
- struct ieee80211_conf *conf)
+static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
{
struct ath_softc *sc = hw->priv;
- struct ieee80211_channel *curchan = hw->conf.channel;
- int pos;
+ struct ieee80211_conf *conf = &hw->conf;
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set channel: %d MHz\n",
- __func__,
- curchan->center_freq);
+ mutex_lock(&sc->mutex);
+ if (changed & (IEEE80211_CONF_CHANGE_CHANNEL |
+ IEEE80211_CONF_CHANGE_HT)) {
+ struct ieee80211_channel *curchan = hw->conf.channel;
+ int pos;
- pos = ath_get_channel(sc, curchan);
- if (pos == -1) {
- DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__);
- return -EINVAL;
- }
+ DPRINTF(sc, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
+ curchan->center_freq);
- sc->sc_ah->ah_channels[pos].chanmode =
- (curchan->band == IEEE80211_BAND_2GHZ) ?
- CHANNEL_G : CHANNEL_A;
+ pos = ath_get_channel(sc, curchan);
+ if (pos == -1) {
+ DPRINTF(sc, ATH_DBG_FATAL, "Invalid channel: %d\n",
+ curchan->center_freq);
+ mutex_unlock(&sc->mutex);
+ return -EINVAL;
+ }
- if (sc->sc_curaid && hw->conf.ht_conf.ht_supported)
+ sc->tx_chan_width = ATH9K_HT_MACMODE_20;
sc->sc_ah->ah_channels[pos].chanmode =
- ath_get_extchanmode(sc, curchan);
+ (curchan->band == IEEE80211_BAND_2GHZ) ?
+ CHANNEL_G : CHANNEL_A;
- sc->sc_config.txpowlimit = 2 * conf->power_level;
+ if (conf->ht.enabled) {
+ if (conf->ht.channel_type == NL80211_CHAN_HT40PLUS ||
+ conf->ht.channel_type == NL80211_CHAN_HT40MINUS)
+ sc->tx_chan_width = ATH9K_HT_MACMODE_2040;
- /* set h/w channel */
- if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0)
- DPRINTF(sc, ATH_DBG_FATAL, "%s: Unable to set channel\n",
- __func__);
+ sc->sc_ah->ah_channels[pos].chanmode =
+ ath_get_extchanmode(sc, curchan,
+ conf->ht.channel_type);
+ }
+
+ if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) {
+ DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n");
+ mutex_unlock(&sc->mutex);
+ return -EINVAL;
+ }
+
+ ath_update_chainmask(sc, conf->ht.enabled);
+ }
+
+ if (changed & IEEE80211_CONF_CHANGE_POWER)
+ sc->sc_config.txpowlimit = 2 * conf->power_level;
+ mutex_unlock(&sc->mutex);
return 0;
}
@@ -1275,23 +2186,15 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
{
struct ath_softc *sc = hw->priv;
struct ath_hal *ah = sc->sc_ah;
- struct ath_vap *avp;
+ struct ath_vap *avp = (void *)vif->drv_priv;
u32 rfilt = 0;
int error, i;
- DECLARE_MAC_BUF(mac);
-
- avp = sc->sc_vaps[0];
- if (avp == NULL) {
- DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid interface\n",
- __func__);
- return -EINVAL;
- }
/* TODO: Need to decide which hw opmode to use for multi-interface
* cases */
if (vif->type == NL80211_IFTYPE_AP &&
- ah->ah_opmode != ATH9K_M_HOSTAP) {
- ah->ah_opmode = ATH9K_M_HOSTAP;
+ ah->ah_opmode != NL80211_IFTYPE_AP) {
+ ah->ah_opmode = NL80211_IFTYPE_STATION;
ath9k_hw_setopmode(ah);
ath9k_hw_write_associd(ah, sc->sc_myaddr, 0);
/* Request full reset to get hw opmode changed properly */
@@ -1303,9 +2206,6 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
switch (vif->type) {
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
- /* Update ratectrl about the new state */
- ath_rate_newstate(sc, avp);
-
/* Set BSSID */
memcpy(sc->sc_curbssid, conf->bssid, ETH_ALEN);
sc->sc_curaid = 0;
@@ -1315,27 +2215,9 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
/* Set aggregation protection mode parameters */
sc->sc_config.ath_aggr_prot = 0;
- /*
- * Reset our TSF so that its value is lower than the
- * beacon that we are trying to catch.
- * Only then hw will update its TSF register with the
- * new beacon. Reset the TSF before setting the BSSID
- * to avoid allowing in any frames that would update
- * our TSF only to have us clear it
- * immediately thereafter.
- */
- ath9k_hw_reset_tsf(sc->sc_ah);
-
- /* Disable BMISS interrupt when we're not associated */
- ath9k_hw_set_interrupts(sc->sc_ah,
- sc->sc_imask &
- ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS));
- sc->sc_imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
-
DPRINTF(sc, ATH_DBG_CONFIG,
- "%s: RX filter 0x%x bssid %s aid 0x%x\n",
- __func__, rfilt,
- print_mac(mac, sc->sc_curbssid), sc->sc_curaid);
+ "RX filter 0x%x bssid %pM aid 0x%x\n",
+ rfilt, sc->sc_curbssid, sc->sc_curaid);
/* need to reconfigure the beacon */
sc->sc_flags &= ~SC_OP_BEACONS ;
@@ -1357,7 +2239,7 @@ static int ath9k_config_interface(struct ieee80211_hw *hw,
* causes reconfiguration; we may be called
* with beacon transmission active.
*/
- ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq);
+ ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
error = ath_beacon_alloc(sc, 0);
if (error != 0)
@@ -1403,7 +2285,7 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw,
changed_flags &= SUPPORTED_FILTERS;
*total_flags &= SUPPORTED_FILTERS;
- sc->rx_filter = *total_flags;
+ sc->rx.rxfilter = *total_flags;
rfilt = ath_calcrxfilter(sc);
ath9k_hw_setrxfilter(sc->sc_ah, rfilt);
@@ -1412,8 +2294,7 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw,
ath9k_hw_write_associd(sc->sc_ah, ath_bcast_mac, 0);
}
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: Set HW RX filter: 0x%x\n",
- __func__, sc->rx_filter);
+ DPRINTF(sc, ATH_DBG_CONFIG, "Set HW RX filter: 0x%x\n", sc->rx.rxfilter);
}
static void ath9k_sta_notify(struct ieee80211_hw *hw,
@@ -1422,37 +2303,13 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw,
struct ieee80211_sta *sta)
{
struct ath_softc *sc = hw->priv;
- struct ath_node *an;
- unsigned long flags;
- DECLARE_MAC_BUF(mac);
-
- spin_lock_irqsave(&sc->node_lock, flags);
- an = ath_node_find(sc, sta->addr);
- spin_unlock_irqrestore(&sc->node_lock, flags);
switch (cmd) {
case STA_NOTIFY_ADD:
- spin_lock_irqsave(&sc->node_lock, flags);
- if (!an) {
- ath_node_attach(sc, sta->addr, 0);
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: Attach a node: %s\n",
- __func__, print_mac(mac, sta->addr));
- } else {
- ath_node_get(sc, sta->addr);
- }
- spin_unlock_irqrestore(&sc->node_lock, flags);
+ ath_node_attach(sc, sta);
break;
case STA_NOTIFY_REMOVE:
- if (!an)
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: Removal of a non-existent node\n",
- __func__);
- else {
- ath_node_put(sc, an, ATH9K_BH_STATUS_INTACT);
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: Put a node: %s\n",
- __func__,
- print_mac(mac, sta->addr));
- }
+ ath_node_detach(sc, sta);
break;
default:
break;
@@ -1477,20 +2334,14 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw,
qnum = ath_get_hal_qnum(queue, sc);
DPRINTF(sc, ATH_DBG_CONFIG,
- "%s: Configure tx [queue/halq] [%d/%d], "
+ "Configure tx [queue/halq] [%d/%d], "
"aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
- __func__,
- queue,
- qnum,
- params->aifs,
- params->cw_min,
- params->cw_max,
- params->txop);
+ queue, qnum, params->aifs, params->cw_min,
+ params->cw_max, params->txop);
ret = ath_txq_update(sc, qnum, &qi);
if (ret)
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: TXQ Update failed\n", __func__);
+ DPRINTF(sc, ATH_DBG_FATAL, "TXQ Update failed\n");
return ret;
}
@@ -1504,23 +2355,22 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
struct ath_softc *sc = hw->priv;
int ret = 0;
- DPRINTF(sc, ATH_DBG_KEYCACHE, " %s: Set HW Key\n", __func__);
+ DPRINTF(sc, ATH_DBG_KEYCACHE, "Set HW Key\n");
switch (cmd) {
case SET_KEY:
ret = ath_key_config(sc, addr, key);
- if (!ret) {
- set_bit(key->keyidx, sc->sc_keymap);
- key->hw_key_idx = key->keyidx;
+ if (ret >= 0) {
+ key->hw_key_idx = ret;
/* push IV and Michael MIC generation to stack */
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
if (key->alg == ALG_TKIP)
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+ ret = 0;
}
break;
case DISABLE_KEY:
ath_key_delete(sc, key);
- clear_bit(key->keyidx, sc->sc_keymap);
break;
default:
ret = -EINVAL;
@@ -1537,8 +2387,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
struct ath_softc *sc = hw->priv;
if (changed & BSS_CHANGED_ERP_PREAMBLE) {
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed PREAMBLE %d\n",
- __func__,
+ DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n",
bss_conf->use_short_preamble);
if (bss_conf->use_short_preamble)
sc->sc_flags |= SC_OP_PREAMBLE_SHORT;
@@ -1547,8 +2396,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
}
if (changed & BSS_CHANGED_ERP_CTS_PROT) {
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed CTS PROT %d\n",
- __func__,
+ DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n",
bss_conf->use_cts_prot);
if (bss_conf->use_cts_prot &&
hw->conf.channel->band != IEEE80211_BAND_5GHZ)
@@ -1557,18 +2405,10 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
sc->sc_flags &= ~SC_OP_PROTECT_ENABLE;
}
- if (changed & BSS_CHANGED_HT) {
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed HT %d\n",
- __func__,
- bss_conf->assoc_ht);
- ath9k_ht_conf(sc, bss_conf);
- }
-
if (changed & BSS_CHANGED_ASSOC) {
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed ASSOC %d\n",
- __func__,
+ DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
bss_conf->assoc);
- ath9k_bss_assoc_info(sc, bss_conf);
+ ath9k_bss_assoc_info(sc, vif, bss_conf);
}
}
@@ -1601,50 +2441,37 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
switch (action) {
case IEEE80211_AMPDU_RX_START:
- ret = ath_rx_aggr_start(sc, sta->addr, tid, ssn);
- if (ret < 0)
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: Unable to start RX aggregation\n",
- __func__);
+ if (!(sc->sc_flags & SC_OP_RXAGGR))
+ ret = -ENOTSUPP;
break;
case IEEE80211_AMPDU_RX_STOP:
- ret = ath_rx_aggr_stop(sc, sta->addr, tid);
- if (ret < 0)
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: Unable to stop RX aggregation\n",
- __func__);
break;
case IEEE80211_AMPDU_TX_START:
- ret = ath_tx_aggr_start(sc, sta->addr, tid, ssn);
+ ret = ath_tx_aggr_start(sc, sta, tid, ssn);
if (ret < 0)
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: Unable to start TX aggregation\n",
- __func__);
+ "Unable to start TX aggregation\n");
else
ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_STOP:
- ret = ath_tx_aggr_stop(sc, sta->addr, tid);
+ ret = ath_tx_aggr_stop(sc, sta, tid);
if (ret < 0)
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: Unable to stop TX aggregation\n",
- __func__);
+ "Unable to stop TX aggregation\n");
ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid);
break;
+ case IEEE80211_AMPDU_TX_RESUME:
+ ath_tx_aggr_resume(sc, sta, tid);
+ break;
default:
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: Unknown AMPDU action\n", __func__);
+ DPRINTF(sc, ATH_DBG_FATAL, "Unknown AMPDU action\n");
}
return ret;
}
-static int ath9k_no_fragmentation(struct ieee80211_hw *hw, u32 value)
-{
- return -EOPNOTSUPP;
-}
-
static struct ieee80211_ops ath9k_ops = {
.tx = ath9k_tx,
.start = ath9k_start,
@@ -1654,42 +2481,97 @@ static struct ieee80211_ops ath9k_ops = {
.config = ath9k_config,
.config_interface = ath9k_config_interface,
.configure_filter = ath9k_configure_filter,
- .get_stats = NULL,
.sta_notify = ath9k_sta_notify,
.conf_tx = ath9k_conf_tx,
- .get_tx_stats = NULL,
.bss_info_changed = ath9k_bss_info_changed,
- .set_tim = NULL,
.set_key = ath9k_set_key,
- .hw_scan = NULL,
- .get_tkip_seq = NULL,
- .set_rts_threshold = NULL,
- .set_frag_threshold = NULL,
- .set_retry_limit = NULL,
.get_tsf = ath9k_get_tsf,
.reset_tsf = ath9k_reset_tsf,
- .tx_last_beacon = NULL,
.ampdu_action = ath9k_ampdu_action,
- .set_frag_threshold = ath9k_no_fragmentation,
};
+static struct {
+ u32 version;
+ const char * name;
+} ath_mac_bb_names[] = {
+ { AR_SREV_VERSION_5416_PCI, "5416" },
+ { AR_SREV_VERSION_5416_PCIE, "5418" },
+ { AR_SREV_VERSION_9100, "9100" },
+ { AR_SREV_VERSION_9160, "9160" },
+ { AR_SREV_VERSION_9280, "9280" },
+ { AR_SREV_VERSION_9285, "9285" }
+};
+
+static struct {
+ u16 version;
+ const char * name;
+} ath_rf_names[] = {
+ { 0, "5133" },
+ { AR_RAD5133_SREV_MAJOR, "5133" },
+ { AR_RAD5122_SREV_MAJOR, "5122" },
+ { AR_RAD2133_SREV_MAJOR, "2133" },
+ { AR_RAD2122_SREV_MAJOR, "2122" }
+};
+
+/*
+ * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown.
+ */
+static const char *
+ath_mac_bb_name(u32 mac_bb_version)
+{
+ int i;
+
+ for (i=0; i<ARRAY_SIZE(ath_mac_bb_names); i++) {
+ if (ath_mac_bb_names[i].version == mac_bb_version) {
+ return ath_mac_bb_names[i].name;
+ }
+ }
+
+ return "????";
+}
+
+/*
+ * Return the RF name. "????" is returned if the RF is unknown.
+ */
+static const char *
+ath_rf_name(u16 rf_version)
+{
+ int i;
+
+ for (i=0; i<ARRAY_SIZE(ath_rf_names); i++) {
+ if (ath_rf_names[i].version == rf_version) {
+ return ath_rf_names[i].name;
+ }
+ }
+
+ return "????";
+}
+
static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
void __iomem *mem;
struct ath_softc *sc;
struct ieee80211_hw *hw;
- const char *athname;
u8 csz;
u32 val;
int ret = 0;
+ struct ath_hal *ah;
if (pci_enable_device(pdev))
return -EIO;
- /* XXX 32-bit addressing only */
- if (pci_set_dma_mask(pdev, 0xffffffff)) {
- printk(KERN_ERR "ath_pci: 32-bit DMA not available\n");
- ret = -ENODEV;
+ ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
+
+ if (ret) {
+ printk(KERN_ERR "ath9k: 32-bit DMA not available\n");
+ goto bad;
+ }
+
+ ret = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
+
+ if (ret) {
+ printk(KERN_ERR "ath9k: 32-bit DMA consistent "
+ "DMA enable failed\n");
goto bad;
}
@@ -1746,16 +2628,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto bad2;
}
- hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
- IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
- IEEE80211_HW_SIGNAL_DBM |
- IEEE80211_HW_NOISE_DBM;
-
- hw->wiphy->interface_modes =
- BIT(NL80211_IFTYPE_AP) |
- BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC);
-
SET_IEEE80211_DEV(hw, &pdev->dev);
pci_set_drvdata(pdev, hw);
@@ -1778,11 +2650,15 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto bad4;
}
- athname = ath9k_hw_probe(id->vendor, id->device);
-
- printk(KERN_INFO "%s: %s: mem=0x%lx, irq=%d\n",
+ ah = sc->sc_ah;
+ printk(KERN_INFO
+ "%s: Atheros AR%s MAC/BB Rev:%x "
+ "AR%s RF Rev:%x: mem=0x%lx, irq=%d\n",
wiphy_name(hw->wiphy),
- athname ? athname : "Atheros ???",
+ ath_mac_bb_name(ah->ah_macVersion),
+ ah->ah_macRev,
+ ath_rf_name((ah->ah_analog5GhzRev & AR_RADIO_SREV_MAJOR)),
+ ah->ah_phyRev,
(unsigned long)mem, pdev->irq);
return 0;
@@ -1803,17 +2679,10 @@ static void ath_pci_remove(struct pci_dev *pdev)
{
struct ieee80211_hw *hw = pci_get_drvdata(pdev);
struct ath_softc *sc = hw->priv;
- enum ath9k_int status;
- if (pdev->irq) {
- ath9k_hw_set_interrupts(sc->sc_ah, 0);
- /* clear the ISR */
- ath9k_hw_getisr(sc->sc_ah, &status);
- sc->sc_flags |= SC_OP_INVALID;
- free_irq(pdev->irq, sc);
- }
ath_detach(sc);
-
+ if (pdev->irq)
+ free_irq(pdev->irq, sc);
pci_iounmap(pdev, sc->mem);
pci_release_region(pdev, 0);
pci_disable_device(pdev);
@@ -1829,7 +2698,7 @@ static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state)
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
-#ifdef CONFIG_RFKILL
+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
cancel_delayed_work_sync(&sc->rf_kill.rfkill_poll);
#endif
@@ -1866,7 +2735,7 @@ static int ath_pci_resume(struct pci_dev *pdev)
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1);
-#ifdef CONFIG_RFKILL
+#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE)
/*
* check the h/w rfkill state on resume
* and start the rfkill poll timer
@@ -1896,11 +2765,24 @@ static struct pci_driver ath_pci_driver = {
static int __init init_ath_pci(void)
{
+ int error;
+
printk(KERN_INFO "%s: %s\n", dev_info, ATH_PCI_VERSION);
+ /* Register rate control algorithm */
+ error = ath_rate_control_register();
+ if (error != 0) {
+ printk(KERN_ERR
+ "Unable to register rate control algorithm: %d\n",
+ error);
+ ath_rate_control_unregister();
+ return error;
+ }
+
if (pci_register_driver(&ath_pci_driver) < 0) {
printk(KERN_ERR
"ath_pci: No devices found, driver not installed.\n");
+ ath_rate_control_unregister();
pci_unregister_driver(&ath_pci_driver);
return -ENODEV;
}
@@ -1911,7 +2793,8 @@ module_init(init_ath_pci);
static void __exit exit_ath_pci(void)
{
+ ath_rate_control_unregister();
pci_unregister_driver(&ath_pci_driver);
- printk(KERN_INFO "%s: driver unloaded\n", dev_info);
+ printk(KERN_INFO "%s: Driver unloaded\n", dev_info);
}
module_exit(exit_ath_pci);
diff --git a/drivers/net/wireless/ath9k/phy.c b/drivers/net/wireless/ath9k/phy.c
index eb9121fdfd38..766982a8196e 100644
--- a/drivers/net/wireless/ath9k/phy.c
+++ b/drivers/net/wireless/ath9k/phy.c
@@ -52,8 +52,7 @@ ath9k_hw_set_channel(struct ath_hal *ah, struct ath9k_channel *chan)
bModeSynth = 1;
} else {
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
- "%s: invalid channel %u MHz\n", __func__,
- freq);
+ "Invalid channel %u MHz\n", freq);
return false;
}
@@ -86,7 +85,7 @@ ath9k_hw_set_channel(struct ath_hal *ah, struct ath9k_channel *chan)
aModeRefSel = ath9k_hw_reverse_bits(1, 2);
} else {
DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL,
- "%s: invalid channel %u MHz\n", __func__, freq);
+ "Invalid channel %u MHz\n", freq);
return false;
}
@@ -215,7 +214,7 @@ ath9k_hw_set_rf_regs(struct ath_hal *ah, struct ath9k_channel *chan,
if (AR_SREV_9280_10_OR_LATER(ah))
return true;
- eepMinorRev = ath9k_hw_get_eeprom(ahp, EEP_MINOR_REV);
+ eepMinorRev = ath9k_hw_get_eeprom(ah, EEP_MINOR_REV);
RF_BANK_SETUP(ahp->ah_analogBank0Data, &ahp->ah_iniBank0, 1);
@@ -235,15 +234,15 @@ ath9k_hw_set_rf_regs(struct ath_hal *ah, struct ath9k_channel *chan,
if (eepMinorRev >= 2) {
if (IS_CHAN_2GHZ(chan)) {
- ob2GHz = ath9k_hw_get_eeprom(ahp, EEP_OB_2);
- db2GHz = ath9k_hw_get_eeprom(ahp, EEP_DB_2);
+ ob2GHz = ath9k_hw_get_eeprom(ah, EEP_OB_2);
+ db2GHz = ath9k_hw_get_eeprom(ah, EEP_DB_2);
ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data,
ob2GHz, 3, 197, 0);
ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data,
db2GHz, 3, 194, 0);
} else {
- ob5GHz = ath9k_hw_get_eeprom(ahp, EEP_OB_5);
- db5GHz = ath9k_hw_get_eeprom(ahp, EEP_DB_5);
+ ob5GHz = ath9k_hw_get_eeprom(ah, EEP_OB_5);
+ db5GHz = ath9k_hw_get_eeprom(ah, EEP_DB_5);
ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data,
ob5GHz, 3, 203, 0);
ath9k_phy_modify_rx_buffer(ahp->ah_analogBank6Data,
@@ -348,8 +347,7 @@ bool ath9k_hw_init_rf(struct ath_hal *ah, int *status)
|| ahp->ah_analogBank6TPCData == NULL
|| ahp->ah_analogBank7Data == NULL) {
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
- "%s: cannot allocate RF banks\n",
- __func__);
+ "Cannot allocate RF banks\n");
*status = -ENOMEM;
return false;
}
@@ -360,8 +358,7 @@ bool ath9k_hw_init_rf(struct ath_hal *ah, int *status)
ahp->ah_iniAddac.ia_columns), GFP_KERNEL);
if (ahp->ah_addac5416_21 == NULL) {
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
- "%s: cannot allocate ah_addac5416_21\n",
- __func__);
+ "Cannot allocate ah_addac5416_21\n");
*status = -ENOMEM;
return false;
}
@@ -371,8 +368,7 @@ bool ath9k_hw_init_rf(struct ath_hal *ah, int *status)
ahp->ah_iniBank6.ia_rows), GFP_KERNEL);
if (ahp->ah_bank6Temp == NULL) {
DPRINTF(ah->ah_sc, ATH_DBG_FATAL,
- "%s: cannot allocate ah_bank6Temp\n",
- __func__);
+ "Cannot allocate ah_bank6Temp\n");
*status = -ENOMEM;
return false;
}
diff --git a/drivers/net/wireless/ath9k/phy.h b/drivers/net/wireless/ath9k/phy.h
index 14702344448b..3a406a5c0593 100644
--- a/drivers/net/wireless/ath9k/phy.h
+++ b/drivers/net/wireless/ath9k/phy.h
@@ -50,6 +50,9 @@ bool ath9k_hw_init_rf(struct ath_hal *ah,
#define AR_PHY_FC_SHORT_GI_40 0x00000080
#define AR_PHY_FC_WALSH 0x00000100
#define AR_PHY_FC_SINGLE_HT_LTF1 0x00000200
+#define AR_PHY_FC_ENABLE_DAC_FIFO 0x00000800
+
+#define AR_PHY_TEST2 0x9808
#define AR_PHY_TIMING2 0x9810
#define AR_PHY_TIMING3 0x9814
@@ -100,6 +103,8 @@ bool ath9k_hw_init_rf(struct ath_hal *ah,
#define AR_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000FF
#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S 0
+#define AR_PHY_TSTDAC_CONST 0x983c
+
#define AR_PHY_SETTLING 0x9844
#define AR_PHY_SETTLING_SWITCH 0x00003F80
#define AR_PHY_SETTLING_SWITCH_S 7
diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c
index cca2fc5b0765..04ab457a8faa 100644
--- a/drivers/net/wireless/ath9k/rc.c
+++ b/drivers/net/wireless/ath9k/rc.c
@@ -15,143 +15,136 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/*
- * Atheros rate control algorithm
- */
-
#include "core.h"
-/* FIXME: remove this include! */
-#include "../net/mac80211/rate.h"
-
-static u32 tx_triglevel_max;
static struct ath_rate_table ar5416_11na_ratetable = {
42,
+ {0},
{
- { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 6 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
5400, 0x0b, 0x00, 12,
0, 2, 1, 0, 0, 0, 0, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 9 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
7800, 0x0f, 0x00, 18,
0, 3, 1, 1, 1, 1, 1, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
10000, 0x0a, 0x00, 24,
2, 4, 2, 2, 2, 2, 2, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
13900, 0x0e, 0x00, 36,
2, 6, 2, 3, 3, 3, 3, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
17300, 0x09, 0x00, 48,
4, 10, 3, 4, 4, 4, 4, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
23000, 0x0d, 0x00, 72,
4, 14, 3, 5, 5, 5, 5, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
27400, 0x08, 0x00, 96,
4, 20, 3, 6, 6, 6, 6, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
29300, 0x0c, 0x00, 108,
4, 23, 3, 7, 7, 7, 7, 0 },
- { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 6500, /* 6.5 Mb */
+ { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
6400, 0x80, 0x00, 0,
0, 2, 3, 8, 24, 8, 24, 3216 },
- { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 13000, /* 13 Mb */
+ { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
12700, 0x81, 0x00, 1,
2, 4, 3, 9, 25, 9, 25, 6434 },
- { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 19500, /* 19.5 Mb */
+ { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
18800, 0x82, 0x00, 2,
2, 6, 3, 10, 26, 10, 26, 9650 },
- { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 26000, /* 26 Mb */
+ { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
25000, 0x83, 0x00, 3,
4, 10, 3, 11, 27, 11, 27, 12868 },
- { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 39000, /* 39 Mb */
+ { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
36700, 0x84, 0x00, 4,
4, 14, 3, 12, 28, 12, 28, 19304 },
- { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 52000, /* 52 Mb */
+ { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
48100, 0x85, 0x00, 5,
4, 20, 3, 13, 29, 13, 29, 25740 },
- { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 58500, /* 58.5 Mb */
+ { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
53500, 0x86, 0x00, 6,
4, 23, 3, 14, 30, 14, 30, 28956 },
- { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 65000, /* 65 Mb */
+ { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
59000, 0x87, 0x00, 7,
4, 25, 3, 15, 31, 15, 32, 32180 },
- { FALSE, FALSE, WLAN_PHY_HT_20_DS, 13000, /* 13 Mb */
+ { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
12700, 0x88, 0x00,
8, 0, 2, 3, 16, 33, 16, 33, 6430 },
- { FALSE, FALSE, WLAN_PHY_HT_20_DS, 26000, /* 26 Mb */
+ { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
24800, 0x89, 0x00, 9,
2, 4, 3, 17, 34, 17, 34, 12860 },
- { FALSE, FALSE, WLAN_PHY_HT_20_DS, 39000, /* 39 Mb */
+ { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
36600, 0x8a, 0x00, 10,
2, 6, 3, 18, 35, 18, 35, 19300 },
- { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 52000, /* 52 Mb */
+ { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
48100, 0x8b, 0x00, 11,
4, 10, 3, 19, 36, 19, 36, 25736 },
- { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 78000, /* 78 Mb */
+ { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
69500, 0x8c, 0x00, 12,
4, 14, 3, 20, 37, 20, 37, 38600 },
- { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 104000, /* 104 Mb */
+ { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
89500, 0x8d, 0x00, 13,
4, 20, 3, 21, 38, 21, 38, 51472 },
- { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 117000, /* 117 Mb */
+ { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
98900, 0x8e, 0x00, 14,
4, 23, 3, 22, 39, 22, 39, 57890 },
- { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 130000, /* 130 Mb */
+ { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
108300, 0x8f, 0x00, 15,
4, 25, 3, 23, 40, 23, 41, 64320 },
- { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 13500, /* 13.5 Mb */
+ { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
13200, 0x80, 0x00, 0,
0, 2, 3, 8, 24, 24, 24, 6684 },
- { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 27500, /* 27.0 Mb */
+ { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
25900, 0x81, 0x00, 1,
2, 4, 3, 9, 25, 25, 25, 13368 },
- { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 40500, /* 40.5 Mb */
+ { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
38600, 0x82, 0x00, 2,
2, 6, 3, 10, 26, 26, 26, 20052 },
- { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 54000, /* 54 Mb */
+ { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
49800, 0x83, 0x00, 3,
4, 10, 3, 11, 27, 27, 27, 26738 },
- { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 81500, /* 81 Mb */
+ { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
72200, 0x84, 0x00, 4,
4, 14, 3, 12, 28, 28, 28, 40104 },
- { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 108000, /* 108 Mb */
+ { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
92900, 0x85, 0x00, 5,
4, 20, 3, 13, 29, 29, 29, 53476 },
- { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 121500, /* 121.5 Mb */
+ { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */
102700, 0x86, 0x00, 6,
4, 23, 3, 14, 30, 30, 30, 60156 },
- { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 135000, /* 135 Mb */
+ { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
112000, 0x87, 0x00, 7,
4, 25, 3, 15, 31, 32, 32, 66840 },
- { FALSE, TRUE_40, WLAN_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
+ { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
122000, 0x87, 0x00, 7,
4, 25, 3, 15, 31, 32, 32, 74200 },
- { FALSE, FALSE, WLAN_PHY_HT_40_DS, 27000, /* 27 Mb */
+ { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
25800, 0x88, 0x00, 8,
0, 2, 3, 16, 33, 33, 33, 13360 },
- { FALSE, FALSE, WLAN_PHY_HT_40_DS, 54000, /* 54 Mb */
+ { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
49800, 0x89, 0x00, 9,
2, 4, 3, 17, 34, 34, 34, 26720 },
- { FALSE, FALSE, WLAN_PHY_HT_40_DS, 81000, /* 81 Mb */
+ { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
71900, 0x8a, 0x00, 10,
2, 6, 3, 18, 35, 35, 35, 40080 },
- { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 108000, /* 108 Mb */
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
92500, 0x8b, 0x00, 11,
4, 10, 3, 19, 36, 36, 36, 53440 },
- { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 162000, /* 162 Mb */
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
130300, 0x8c, 0x00, 12,
4, 14, 3, 20, 37, 37, 37, 80160 },
- { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 216000, /* 216 Mb */
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
162800, 0x8d, 0x00, 13,
4, 20, 3, 21, 38, 38, 38, 106880 },
- { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 243000, /* 243 Mb */
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
178200, 0x8e, 0x00, 14,
4, 23, 3, 22, 39, 39, 39, 120240 },
- { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 270000, /* 270 Mb */
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
192100, 0x8f, 0x00, 15,
4, 25, 3, 23, 40, 41, 41, 133600 },
- { TRUE_40, FALSE, WLAN_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
207000, 0x8f, 0x00, 15,
4, 25, 3, 23, 40, 41, 41, 148400 },
},
@@ -160,153 +153,149 @@ static struct ath_rate_table ar5416_11na_ratetable = {
WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
};
-/* TRUE_ALL - valid for 20/40/Legacy,
- * TRUE - Legacy only,
- * TRUE_20 - HT 20 only,
- * TRUE_40 - HT 40 only */
-
/* 4ms frame limit not used for NG mode. The values filled
* for HT are the 64K max aggregate limit */
static struct ath_rate_table ar5416_11ng_ratetable = {
46,
+ {0},
{
- { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 1000, /* 1 Mb */
+ { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
900, 0x1b, 0x00, 2,
0, 0, 1, 0, 0, 0, 0, 0 },
- { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 2000, /* 2 Mb */
+ { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
1900, 0x1a, 0x04, 4,
1, 1, 1, 1, 1, 1, 1, 0 },
- { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 5500, /* 5.5 Mb */
+ { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
4900, 0x19, 0x04, 11,
2, 2, 2, 2, 2, 2, 2, 0 },
- { TRUE_ALL, TRUE_ALL, WLAN_PHY_CCK, 11000, /* 11 Mb */
+ { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
8100, 0x18, 0x04, 22,
3, 3, 2, 3, 3, 3, 3, 0 },
- { FALSE, FALSE, WLAN_PHY_OFDM, 6000, /* 6 Mb */
+ { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
5400, 0x0b, 0x00, 12,
4, 2, 1, 4, 4, 4, 4, 0 },
- { FALSE, FALSE, WLAN_PHY_OFDM, 9000, /* 9 Mb */
+ { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
7800, 0x0f, 0x00, 18,
4, 3, 1, 5, 5, 5, 5, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
10100, 0x0a, 0x00, 24,
6, 4, 1, 6, 6, 6, 6, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
14100, 0x0e, 0x00, 36,
6, 6, 2, 7, 7, 7, 7, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
17700, 0x09, 0x00, 48,
8, 10, 3, 8, 8, 8, 8, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
23700, 0x0d, 0x00, 72,
8, 14, 3, 9, 9, 9, 9, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
27400, 0x08, 0x00, 96,
8, 20, 3, 10, 10, 10, 10, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
30900, 0x0c, 0x00, 108,
8, 23, 3, 11, 11, 11, 11, 0 },
- { FALSE, FALSE, WLAN_PHY_HT_20_SS, 6500, /* 6.5 Mb */
+ { INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
6400, 0x80, 0x00, 0,
4, 2, 3, 12, 28, 12, 28, 3216 },
- { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 13000, /* 13 Mb */
+ { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
12700, 0x81, 0x00, 1,
6, 4, 3, 13, 29, 13, 29, 6434 },
- { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 19500, /* 19.5 Mb */
+ { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
18800, 0x82, 0x00, 2,
6, 6, 3, 14, 30, 14, 30, 9650 },
- { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 26000, /* 26 Mb */
+ { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
25000, 0x83, 0x00, 3,
8, 10, 3, 15, 31, 15, 31, 12868 },
- { TRUE_20, TRUE_20, WLAN_PHY_HT_20_SS, 39000, /* 39 Mb */
+ { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
36700, 0x84, 0x00, 4,
8, 14, 3, 16, 32, 16, 32, 19304 },
- { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 52000, /* 52 Mb */
+ { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
48100, 0x85, 0x00, 5,
8, 20, 3, 17, 33, 17, 33, 25740 },
- { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 58500, /* 58.5 Mb */
+ { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
53500, 0x86, 0x00, 6,
8, 23, 3, 18, 34, 18, 34, 28956 },
- { FALSE, TRUE_20, WLAN_PHY_HT_20_SS, 65000, /* 65 Mb */
+ { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
59000, 0x87, 0x00, 7,
8, 25, 3, 19, 35, 19, 36, 32180 },
- { FALSE, FALSE, WLAN_PHY_HT_20_DS, 13000, /* 13 Mb */
+ { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
12700, 0x88, 0x00, 8,
4, 2, 3, 20, 37, 20, 37, 6430 },
- { FALSE, FALSE, WLAN_PHY_HT_20_DS, 26000, /* 26 Mb */
+ { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
24800, 0x89, 0x00, 9,
6, 4, 3, 21, 38, 21, 38, 12860 },
- { FALSE, FALSE, WLAN_PHY_HT_20_DS, 39000, /* 39 Mb */
+ { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
36600, 0x8a, 0x00, 10,
6, 6, 3, 22, 39, 22, 39, 19300 },
- { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 52000, /* 52 Mb */
+ { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
48100, 0x8b, 0x00, 11,
8, 10, 3, 23, 40, 23, 40, 25736 },
- { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 78000, /* 78 Mb */
+ { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
69500, 0x8c, 0x00, 12,
8, 14, 3, 24, 41, 24, 41, 38600 },
- { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 104000, /* 104 Mb */
+ { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
89500, 0x8d, 0x00, 13,
8, 20, 3, 25, 42, 25, 42, 51472 },
- { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 117000, /* 117 Mb */
+ { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
98900, 0x8e, 0x00, 14,
8, 23, 3, 26, 43, 26, 44, 57890 },
- { TRUE_20, FALSE, WLAN_PHY_HT_20_DS, 130000, /* 130 Mb */
+ { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
108300, 0x8f, 0x00, 15,
8, 25, 3, 27, 44, 27, 45, 64320 },
- { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 13500, /* 13.5 Mb */
+ { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
13200, 0x80, 0x00, 0,
8, 2, 3, 12, 28, 28, 28, 6684 },
- { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 27500, /* 27.0 Mb */
+ { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
25900, 0x81, 0x00, 1,
8, 4, 3, 13, 29, 29, 29, 13368 },
- { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 40500, /* 40.5 Mb */
+ { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
38600, 0x82, 0x00, 2,
8, 6, 3, 14, 30, 30, 30, 20052 },
- { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 54000, /* 54 Mb */
+ { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
49800, 0x83, 0x00, 3,
8, 10, 3, 15, 31, 31, 31, 26738 },
- { TRUE_40, TRUE_40, WLAN_PHY_HT_40_SS, 81500, /* 81 Mb */
+ { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
72200, 0x84, 0x00, 4,
8, 14, 3, 16, 32, 32, 32, 40104 },
- { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 108000, /* 108 Mb */
+ { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
92900, 0x85, 0x00, 5,
8, 20, 3, 17, 33, 33, 33, 53476 },
- { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 121500, /* 121.5 Mb */
+ { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */
102700, 0x86, 0x00, 6,
8, 23, 3, 18, 34, 34, 34, 60156 },
- { FALSE, TRUE_40, WLAN_PHY_HT_40_SS, 135000, /* 135 Mb */
+ { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
112000, 0x87, 0x00, 7,
8, 23, 3, 19, 35, 36, 36, 66840 },
- { FALSE, TRUE_40, WLAN_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
+ { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
122000, 0x87, 0x00, 7,
8, 25, 3, 19, 35, 36, 36, 74200 },
- { FALSE, FALSE, WLAN_PHY_HT_40_DS, 27000, /* 27 Mb */
+ { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
25800, 0x88, 0x00, 8,
8, 2, 3, 20, 37, 37, 37, 13360 },
- { FALSE, FALSE, WLAN_PHY_HT_40_DS, 54000, /* 54 Mb */
+ { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
49800, 0x89, 0x00, 9,
8, 4, 3, 21, 38, 38, 38, 26720 },
- { FALSE, FALSE, WLAN_PHY_HT_40_DS, 81000, /* 81 Mb */
+ { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
71900, 0x8a, 0x00, 10,
8, 6, 3, 22, 39, 39, 39, 40080 },
- { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 108000, /* 108 Mb */
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
92500, 0x8b, 0x00, 11,
8, 10, 3, 23, 40, 40, 40, 53440 },
- { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 162000, /* 162 Mb */
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
130300, 0x8c, 0x00, 12,
8, 14, 3, 24, 41, 41, 41, 80160 },
- { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 216000, /* 216 Mb */
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
162800, 0x8d, 0x00, 13,
8, 20, 3, 25, 42, 42, 42, 106880 },
- { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 243000, /* 243 Mb */
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
178200, 0x8e, 0x00, 14,
8, 23, 3, 26, 43, 43, 43, 120240 },
- { TRUE_40, FALSE, WLAN_PHY_HT_40_DS, 270000, /* 270 Mb */
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
192100, 0x8f, 0x00, 15,
8, 23, 3, 27, 44, 45, 45, 133600 },
- { TRUE_40, FALSE, WLAN_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
+ { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
207000, 0x8f, 0x00, 15,
8, 25, 3, 27, 44, 45, 45, 148400 },
},
@@ -317,29 +306,30 @@ static struct ath_rate_table ar5416_11ng_ratetable = {
static struct ath_rate_table ar5416_11a_ratetable = {
8,
+ {0},
{
- { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 6 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
5400, 0x0b, 0x00, (0x80|12),
0, 2, 1, 0, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 9 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
7800, 0x0f, 0x00, 18,
0, 3, 1, 1, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
10000, 0x0a, 0x00, (0x80|24),
2, 4, 2, 2, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
13900, 0x0e, 0x00, 36,
2, 6, 2, 3, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
17300, 0x09, 0x00, (0x80|48),
4, 10, 3, 4, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
23000, 0x0d, 0x00, 72,
4, 14, 3, 5, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
27400, 0x08, 0x00, 96,
4, 19, 3, 6, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
29300, 0x0c, 0x00, 108,
4, 23, 3, 7, 0 },
},
@@ -348,109 +338,44 @@ static struct ath_rate_table ar5416_11a_ratetable = {
0, /* Phy rates allowed initially */
};
-static struct ath_rate_table ar5416_11a_ratetable_Half = {
- 8,
- {
- { TRUE, TRUE, WLAN_PHY_OFDM, 3000, /* 6 Mb */
- 2700, 0x0b, 0x00, (0x80|6),
- 0, 2, 1, 0, 0},
- { TRUE, TRUE, WLAN_PHY_OFDM, 4500, /* 9 Mb */
- 3900, 0x0f, 0x00, 9,
- 0, 3, 1, 1, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 12 Mb */
- 5000, 0x0a, 0x00, (0x80|12),
- 2, 4, 2, 2, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 18 Mb */
- 6950, 0x0e, 0x00, 18,
- 2, 6, 2, 3, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 24 Mb */
- 8650, 0x09, 0x00, (0x80|24),
- 4, 10, 3, 4, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 36 Mb */
- 11500, 0x0d, 0x00, 36,
- 4, 14, 3, 5, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 48 Mb */
- 13700, 0x08, 0x00, 48,
- 4, 19, 3, 6, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 27000, /* 54 Mb */
- 14650, 0x0c, 0x00, 54,
- 4, 23, 3, 7, 0 },
- },
- 50, /* probe interval */
- 50, /* rssi reduce interval */
- 0, /* Phy rates allowed initially */
-};
-
-static struct ath_rate_table ar5416_11a_ratetable_Quarter = {
- 8,
- {
- { TRUE, TRUE, WLAN_PHY_OFDM, 1500, /* 6 Mb */
- 1350, 0x0b, 0x00, (0x80|3),
- 0, 2, 1, 0, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 2250, /* 9 Mb */
- 1950, 0x0f, 0x00, 4,
- 0, 3, 1, 1, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 3000, /* 12 Mb */
- 2500, 0x0a, 0x00, (0x80|6),
- 2, 4, 2, 2, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 4500, /* 18 Mb */
- 3475, 0x0e, 0x00, 9,
- 2, 6, 2, 3, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 6000, /* 25 Mb */
- 4325, 0x09, 0x00, (0x80|12),
- 4, 10, 3, 4, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 9000, /* 36 Mb */
- 5750, 0x0d, 0x00, 18,
- 4, 14, 3, 5, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 48 Mb */
- 6850, 0x08, 0x00, 24,
- 4, 19, 3, 6, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 13500, /* 54 Mb */
- 7325, 0x0c, 0x00, 27,
- 4, 23, 3, 7, 0 },
- },
- 50, /* probe interval */
- 50, /* rssi reduce interval */
- 0, /* Phy rates allowed initially */
-};
-
static struct ath_rate_table ar5416_11g_ratetable = {
12,
+ {0},
{
- { TRUE, TRUE, WLAN_PHY_CCK, 1000, /* 1 Mb */
+ { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
900, 0x1b, 0x00, 2,
0, 0, 1, 0, 0 },
- { TRUE, TRUE, WLAN_PHY_CCK, 2000, /* 2 Mb */
+ { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
1900, 0x1a, 0x04, 4,
1, 1, 1, 1, 0 },
- { TRUE, TRUE, WLAN_PHY_CCK, 5500, /* 5.5 Mb */
+ { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
4900, 0x19, 0x04, 11,
2, 2, 2, 2, 0 },
- { TRUE, TRUE, WLAN_PHY_CCK, 11000, /* 11 Mb */
+ { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
8100, 0x18, 0x04, 22,
3, 3, 2, 3, 0 },
- { FALSE, FALSE, WLAN_PHY_OFDM, 6000, /* 6 Mb */
+ { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
5400, 0x0b, 0x00, 12,
4, 2, 1, 4, 0 },
- { FALSE, FALSE, WLAN_PHY_OFDM, 9000, /* 9 Mb */
+ { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
7800, 0x0f, 0x00, 18,
4, 3, 1, 5, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 12000, /* 12 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
10000, 0x0a, 0x00, 24,
6, 4, 1, 6, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 18000, /* 18 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
13900, 0x0e, 0x00, 36,
6, 6, 2, 7, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 24000, /* 24 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
17300, 0x09, 0x00, 48,
8, 10, 3, 8, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 36000, /* 36 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
23000, 0x0d, 0x00, 72,
8, 14, 3, 9, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 48000, /* 48 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
27400, 0x08, 0x00, 96,
8, 19, 3, 10, 0 },
- { TRUE, TRUE, WLAN_PHY_OFDM, 54000, /* 54 Mb */
+ { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
29300, 0x0c, 0x00, 108,
8, 23, 3, 11, 0 },
},
@@ -461,17 +386,18 @@ static struct ath_rate_table ar5416_11g_ratetable = {
static struct ath_rate_table ar5416_11b_ratetable = {
4,
+ {0},
{
- { TRUE, TRUE, WLAN_PHY_CCK, 1000, /* 1 Mb */
+ { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
900, 0x1b, 0x00, (0x80|2),
0, 0, 1, 0, 0 },
- { TRUE, TRUE, WLAN_PHY_CCK, 2000, /* 2 Mb */
+ { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
1800, 0x1a, 0x04, (0x80|4),
1, 1, 1, 1, 0 },
- { TRUE, TRUE, WLAN_PHY_CCK, 5500, /* 5.5 Mb */
+ { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
4300, 0x19, 0x04, (0x80|11),
1, 2, 2, 2, 0 },
- { TRUE, TRUE, WLAN_PHY_CCK, 11000, /* 11 Mb */
+ { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
7100, 0x18, 0x04, (0x80|22),
1, 4, 100, 3, 0 },
},
@@ -480,48 +406,6 @@ static struct ath_rate_table ar5416_11b_ratetable = {
0, /* Phy rates allowed initially */
};
-static void ar5416_attach_ratetables(struct ath_rate_softc *sc)
-{
- /*
- * Attach rate tables.
- */
- sc->hw_rate_table[ATH9K_MODE_11B] = &ar5416_11b_ratetable;
- sc->hw_rate_table[ATH9K_MODE_11A] = &ar5416_11a_ratetable;
- sc->hw_rate_table[ATH9K_MODE_11G] = &ar5416_11g_ratetable;
-
- sc->hw_rate_table[ATH9K_MODE_11NA_HT20] = &ar5416_11na_ratetable;
- sc->hw_rate_table[ATH9K_MODE_11NG_HT20] = &ar5416_11ng_ratetable;
- sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] =
- &ar5416_11na_ratetable;
- sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] =
- &ar5416_11na_ratetable;
- sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] =
- &ar5416_11ng_ratetable;
- sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS] =
- &ar5416_11ng_ratetable;
-}
-
-static void ar5416_setquarter_ratetable(struct ath_rate_softc *sc)
-{
- sc->hw_rate_table[ATH9K_MODE_11A] = &ar5416_11a_ratetable_Quarter;
- return;
-}
-
-static void ar5416_sethalf_ratetable(struct ath_rate_softc *sc)
-{
- sc->hw_rate_table[ATH9K_MODE_11A] = &ar5416_11a_ratetable_Half;
- return;
-}
-
-static void ar5416_setfull_ratetable(struct ath_rate_softc *sc)
-{
- sc->hw_rate_table[ATH9K_MODE_11A] = &ar5416_11a_ratetable;
- return;
-}
-
-/*
- * Return the median of three numbers
- */
static inline int8_t median(int8_t a, int8_t b, int8_t c)
{
if (a >= b) {
@@ -541,68 +425,65 @@ static inline int8_t median(int8_t a, int8_t b, int8_t c)
}
}
-static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table,
- struct ath_tx_ratectrl *rate_ctrl)
+static void ath_rc_sort_validrates(struct ath_rate_table *rate_table,
+ struct ath_rate_priv *ath_rc_priv)
{
u8 i, j, idx, idx_next;
- for (i = rate_ctrl->max_valid_rate - 1; i > 0; i--) {
+ for (i = ath_rc_priv->max_valid_rate - 1; i > 0; i--) {
for (j = 0; j <= i-1; j++) {
- idx = rate_ctrl->valid_rate_index[j];
- idx_next = rate_ctrl->valid_rate_index[j+1];
+ idx = ath_rc_priv->valid_rate_index[j];
+ idx_next = ath_rc_priv->valid_rate_index[j+1];
if (rate_table->info[idx].ratekbps >
rate_table->info[idx_next].ratekbps) {
- rate_ctrl->valid_rate_index[j] = idx_next;
- rate_ctrl->valid_rate_index[j+1] = idx;
+ ath_rc_priv->valid_rate_index[j] = idx_next;
+ ath_rc_priv->valid_rate_index[j+1] = idx;
}
}
}
}
-/* Access functions for valid_txrate_mask */
-
-static void ath_rc_init_valid_txmask(struct ath_tx_ratectrl *rate_ctrl)
+static void ath_rc_init_valid_txmask(struct ath_rate_priv *ath_rc_priv)
{
u8 i;
- for (i = 0; i < rate_ctrl->rate_table_size; i++)
- rate_ctrl->valid_rate_index[i] = FALSE;
+ for (i = 0; i < ath_rc_priv->rate_table_size; i++)
+ ath_rc_priv->valid_rate_index[i] = 0;
}
-static inline void ath_rc_set_valid_txmask(struct ath_tx_ratectrl *rate_ctrl,
+static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv,
u8 index, int valid_tx_rate)
{
- ASSERT(index <= rate_ctrl->rate_table_size);
- rate_ctrl->valid_rate_index[index] = valid_tx_rate ? TRUE : FALSE;
+ ASSERT(index <= ath_rc_priv->rate_table_size);
+ ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? 1 : 0;
}
-static inline int ath_rc_isvalid_txmask(struct ath_tx_ratectrl *rate_ctrl,
+static inline int ath_rc_isvalid_txmask(struct ath_rate_priv *ath_rc_priv,
u8 index)
{
- ASSERT(index <= rate_ctrl->rate_table_size);
- return rate_ctrl->valid_rate_index[index];
+ ASSERT(index <= ath_rc_priv->rate_table_size);
+ return ath_rc_priv->valid_rate_index[index];
}
-/* Iterators for valid_txrate_mask */
-static inline int
-ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table,
- struct ath_tx_ratectrl *rate_ctrl,
- u8 cur_valid_txrate,
- u8 *next_idx)
+static inline int ath_rc_get_nextvalid_txrate(struct ath_rate_table *rate_table,
+ struct ath_rate_priv *ath_rc_priv,
+ u8 cur_valid_txrate,
+ u8 *next_idx)
{
u8 i;
- for (i = 0; i < rate_ctrl->max_valid_rate - 1; i++) {
- if (rate_ctrl->valid_rate_index[i] == cur_valid_txrate) {
- *next_idx = rate_ctrl->valid_rate_index[i+1];
- return TRUE;
+ for (i = 0; i < ath_rc_priv->max_valid_rate - 1; i++) {
+ if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) {
+ *next_idx = ath_rc_priv->valid_rate_index[i+1];
+ return 1;
}
}
/* No more valid rates */
*next_idx = 0;
- return FALSE;
+
+ return 0;
}
/* Return true only for single stream */
@@ -610,83 +491,72 @@ ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table,
static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw)
{
if (WLAN_RC_PHY_HT(phy) & !(capflag & WLAN_RC_HT_FLAG))
- return FALSE;
+ return 0;
if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG))
- return FALSE;
+ return 0;
if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG))
- return FALSE;
+ return 0;
if (!ignore_cw && WLAN_RC_PHY_HT(phy))
if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG))
- return FALSE;
+ return 0;
if (!WLAN_RC_PHY_40(phy) && (capflag & WLAN_RC_40_FLAG))
- return FALSE;
- return TRUE;
+ return 0;
+ return 1;
}
static inline int
-ath_rc_get_nextlowervalid_txrate(const struct ath_rate_table *rate_table,
- struct ath_tx_ratectrl *rate_ctrl,
+ath_rc_get_nextlowervalid_txrate(struct ath_rate_table *rate_table,
+ struct ath_rate_priv *ath_rc_priv,
u8 cur_valid_txrate, u8 *next_idx)
{
int8_t i;
- for (i = 1; i < rate_ctrl->max_valid_rate ; i++) {
- if (rate_ctrl->valid_rate_index[i] == cur_valid_txrate) {
- *next_idx = rate_ctrl->valid_rate_index[i-1];
- return TRUE;
+ for (i = 1; i < ath_rc_priv->max_valid_rate ; i++) {
+ if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) {
+ *next_idx = ath_rc_priv->valid_rate_index[i-1];
+ return 1;
}
}
- return FALSE;
+
+ return 0;
}
-/*
- * Initialize the Valid Rate Index from valid entries in Rate Table
- */
-static u8
-ath_rc_sib_init_validrates(struct ath_rate_node *ath_rc_priv,
- const struct ath_rate_table *rate_table,
- u32 capflag)
+static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv,
+ struct ath_rate_table *rate_table,
+ u32 capflag)
{
- struct ath_tx_ratectrl *rate_ctrl;
u8 i, hi = 0;
u32 valid;
- rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv);
for (i = 0; i < rate_table->rate_cnt; i++) {
valid = (ath_rc_priv->single_stream ?
rate_table->info[i].valid_single_stream :
rate_table->info[i].valid);
- if (valid == TRUE) {
+ if (valid == 1) {
u32 phy = rate_table->info[i].phy;
u8 valid_rate_count = 0;
- if (!ath_rc_valid_phyrate(phy, capflag, FALSE))
+ if (!ath_rc_valid_phyrate(phy, capflag, 0))
continue;
- valid_rate_count = rate_ctrl->valid_phy_ratecnt[phy];
+ valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy];
- rate_ctrl->valid_phy_rateidx[phy][valid_rate_count] = i;
- rate_ctrl->valid_phy_ratecnt[phy] += 1;
- ath_rc_set_valid_txmask(rate_ctrl, i, TRUE);
+ ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i;
+ ath_rc_priv->valid_phy_ratecnt[phy] += 1;
+ ath_rc_set_valid_txmask(ath_rc_priv, i, 1);
hi = A_MAX(hi, i);
}
}
+
return hi;
}
-/*
- * Initialize the Valid Rate Index from Rate Set
- */
-static u8
-ath_rc_sib_setvalid_rates(struct ath_rate_node *ath_rc_priv,
- const struct ath_rate_table *rate_table,
- struct ath_rateset *rateset,
- u32 capflag)
+static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
+ struct ath_rate_table *rate_table,
+ struct ath_rateset *rateset,
+ u32 capflag)
{
- /* XXX: Clean me up and make identation friendly */
u8 i, j, hi = 0;
- struct ath_tx_ratectrl *rate_ctrl =
- (struct ath_tx_ratectrl *)(ath_rc_priv);
/* Use intersection of working rates and valid rates */
for (i = 0; i < rateset->rs_nrates; i++) {
@@ -695,196 +565,89 @@ ath_rc_sib_setvalid_rates(struct ath_rate_node *ath_rc_priv,
u32 valid = (ath_rc_priv->single_stream ?
rate_table->info[j].valid_single_stream :
rate_table->info[j].valid);
+ u8 rate = rateset->rs_rates[i];
+ u8 dot11rate = rate_table->info[j].dot11rate;
/* We allow a rate only if its valid and the
* capflag matches one of the validity
- * (TRUE/TRUE_20/TRUE_40) flags */
-
- /* XXX: catch the negative of this branch
- * first and then continue */
- if (((rateset->rs_rates[i] & 0x7F) ==
- (rate_table->info[j].dot11rate & 0x7F)) &&
- ((valid & WLAN_RC_CAP_MODE(capflag)) ==
- WLAN_RC_CAP_MODE(capflag)) &&
- !WLAN_RC_PHY_HT(phy)) {
+ * (VALID/VALID_20/VALID_40) flags */
+ if (((rate & 0x7F) == (dot11rate & 0x7F)) &&
+ ((valid & WLAN_RC_CAP_MODE(capflag)) ==
+ WLAN_RC_CAP_MODE(capflag)) &&
+ !WLAN_RC_PHY_HT(phy)) {
u8 valid_rate_count = 0;
- if (!ath_rc_valid_phyrate(phy, capflag, FALSE))
+ if (!ath_rc_valid_phyrate(phy, capflag, 0))
continue;
valid_rate_count =
- rate_ctrl->valid_phy_ratecnt[phy];
+ ath_rc_priv->valid_phy_ratecnt[phy];
- rate_ctrl->valid_phy_rateidx[phy]
+ ath_rc_priv->valid_phy_rateidx[phy]
[valid_rate_count] = j;
- rate_ctrl->valid_phy_ratecnt[phy] += 1;
- ath_rc_set_valid_txmask(rate_ctrl, j, TRUE);
+ ath_rc_priv->valid_phy_ratecnt[phy] += 1;
+ ath_rc_set_valid_txmask(ath_rc_priv, j, 1);
hi = A_MAX(hi, j);
}
}
}
+
return hi;
}
-static u8
-ath_rc_sib_setvalid_htrates(struct ath_rate_node *ath_rc_priv,
- const struct ath_rate_table *rate_table,
- u8 *mcs_set, u32 capflag)
+static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
+ struct ath_rate_table *rate_table,
+ u8 *mcs_set, u32 capflag)
{
+ struct ath_rateset *rateset = (struct ath_rateset *)mcs_set;
+
u8 i, j, hi = 0;
- struct ath_tx_ratectrl *rate_ctrl =
- (struct ath_tx_ratectrl *)(ath_rc_priv);
/* Use intersection of working rates and valid rates */
- for (i = 0; i < ((struct ath_rateset *)mcs_set)->rs_nrates; i++) {
+ for (i = 0; i < rateset->rs_nrates; i++) {
for (j = 0; j < rate_table->rate_cnt; j++) {
u32 phy = rate_table->info[j].phy;
u32 valid = (ath_rc_priv->single_stream ?
rate_table->info[j].valid_single_stream :
rate_table->info[j].valid);
+ u8 rate = rateset->rs_rates[i];
+ u8 dot11rate = rate_table->info[j].dot11rate;
- if (((((struct ath_rateset *)
- mcs_set)->rs_rates[i] & 0x7F) !=
- (rate_table->info[j].dot11rate & 0x7F)) ||
+ if (((rate & 0x7F) != (dot11rate & 0x7F)) ||
!WLAN_RC_PHY_HT(phy) ||
!WLAN_RC_PHY_HT_VALID(valid, capflag))
continue;
- if (!ath_rc_valid_phyrate(phy, capflag, FALSE))
+ if (!ath_rc_valid_phyrate(phy, capflag, 0))
continue;
- rate_ctrl->valid_phy_rateidx[phy]
- [rate_ctrl->valid_phy_ratecnt[phy]] = j;
- rate_ctrl->valid_phy_ratecnt[phy] += 1;
- ath_rc_set_valid_txmask(rate_ctrl, j, TRUE);
+ ath_rc_priv->valid_phy_rateidx[phy]
+ [ath_rc_priv->valid_phy_ratecnt[phy]] = j;
+ ath_rc_priv->valid_phy_ratecnt[phy] += 1;
+ ath_rc_set_valid_txmask(ath_rc_priv, j, 1);
hi = A_MAX(hi, j);
}
}
- return hi;
-}
-
-/*
- * Attach to a device instance. Setup the public definition
- * of how much per-node space we need and setup the private
- * phy tables that have rate control parameters.
- */
-struct ath_rate_softc *ath_rate_attach(struct ath_hal *ah)
-{
- struct ath_rate_softc *asc;
-
- /* we are only in user context so we can sleep for memory */
- asc = kzalloc(sizeof(struct ath_rate_softc), GFP_KERNEL);
- if (asc == NULL)
- return NULL;
-
- ar5416_attach_ratetables(asc);
-
- /* Save Maximum TX Trigger Level (used for 11n) */
- tx_triglevel_max = ah->ah_caps.tx_triglevel_max;
- /* return alias for ath_rate_softc * */
- return asc;
-}
-
-static struct ath_rate_node *ath_rate_node_alloc(struct ath_vap *avp,
- struct ath_rate_softc *rsc,
- gfp_t gfp)
-{
- struct ath_rate_node *anode;
-
- anode = kzalloc(sizeof(struct ath_rate_node), gfp);
- if (anode == NULL)
- return NULL;
-
- anode->avp = avp;
- anode->asc = rsc;
- avp->rc_node = anode;
-
- return anode;
-}
-
-static void ath_rate_node_free(struct ath_rate_node *anode)
-{
- if (anode != NULL)
- kfree(anode);
-}
-
-void ath_rate_detach(struct ath_rate_softc *asc)
-{
- if (asc != NULL)
- kfree(asc);
-}
-
-u8 ath_rate_findrateix(struct ath_softc *sc,
- u8 dot11rate)
-{
- const struct ath_rate_table *ratetable;
- struct ath_rate_softc *rsc = sc->sc_rc;
- int i;
-
- ratetable = rsc->hw_rate_table[sc->sc_curmode];
-
- if (WARN_ON(!ratetable))
- return 0;
-
- for (i = 0; i < ratetable->rate_cnt; i++) {
- if ((ratetable->info[i].dot11rate & 0x7f) == (dot11rate & 0x7f))
- return i;
- }
- return 0;
-}
-
-/*
- * Update rate-control state on a device state change. When
- * operating as a station this includes associate/reassociate
- * with an AP. Otherwise this gets called, for example, when
- * the we transition to run state when operating as an AP.
- */
-void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp)
-{
- struct ath_rate_softc *asc = sc->sc_rc;
-
- /* For half and quarter rate channles use different
- * rate tables
- */
- if (sc->sc_ah->ah_curchan->channelFlags & CHANNEL_HALF)
- ar5416_sethalf_ratetable(asc);
- else if (sc->sc_ah->ah_curchan->channelFlags & CHANNEL_QUARTER)
- ar5416_setquarter_ratetable(asc);
- else /* full rate */
- ar5416_setfull_ratetable(asc);
-
- if (avp->av_config.av_fixed_rateset != IEEE80211_FIXED_RATE_NONE) {
- asc->fixedrix =
- sc->sc_rixmap[avp->av_config.av_fixed_rateset & 0xff];
- /* NB: check the fixed rate exists */
- if (asc->fixedrix == 0xff)
- asc->fixedrix = IEEE80211_FIXED_RATE_NONE;
- } else {
- asc->fixedrix = IEEE80211_FIXED_RATE_NONE;
- }
+ return hi;
}
static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
- struct ath_rate_node *ath_rc_priv,
- const struct ath_rate_table *rate_table,
+ struct ath_rate_priv *ath_rc_priv,
+ struct ath_rate_table *rate_table,
int probe_allowed, int *is_probing,
int is_retry)
{
u32 dt, best_thruput, this_thruput, now_msec;
u8 rate, next_rate, best_rate, maxindex, minindex;
int8_t rssi_last, rssi_reduce = 0, index = 0;
- struct ath_tx_ratectrl *rate_ctrl = NULL;
-
- rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv ?
- (ath_rc_priv) : NULL);
- *is_probing = FALSE;
+ *is_probing = 0;
- rssi_last = median(rate_ctrl->rssi_last,
- rate_ctrl->rssi_last_prev,
- rate_ctrl->rssi_last_prev2);
+ rssi_last = median(ath_rc_priv->rssi_last,
+ ath_rc_priv->rssi_last_prev,
+ ath_rc_priv->rssi_last_prev2);
/*
* Age (reduce) last ack rssi based on how old it is.
@@ -896,7 +659,7 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
*/
now_msec = jiffies_to_msecs(jiffies);
- dt = now_msec - rate_ctrl->rssi_time;
+ dt = now_msec - ath_rc_priv->rssi_time;
if (dt >= 185)
rssi_reduce = 10;
@@ -915,7 +678,7 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
*/
best_thruput = 0;
- maxindex = rate_ctrl->max_valid_rate-1;
+ maxindex = ath_rc_priv->max_valid_rate-1;
minindex = 0;
best_rate = minindex;
@@ -927,8 +690,8 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
for (index = maxindex; index >= minindex ; index--) {
u8 per_thres;
- rate = rate_ctrl->valid_rate_index[index];
- if (rate > rate_ctrl->rate_max_phy)
+ rate = ath_rc_priv->valid_rate_index[index];
+ if (rate > ath_rc_priv->rate_max_phy)
continue;
/*
@@ -942,7 +705,7 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
* 10-15 and we would be worse off then staying
* at the current rate.
*/
- per_thres = rate_ctrl->state[rate].per;
+ per_thres = ath_rc_priv->state[rate].per;
if (per_thres < 12)
per_thres = 12;
@@ -961,41 +724,35 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
* of max retries, use the min rate for the next retry
*/
if (is_retry)
- rate = rate_ctrl->valid_rate_index[minindex];
+ rate = ath_rc_priv->valid_rate_index[minindex];
- rate_ctrl->rssi_last_lookup = rssi_last;
+ ath_rc_priv->rssi_last_lookup = rssi_last;
/*
* Must check the actual rate (ratekbps) to account for
* non-monoticity of 11g's rate table
*/
- if (rate >= rate_ctrl->rate_max_phy && probe_allowed) {
- rate = rate_ctrl->rate_max_phy;
+ if (rate >= ath_rc_priv->rate_max_phy && probe_allowed) {
+ rate = ath_rc_priv->rate_max_phy;
/* Probe the next allowed phy state */
/* FIXME:XXXX Check to make sure ratMax is checked properly */
if (ath_rc_get_nextvalid_txrate(rate_table,
- rate_ctrl, rate, &next_rate) &&
- (now_msec - rate_ctrl->probe_time >
+ ath_rc_priv, rate, &next_rate) &&
+ (now_msec - ath_rc_priv->probe_time >
rate_table->probe_interval) &&
- (rate_ctrl->hw_maxretry_pktcnt >= 1)) {
+ (ath_rc_priv->hw_maxretry_pktcnt >= 1)) {
rate = next_rate;
- rate_ctrl->probe_rate = rate;
- rate_ctrl->probe_time = now_msec;
- rate_ctrl->hw_maxretry_pktcnt = 0;
- *is_probing = TRUE;
+ ath_rc_priv->probe_rate = rate;
+ ath_rc_priv->probe_time = now_msec;
+ ath_rc_priv->hw_maxretry_pktcnt = 0;
+ *is_probing = 1;
}
}
- /*
- * Make sure rate is not higher than the allowed maximum.
- * We should also enforce the min, but I suspect the min is
- * normally 1 rather than 0 because of the rate 9 vs 6 issue
- * in the old code.
- */
- if (rate > (rate_ctrl->rate_table_size - 1))
- rate = rate_ctrl->rate_table_size - 1;
+ if (rate > (ath_rc_priv->rate_table_size - 1))
+ rate = ath_rc_priv->rate_table_size - 1;
ASSERT((rate_table->info[rate].valid && !ath_rc_priv->single_stream) ||
(rate_table->info[rate].valid_single_stream &&
@@ -1004,40 +761,36 @@ static u8 ath_rc_ratefind_ht(struct ath_softc *sc,
return rate;
}
-static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table ,
- struct ath_rc_series *series,
- u8 tries,
- u8 rix,
- int rtsctsenable)
+static void ath_rc_rate_set_series(struct ath_rate_table *rate_table ,
+ struct ieee80211_tx_rate *rate,
+ u8 tries, u8 rix, int rtsctsenable)
{
- series->tries = tries;
- series->flags = (rtsctsenable ? ATH_RC_RTSCTS_FLAG : 0) |
- (WLAN_RC_PHY_DS(rate_table->info[rix].phy) ?
- ATH_RC_DS_FLAG : 0) |
- (WLAN_RC_PHY_40(rate_table->info[rix].phy) ?
- ATH_RC_CW40_FLAG : 0) |
- (WLAN_RC_PHY_SGI(rate_table->info[rix].phy) ?
- ATH_RC_SGI_FLAG : 0);
-
- series->rix = rate_table->info[rix].base_index;
- series->max_4ms_framelen = rate_table->info[rix].max_4ms_framelen;
+ rate->count = tries;
+ rate->idx = rix;
+
+ if (rtsctsenable)
+ rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
+ if (WLAN_RC_PHY_40(rate_table->info[rix].phy))
+ rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
+ if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy))
+ rate->flags |= IEEE80211_TX_RC_SHORT_GI;
+ if (WLAN_RC_PHY_HT(rate_table->info[rix].phy))
+ rate->flags |= IEEE80211_TX_RC_MCS;
}
static u8 ath_rc_rate_getidx(struct ath_softc *sc,
- struct ath_rate_node *ath_rc_priv,
- const struct ath_rate_table *rate_table,
+ struct ath_rate_priv *ath_rc_priv,
+ struct ath_rate_table *rate_table,
u8 rix, u16 stepdown,
u16 min_rate)
{
u32 j;
u8 nextindex;
- struct ath_tx_ratectrl *rate_ctrl =
- (struct ath_tx_ratectrl *)(ath_rc_priv);
if (min_rate) {
for (j = RATE_TABLE_SIZE; j > 0; j--) {
if (ath_rc_get_nextlowervalid_txrate(rate_table,
- rate_ctrl, rix, &nextindex))
+ ath_rc_priv, rix, &nextindex))
rix = nextindex;
else
break;
@@ -1045,7 +798,7 @@ static u8 ath_rc_rate_getidx(struct ath_softc *sc,
} else {
for (j = stepdown; j > 0; j--) {
if (ath_rc_get_nextlowervalid_txrate(rate_table,
- rate_ctrl, rix, &nextindex))
+ ath_rc_priv, rix, &nextindex))
rix = nextindex;
else
break;
@@ -1055,41 +808,39 @@ static u8 ath_rc_rate_getidx(struct ath_softc *sc,
}
static void ath_rc_ratefind(struct ath_softc *sc,
- struct ath_rate_node *ath_rc_priv,
- int num_tries, int num_rates, unsigned int rcflag,
- struct ath_rc_series series[], int *is_probe,
+ struct ath_rate_priv *ath_rc_priv,
+ int num_tries, int num_rates,
+ struct ieee80211_tx_info *tx_info, int *is_probe,
int is_retry)
{
u8 try_per_rate = 0, i = 0, rix, nrix;
- struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc;
struct ath_rate_table *rate_table;
+ struct ieee80211_tx_rate *rates = tx_info->control.rates;
- rate_table =
- (struct ath_rate_table *)asc->hw_rate_table[sc->sc_curmode];
- rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table,
- (rcflag & ATH_RC_PROBE_ALLOWED) ? 1 : 0,
+ rate_table = sc->cur_rate_table;
+ rix = ath_rc_ratefind_ht(sc, ath_rc_priv, rate_table, 1,
is_probe, is_retry);
nrix = rix;
- if ((rcflag & ATH_RC_PROBE_ALLOWED) && (*is_probe)) {
+ if (*is_probe) {
/* set one try for probe rates. For the
* probes don't enable rts */
ath_rc_rate_set_series(rate_table,
- &series[i++], 1, nrix, FALSE);
+ &rates[i++], 1, nrix, 0);
try_per_rate = (num_tries/num_rates);
/* Get the next tried/allowed rate. No RTS for the next series
* after the probe rate
*/
nrix = ath_rc_rate_getidx(sc,
- ath_rc_priv, rate_table, nrix, 1, FALSE);
+ ath_rc_priv, rate_table, nrix, 1, 0);
ath_rc_rate_set_series(rate_table,
- &series[i++], try_per_rate, nrix, 0);
+ &rates[i++], try_per_rate, nrix, 0);
} else {
try_per_rate = (num_tries/num_rates);
/* Set the choosen rate. No RTS for first series entry. */
ath_rc_rate_set_series(rate_table,
- &series[i++], try_per_rate, nrix, FALSE);
+ &rates[i++], try_per_rate, nrix, 0);
}
/* Fill in the other rates for multirate retry */
@@ -1099,14 +850,13 @@ static void ath_rc_ratefind(struct ath_softc *sc,
try_num = ((i + 1) == num_rates) ?
num_tries - (try_per_rate * i) : try_per_rate ;
- min_rate = (((i + 1) == num_rates) &&
- (rcflag & ATH_RC_MINRATE_LASTRATE)) ? 1 : 0;
+ min_rate = (((i + 1) == num_rates) && 0);
nrix = ath_rc_rate_getidx(sc, ath_rc_priv,
rate_table, nrix, 1, min_rate);
/* All other rates in the series have RTS enabled */
ath_rc_rate_set_series(rate_table,
- &series[i], try_num, nrix, TRUE);
+ &rates[i], try_num, nrix, 1);
}
/*
@@ -1124,115 +874,29 @@ static void ath_rc_ratefind(struct ath_softc *sc,
* So, set fourth rate in series to be same as third one for
* above conditions.
*/
- if ((sc->sc_curmode == ATH9K_MODE_11NG_HT20) ||
- (sc->sc_curmode == ATH9K_MODE_11NG_HT40PLUS) ||
- (sc->sc_curmode == ATH9K_MODE_11NG_HT40MINUS)) {
- u8 dot11rate = rate_table->info[rix].dot11rate;
+ if ((sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ) &&
+ (sc->hw->conf.ht.enabled)) {
+ u8 dot11rate = rate_table->info[rix].dot11rate;
u8 phy = rate_table->info[rix].phy;
if (i == 4 &&
((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) ||
(dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) {
- series[3].rix = series[2].rix;
- series[3].flags = series[2].flags;
- series[3].max_4ms_framelen = series[2].max_4ms_framelen;
- }
- }
-}
-
-/*
- * Return the Tx rate series.
- */
-static void ath_rate_findrate(struct ath_softc *sc,
- struct ath_rate_node *ath_rc_priv,
- int num_tries,
- int num_rates,
- unsigned int rcflag,
- struct ath_rc_series series[],
- int *is_probe,
- int is_retry)
-{
- struct ath_vap *avp = ath_rc_priv->avp;
-
- DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
-
- if (!num_rates || !num_tries)
- return;
-
- if (avp->av_config.av_fixed_rateset == IEEE80211_FIXED_RATE_NONE) {
- ath_rc_ratefind(sc, ath_rc_priv, num_tries, num_rates,
- rcflag, series, is_probe, is_retry);
- } else {
- /* Fixed rate */
- int idx;
- u8 flags;
- u32 rix;
- struct ath_rate_softc *asc = ath_rc_priv->asc;
- struct ath_rate_table *rate_table;
-
- rate_table = (struct ath_rate_table *)
- asc->hw_rate_table[sc->sc_curmode];
-
- for (idx = 0; idx < 4; idx++) {
- unsigned int mcs;
- u8 series_rix = 0;
-
- series[idx].tries = IEEE80211_RATE_IDX_ENTRY(
- avp->av_config.av_fixed_retryset, idx);
-
- mcs = IEEE80211_RATE_IDX_ENTRY(
- avp->av_config.av_fixed_rateset, idx);
-
- if (idx == 3 && (mcs & 0xf0) == 0x70)
- mcs = (mcs & ~0xf0)|0x80;
-
- if (!(mcs & 0x80))
- flags = 0;
- else
- flags = ((ath_rc_priv->ht_cap &
- WLAN_RC_DS_FLAG) ?
- ATH_RC_DS_FLAG : 0) |
- ((ath_rc_priv->ht_cap &
- WLAN_RC_40_FLAG) ?
- ATH_RC_CW40_FLAG : 0) |
- ((ath_rc_priv->ht_cap &
- WLAN_RC_SGI_FLAG) ?
- ((ath_rc_priv->ht_cap &
- WLAN_RC_40_FLAG) ?
- ATH_RC_SGI_FLAG : 0) : 0);
-
- series[idx].rix = sc->sc_rixmap[mcs];
- series_rix = series[idx].rix;
-
- /* XXX: Give me some cleanup love */
- if ((flags & ATH_RC_CW40_FLAG) &&
- (flags & ATH_RC_SGI_FLAG))
- rix = rate_table->info[series_rix].ht_index;
- else if (flags & ATH_RC_SGI_FLAG)
- rix = rate_table->info[series_rix].sgi_index;
- else if (flags & ATH_RC_CW40_FLAG)
- rix = rate_table->info[series_rix].cw40index;
- else
- rix = rate_table->info[series_rix].base_index;
- series[idx].max_4ms_framelen =
- rate_table->info[rix].max_4ms_framelen;
- series[idx].flags = flags;
+ rates[3].idx = rates[2].idx;
+ rates[3].flags = rates[2].flags;
}
}
}
-static void ath_rc_update_ht(struct ath_softc *sc,
- struct ath_rate_node *ath_rc_priv,
- struct ath_tx_info_priv *info_priv,
- int tx_rate, int xretries, int retries)
+static bool ath_rc_update_per(struct ath_softc *sc,
+ struct ath_rate_table *rate_table,
+ struct ath_rate_priv *ath_rc_priv,
+ struct ath_tx_info_priv *tx_info_priv,
+ int tx_rate, int xretries, int retries,
+ u32 now_msec)
{
- struct ath_tx_ratectrl *rate_ctrl;
- u32 now_msec = jiffies_to_msecs(jiffies);
- int state_change = FALSE, rate, count;
+ bool state_change = false;
+ int count;
u8 last_per;
- struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc;
- struct ath_rate_table *rate_table =
- (struct ath_rate_table *)asc->hw_rate_table[sc->sc_curmode];
-
static u32 nretry_to_per_lookup[10] = {
100 * 0 / 1,
100 * 1 / 4,
@@ -1246,56 +910,35 @@ static void ath_rc_update_ht(struct ath_softc *sc,
100 * 9 / 10
};
- if (!ath_rc_priv)
- return;
-
- rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv);
-
- ASSERT(tx_rate >= 0);
- if (tx_rate < 0)
- return;
-
- /* To compensate for some imbalance between ctrl and ext. channel */
-
- if (WLAN_RC_PHY_40(rate_table->info[tx_rate].phy))
- info_priv->tx.ts_rssi =
- info_priv->tx.ts_rssi < 3 ? 0 :
- info_priv->tx.ts_rssi - 3;
-
- last_per = rate_ctrl->state[tx_rate].per;
+ last_per = ath_rc_priv->state[tx_rate].per;
if (xretries) {
- /* Update the PER. */
if (xretries == 1) {
- rate_ctrl->state[tx_rate].per += 30;
- if (rate_ctrl->state[tx_rate].per > 100)
- rate_ctrl->state[tx_rate].per = 100;
+ ath_rc_priv->state[tx_rate].per += 30;
+ if (ath_rc_priv->state[tx_rate].per > 100)
+ ath_rc_priv->state[tx_rate].per = 100;
} else {
/* xretries == 2 */
- count = sizeof(nretry_to_per_lookup) /
- sizeof(nretry_to_per_lookup[0]);
+ count = ARRAY_SIZE(nretry_to_per_lookup);
if (retries >= count)
retries = count - 1;
+
/* new_PER = 7/8*old_PER + 1/8*(currentPER) */
- rate_ctrl->state[tx_rate].per =
- (u8)(rate_ctrl->state[tx_rate].per -
- (rate_ctrl->state[tx_rate].per >> 3) +
- ((100) >> 3));
+ ath_rc_priv->state[tx_rate].per =
+ (u8)(last_per - (last_per >> 3) + (100 >> 3));
}
/* xretries == 1 or 2 */
- if (rate_ctrl->probe_rate == tx_rate)
- rate_ctrl->probe_rate = 0;
+ if (ath_rc_priv->probe_rate == tx_rate)
+ ath_rc_priv->probe_rate = 0;
- } else { /* xretries == 0 */
- /* Update the PER. */
- /* Make sure it doesn't index out of array's bounds. */
- count = sizeof(nretry_to_per_lookup) /
- sizeof(nretry_to_per_lookup[0]);
+ } else { /* xretries == 0 */
+ count = ARRAY_SIZE(nretry_to_per_lookup);
if (retries >= count)
retries = count - 1;
- if (info_priv->n_bad_frames) {
+
+ if (tx_info_priv->n_bad_frames) {
/* new_PER = 7/8*old_PER + 1/8*(currentPER)
* Assuming that n_frames is not 0. The current PER
* from the retries is 100 * retries / (retries+1),
@@ -1308,37 +951,35 @@ static void ath_rc_update_ht(struct ath_softc *sc,
* the above PER. The expression below is a
* simplified version of the sum of these two terms.
*/
- if (info_priv->n_frames > 0)
- rate_ctrl->state[tx_rate].per
- = (u8)
- (rate_ctrl->state[tx_rate].per -
- (rate_ctrl->state[tx_rate].per >> 3) +
- ((100*(retries*info_priv->n_frames +
- info_priv->n_bad_frames) /
- (info_priv->n_frames *
- (retries+1))) >> 3));
+ if (tx_info_priv->n_frames > 0) {
+ int n_frames, n_bad_frames;
+ u8 cur_per, new_per;
+
+ n_bad_frames = retries * tx_info_priv->n_frames +
+ tx_info_priv->n_bad_frames;
+ n_frames = tx_info_priv->n_frames * (retries + 1);
+ cur_per = (100 * n_bad_frames / n_frames) >> 3;
+ new_per = (u8)(last_per - (last_per >> 3) + cur_per);
+ ath_rc_priv->state[tx_rate].per = new_per;
+ }
} else {
- /* new_PER = 7/8*old_PER + 1/8*(currentPER) */
-
- rate_ctrl->state[tx_rate].per = (u8)
- (rate_ctrl->state[tx_rate].per -
- (rate_ctrl->state[tx_rate].per >> 3) +
- (nretry_to_per_lookup[retries] >> 3));
+ ath_rc_priv->state[tx_rate].per =
+ (u8)(last_per - (last_per >> 3) +
+ (nretry_to_per_lookup[retries] >> 3));
}
- rate_ctrl->rssi_last_prev2 = rate_ctrl->rssi_last_prev;
- rate_ctrl->rssi_last_prev = rate_ctrl->rssi_last;
- rate_ctrl->rssi_last = info_priv->tx.ts_rssi;
- rate_ctrl->rssi_time = now_msec;
+ ath_rc_priv->rssi_last_prev2 = ath_rc_priv->rssi_last_prev;
+ ath_rc_priv->rssi_last_prev = ath_rc_priv->rssi_last;
+ ath_rc_priv->rssi_last = tx_info_priv->tx.ts_rssi;
+ ath_rc_priv->rssi_time = now_msec;
/*
* If we got at most one retry then increase the max rate if
* this was a probe. Otherwise, ignore the probe.
*/
-
- if (rate_ctrl->probe_rate && rate_ctrl->probe_rate == tx_rate) {
- if (retries > 0 || 2 * info_priv->n_bad_frames >
- info_priv->n_frames) {
+ if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) {
+ if (retries > 0 || 2 * tx_info_priv->n_bad_frames >
+ tx_info_priv->n_frames) {
/*
* Since we probed with just a single attempt,
* any retries means the probe failed. Also,
@@ -1346,17 +987,18 @@ static void ath_rc_update_ht(struct ath_softc *sc,
* the subframes were bad then also consider
* the probe a failure.
*/
- rate_ctrl->probe_rate = 0;
+ ath_rc_priv->probe_rate = 0;
} else {
u8 probe_rate = 0;
- rate_ctrl->rate_max_phy = rate_ctrl->probe_rate;
- probe_rate = rate_ctrl->probe_rate;
+ ath_rc_priv->rate_max_phy =
+ ath_rc_priv->probe_rate;
+ probe_rate = ath_rc_priv->probe_rate;
- if (rate_ctrl->state[probe_rate].per > 30)
- rate_ctrl->state[probe_rate].per = 20;
+ if (ath_rc_priv->state[probe_rate].per > 30)
+ ath_rc_priv->state[probe_rate].per = 20;
- rate_ctrl->probe_rate = 0;
+ ath_rc_priv->probe_rate = 0;
/*
* Since this probe succeeded, we allow the next
@@ -1364,8 +1006,8 @@ static void ath_rc_update_ht(struct ath_softc *sc,
* to move up faster if the probes are
* succesful.
*/
- rate_ctrl->probe_time = now_msec -
- rate_table->probe_interval / 2;
+ ath_rc_priv->probe_time =
+ now_msec - rate_table->probe_interval / 2;
}
}
@@ -1375,74 +1017,114 @@ static void ath_rc_update_ht(struct ath_softc *sc,
* this was because of collisions or poor signal.
*
* Later: if rssi_ack is close to
- * rate_ctrl->state[txRate].rssi_thres and we see lots
+ * ath_rc_priv->state[txRate].rssi_thres and we see lots
* of retries, then we could increase
- * rate_ctrl->state[txRate].rssi_thres.
+ * ath_rc_priv->state[txRate].rssi_thres.
*/
- rate_ctrl->hw_maxretry_pktcnt = 0;
+ ath_rc_priv->hw_maxretry_pktcnt = 0;
} else {
+ int32_t rssi_ackAvg;
+ int8_t rssi_thres;
+ int8_t rssi_ack_vmin;
+
/*
* It worked with no retries. First ignore bogus (small)
* rssi_ack values.
*/
- if (tx_rate == rate_ctrl->rate_max_phy &&
- rate_ctrl->hw_maxretry_pktcnt < 255) {
- rate_ctrl->hw_maxretry_pktcnt++;
+ if (tx_rate == ath_rc_priv->rate_max_phy &&
+ ath_rc_priv->hw_maxretry_pktcnt < 255) {
+ ath_rc_priv->hw_maxretry_pktcnt++;
}
- if (info_priv->tx.ts_rssi >=
- rate_table->info[tx_rate].rssi_ack_validmin) {
- /* Average the rssi */
- if (tx_rate != rate_ctrl->rssi_sum_rate) {
- rate_ctrl->rssi_sum_rate = tx_rate;
- rate_ctrl->rssi_sum =
- rate_ctrl->rssi_sum_cnt = 0;
- }
+ if (tx_info_priv->tx.ts_rssi <
+ rate_table->info[tx_rate].rssi_ack_validmin)
+ goto exit;
- rate_ctrl->rssi_sum += info_priv->tx.ts_rssi;
- rate_ctrl->rssi_sum_cnt++;
-
- if (rate_ctrl->rssi_sum_cnt > 4) {
- int32_t rssi_ackAvg =
- (rate_ctrl->rssi_sum + 2) / 4;
- int8_t rssi_thres =
- rate_ctrl->state[tx_rate].
- rssi_thres;
- int8_t rssi_ack_vmin =
- rate_table->info[tx_rate].
- rssi_ack_validmin;
-
- rate_ctrl->rssi_sum =
- rate_ctrl->rssi_sum_cnt = 0;
-
- /* Now reduce the current
- * rssi threshold. */
- if ((rssi_ackAvg < rssi_thres + 2) &&
- (rssi_thres > rssi_ack_vmin)) {
- rate_ctrl->state[tx_rate].
- rssi_thres--;
- }
-
- state_change = TRUE;
- }
+ /* Average the rssi */
+ if (tx_rate != ath_rc_priv->rssi_sum_rate) {
+ ath_rc_priv->rssi_sum_rate = tx_rate;
+ ath_rc_priv->rssi_sum =
+ ath_rc_priv->rssi_sum_cnt = 0;
}
+
+ ath_rc_priv->rssi_sum += tx_info_priv->tx.ts_rssi;
+ ath_rc_priv->rssi_sum_cnt++;
+
+ if (ath_rc_priv->rssi_sum_cnt < 4)
+ goto exit;
+
+ rssi_ackAvg =
+ (ath_rc_priv->rssi_sum + 2) / 4;
+ rssi_thres =
+ ath_rc_priv->state[tx_rate].rssi_thres;
+ rssi_ack_vmin =
+ rate_table->info[tx_rate].rssi_ack_validmin;
+
+ ath_rc_priv->rssi_sum =
+ ath_rc_priv->rssi_sum_cnt = 0;
+
+ /* Now reduce the current rssi threshold */
+ if ((rssi_ackAvg < rssi_thres + 2) &&
+ (rssi_thres > rssi_ack_vmin)) {
+ ath_rc_priv->state[tx_rate].rssi_thres--;
+ }
+
+ state_change = true;
}
}
+exit:
+ return state_change;
+}
+
+/* Update PER, RSSI and whatever else that the code thinks it is doing.
+ If you can make sense of all this, you really need to go out more. */
+
+static void ath_rc_update_ht(struct ath_softc *sc,
+ struct ath_rate_priv *ath_rc_priv,
+ struct ath_tx_info_priv *tx_info_priv,
+ int tx_rate, int xretries, int retries)
+{
+#define CHK_RSSI(rate) \
+ ((ath_rc_priv->state[(rate)].rssi_thres + \
+ rate_table->info[(rate)].rssi_ack_deltamin) > \
+ ath_rc_priv->state[(rate)+1].rssi_thres)
- /* For all cases */
+ u32 now_msec = jiffies_to_msecs(jiffies);
+ int rate;
+ u8 last_per;
+ bool state_change = false;
+ struct ath_rate_table *rate_table = sc->cur_rate_table;
+ int size = ath_rc_priv->rate_table_size;
+
+ if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt))
+ return;
+
+ /* To compensate for some imbalance between ctrl and ext. channel */
+
+ if (WLAN_RC_PHY_40(rate_table->info[tx_rate].phy))
+ tx_info_priv->tx.ts_rssi =
+ tx_info_priv->tx.ts_rssi < 3 ? 0 :
+ tx_info_priv->tx.ts_rssi - 3;
+
+ last_per = ath_rc_priv->state[tx_rate].per;
+
+ /* Update PER first */
+ state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv,
+ tx_info_priv, tx_rate, xretries,
+ retries, now_msec);
/*
* If this rate looks bad (high PER) then stop using it for
* a while (except if we are probing).
*/
- if (rate_ctrl->state[tx_rate].per >= 55 && tx_rate > 0 &&
+ if (ath_rc_priv->state[tx_rate].per >= 55 && tx_rate > 0 &&
rate_table->info[tx_rate].ratekbps <=
- rate_table->info[rate_ctrl->rate_max_phy].ratekbps) {
- ath_rc_get_nextlowervalid_txrate(rate_table, rate_ctrl,
- (u8) tx_rate, &rate_ctrl->rate_max_phy);
+ rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) {
+ ath_rc_get_nextlowervalid_txrate(rate_table, ath_rc_priv,
+ (u8)tx_rate, &ath_rc_priv->rate_max_phy);
/* Don't probe for a little while. */
- rate_ctrl->probe_time = now_msec;
+ ath_rc_priv->probe_time = now_msec;
}
if (state_change) {
@@ -1453,20 +1135,15 @@ static void ath_rc_update_ht(struct ath_softc *sc,
* made to keep the rssi thresholds monotonically
* increasing between the CCK and OFDM rates.)
*/
- for (rate = tx_rate; rate <
- rate_ctrl->rate_table_size - 1; rate++) {
+ for (rate = tx_rate; rate < size - 1; rate++) {
if (rate_table->info[rate+1].phy !=
- rate_table->info[tx_rate].phy)
+ rate_table->info[tx_rate].phy)
break;
- if (rate_ctrl->state[rate].rssi_thres +
- rate_table->info[rate].rssi_ack_deltamin >
- rate_ctrl->state[rate+1].rssi_thres) {
- rate_ctrl->state[rate+1].rssi_thres =
- rate_ctrl->state[rate].
- rssi_thres +
- rate_table->info[rate].
- rssi_ack_deltamin;
+ if (CHK_RSSI(rate)) {
+ ath_rc_priv->state[rate+1].rssi_thres =
+ ath_rc_priv->state[rate].rssi_thres +
+ rate_table->info[rate].rssi_ack_deltamin;
}
}
@@ -1476,27 +1153,20 @@ static void ath_rc_update_ht(struct ath_softc *sc,
rate_table->info[tx_rate].phy)
break;
- if (rate_ctrl->state[rate].rssi_thres +
- rate_table->info[rate].rssi_ack_deltamin >
- rate_ctrl->state[rate+1].rssi_thres) {
- if (rate_ctrl->state[rate+1].rssi_thres <
- rate_table->info[rate].
- rssi_ack_deltamin)
- rate_ctrl->state[rate].rssi_thres = 0;
+ if (CHK_RSSI(rate)) {
+ if (ath_rc_priv->state[rate+1].rssi_thres <
+ rate_table->info[rate].rssi_ack_deltamin)
+ ath_rc_priv->state[rate].rssi_thres = 0;
else {
- rate_ctrl->state[rate].rssi_thres =
- rate_ctrl->state[rate+1].
- rssi_thres -
- rate_table->info[rate].
- rssi_ack_deltamin;
+ ath_rc_priv->state[rate].rssi_thres =
+ ath_rc_priv->state[rate+1].rssi_thres -
+ rate_table->info[rate].rssi_ack_deltamin;
}
- if (rate_ctrl->state[rate].rssi_thres <
- rate_table->info[rate].
- rssi_ack_validmin) {
- rate_ctrl->state[rate].rssi_thres =
- rate_table->info[rate].
- rssi_ack_validmin;
+ if (ath_rc_priv->state[rate].rssi_thres <
+ rate_table->info[rate].rssi_ack_validmin) {
+ ath_rc_priv->state[rate].rssi_thres =
+ rate_table->info[rate].rssi_ack_validmin;
}
}
}
@@ -1504,74 +1174,86 @@ static void ath_rc_update_ht(struct ath_softc *sc,
/* Make sure the rates below this have lower PER */
/* Monotonicity is kept only for rates below the current rate. */
- if (rate_ctrl->state[tx_rate].per < last_per) {
+ if (ath_rc_priv->state[tx_rate].per < last_per) {
for (rate = tx_rate - 1; rate >= 0; rate--) {
if (rate_table->info[rate].phy !=
rate_table->info[tx_rate].phy)
break;
- if (rate_ctrl->state[rate].per >
- rate_ctrl->state[rate+1].per) {
- rate_ctrl->state[rate].per =
- rate_ctrl->state[rate+1].per;
+ if (ath_rc_priv->state[rate].per >
+ ath_rc_priv->state[rate+1].per) {
+ ath_rc_priv->state[rate].per =
+ ath_rc_priv->state[rate+1].per;
}
}
}
/* Maintain monotonicity for rates above the current rate */
- for (rate = tx_rate; rate < rate_ctrl->rate_table_size - 1; rate++) {
- if (rate_ctrl->state[rate+1].per < rate_ctrl->state[rate].per)
- rate_ctrl->state[rate+1].per =
- rate_ctrl->state[rate].per;
+ for (rate = tx_rate; rate < size - 1; rate++) {
+ if (ath_rc_priv->state[rate+1].per <
+ ath_rc_priv->state[rate].per)
+ ath_rc_priv->state[rate+1].per =
+ ath_rc_priv->state[rate].per;
}
/* Every so often, we reduce the thresholds and
* PER (different for CCK and OFDM). */
- if (now_msec - rate_ctrl->rssi_down_time >=
+ if (now_msec - ath_rc_priv->rssi_down_time >=
rate_table->rssi_reduce_interval) {
- for (rate = 0; rate < rate_ctrl->rate_table_size; rate++) {
- if (rate_ctrl->state[rate].rssi_thres >
+ for (rate = 0; rate < size; rate++) {
+ if (ath_rc_priv->state[rate].rssi_thres >
rate_table->info[rate].rssi_ack_validmin)
- rate_ctrl->state[rate].rssi_thres -= 1;
+ ath_rc_priv->state[rate].rssi_thres -= 1;
}
- rate_ctrl->rssi_down_time = now_msec;
+ ath_rc_priv->rssi_down_time = now_msec;
}
/* Every so often, we reduce the thresholds
* and PER (different for CCK and OFDM). */
- if (now_msec - rate_ctrl->per_down_time >=
+ if (now_msec - ath_rc_priv->per_down_time >=
rate_table->rssi_reduce_interval) {
- for (rate = 0; rate < rate_ctrl->rate_table_size; rate++) {
- rate_ctrl->state[rate].per =
- 7 * rate_ctrl->state[rate].per / 8;
+ for (rate = 0; rate < size; rate++) {
+ ath_rc_priv->state[rate].per =
+ 7 * ath_rc_priv->state[rate].per / 8;
}
- rate_ctrl->per_down_time = now_msec;
+ ath_rc_priv->per_down_time = now_msec;
}
+
+#undef CHK_RSSI
}
-/*
- * This routine is called in rate control callback tx_status() to give
- * the status of previous frames.
- */
-static void ath_rc_update(struct ath_softc *sc,
- struct ath_rate_node *ath_rc_priv,
- struct ath_tx_info_priv *info_priv, int final_ts_idx,
- int xretries, int long_retry)
+static int ath_rc_get_rateindex(struct ath_rate_table *rate_table,
+ struct ieee80211_tx_rate *rate)
{
- struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc;
+ int rix;
+
+ if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
+ (rate->flags & IEEE80211_TX_RC_SHORT_GI))
+ rix = rate_table->info[rate->idx].ht_index;
+ else if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
+ rix = rate_table->info[rate->idx].sgi_index;
+ else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ rix = rate_table->info[rate->idx].cw40index;
+ else
+ rix = rate_table->info[rate->idx].base_index;
+
+ return rix;
+}
+
+static void ath_rc_tx_status(struct ath_softc *sc,
+ struct ath_rate_priv *ath_rc_priv,
+ struct ieee80211_tx_info *tx_info,
+ int final_ts_idx, int xretries, int long_retry)
+{
+ struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
struct ath_rate_table *rate_table;
- struct ath_tx_ratectrl *rate_ctrl;
- struct ath_rc_series rcs[4];
+ struct ieee80211_tx_rate *rates = tx_info->status.rates;
u8 flags;
- u32 series = 0, rix;
+ u32 i = 0, rix;
- memcpy(rcs, info_priv->rcs, 4 * sizeof(rcs[0]));
- rate_table = (struct ath_rate_table *)
- asc->hw_rate_table[sc->sc_curmode];
- rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv);
- ASSERT(rcs[0].tries != 0);
+ rate_table = sc->cur_rate_table;
/*
* If the first rate is not the final index, there
@@ -1579,32 +1261,22 @@ static void ath_rc_update(struct ath_softc *sc,
*/
if (final_ts_idx != 0) {
/* Process intermediate rates that failed.*/
- for (series = 0; series < final_ts_idx ; series++) {
- if (rcs[series].tries != 0) {
- flags = rcs[series].flags;
+ for (i = 0; i < final_ts_idx ; i++) {
+ if (rates[i].count != 0 && (rates[i].idx >= 0)) {
+ flags = rates[i].flags;
+
/* If HT40 and we have switched mode from
* 40 to 20 => don't update */
- if ((flags & ATH_RC_CW40_FLAG) &&
- (rate_ctrl->rc_phy_mode !=
- (flags & ATH_RC_CW40_FLAG)))
+
+ if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
+ (ath_rc_priv->rc_phy_mode != WLAN_RC_40_FLAG))
return;
- if ((flags & ATH_RC_CW40_FLAG) &&
- (flags & ATH_RC_SGI_FLAG))
- rix = rate_table->info[
- rcs[series].rix].ht_index;
- else if (flags & ATH_RC_SGI_FLAG)
- rix = rate_table->info[
- rcs[series].rix].sgi_index;
- else if (flags & ATH_RC_CW40_FLAG)
- rix = rate_table->info[
- rcs[series].rix].cw40index;
- else
- rix = rate_table->info[
- rcs[series].rix].base_index;
+
+ rix = ath_rc_get_rateindex(rate_table, &rates[i]);
ath_rc_update_ht(sc, ath_rc_priv,
- info_priv, rix,
+ tx_info_priv, rix,
xretries ? 1 : 2,
- rcs[series].tries);
+ rates[i].count);
}
}
} else {
@@ -1614,240 +1286,152 @@ static void ath_rc_update(struct ath_softc *sc,
* Treating it as an excessive retry penalizes the rate
* inordinately.
*/
- if (rcs[0].tries == 1 && xretries == 1)
+ if (rates[0].count == 1 && xretries == 1)
xretries = 2;
}
- flags = rcs[series].flags;
+ flags = rates[i].flags;
+
/* If HT40 and we have switched mode from 40 to 20 => don't update */
- if ((flags & ATH_RC_CW40_FLAG) &&
- (rate_ctrl->rc_phy_mode != (flags & ATH_RC_CW40_FLAG)))
+ if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
+ (ath_rc_priv->rc_phy_mode != WLAN_RC_40_FLAG)) {
return;
+ }
- if ((flags & ATH_RC_CW40_FLAG) && (flags & ATH_RC_SGI_FLAG))
- rix = rate_table->info[rcs[series].rix].ht_index;
- else if (flags & ATH_RC_SGI_FLAG)
- rix = rate_table->info[rcs[series].rix].sgi_index;
- else if (flags & ATH_RC_CW40_FLAG)
- rix = rate_table->info[rcs[series].rix].cw40index;
- else
- rix = rate_table->info[rcs[series].rix].base_index;
-
- ath_rc_update_ht(sc, ath_rc_priv, info_priv, rix,
- xretries, long_retry);
+ rix = ath_rc_get_rateindex(rate_table, &rates[i]);
+ ath_rc_update_ht(sc, ath_rc_priv, tx_info_priv, rix,
+ xretries, long_retry);
}
-/*
- * Process a tx descriptor for a completed transmit (success or failure).
- */
-static void ath_rate_tx_complete(struct ath_softc *sc,
- struct ath_node *an,
- struct ath_rate_node *rc_priv,
- struct ath_tx_info_priv *info_priv)
+static struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc,
+ enum ieee80211_band band,
+ bool is_ht, bool is_cw_40)
{
- int final_ts_idx = info_priv->tx.ts_rateindex;
- int tx_status = 0, is_underrun = 0;
- struct ath_vap *avp;
-
- avp = rc_priv->avp;
- if ((avp->av_config.av_fixed_rateset != IEEE80211_FIXED_RATE_NONE) ||
- (info_priv->tx.ts_status & ATH9K_TXERR_FILT))
- return;
-
- if (info_priv->tx.ts_rssi > 0) {
- ATH_RSSI_LPF(an->an_chainmask_sel.tx_avgrssi,
- info_priv->tx.ts_rssi);
- }
-
- /*
- * If underrun error is seen assume it as an excessive retry only
- * if prefetch trigger level have reached the max (0x3f for 5416)
- * Adjust the long retry as if the frame was tried ATH_11N_TXMAXTRY
- * times. This affects how ratectrl updates PER for the failed rate.
- */
- if (info_priv->tx.ts_flags &
- (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN) &&
- ((sc->sc_ah->ah_txTrigLevel) >= tx_triglevel_max)) {
- tx_status = 1;
- is_underrun = 1;
+ int mode = 0;
+
+ switch(band) {
+ case IEEE80211_BAND_2GHZ:
+ mode = ATH9K_MODE_11G;
+ if (is_ht)
+ mode = ATH9K_MODE_11NG_HT20;
+ if (is_cw_40)
+ mode = ATH9K_MODE_11NG_HT40PLUS;
+ break;
+ case IEEE80211_BAND_5GHZ:
+ mode = ATH9K_MODE_11A;
+ if (is_ht)
+ mode = ATH9K_MODE_11NA_HT20;
+ if (is_cw_40)
+ mode = ATH9K_MODE_11NA_HT40PLUS;
+ break;
+ default:
+ DPRINTF(sc, ATH_DBG_CONFIG, "Invalid band\n");
+ return NULL;
}
- if ((info_priv->tx.ts_status & ATH9K_TXERR_XRETRY) ||
- (info_priv->tx.ts_status & ATH9K_TXERR_FIFO))
- tx_status = 1;
+ BUG_ON(mode >= ATH9K_MODE_MAX);
- ath_rc_update(sc, rc_priv, info_priv, final_ts_idx, tx_status,
- (is_underrun) ? ATH_11N_TXMAXTRY :
- info_priv->tx.ts_longretry);
+ DPRINTF(sc, ATH_DBG_CONFIG, "Choosing rate table for mode: %d\n", mode);
+ return sc->hw_rate_table[mode];
}
-/*
- * Update the SIB's rate control information
- *
- * This should be called when the supported rates change
- * (e.g. SME operation, wireless mode change)
- *
- * It will determine which rates are valid for use.
- */
-static void ath_rc_sib_update(struct ath_softc *sc,
- struct ath_rate_node *ath_rc_priv,
- u32 capflag, int keep_state,
- struct ath_rateset *negotiated_rates,
- struct ath_rateset *negotiated_htrates)
+static void ath_rc_init(struct ath_softc *sc,
+ struct ath_rate_priv *ath_rc_priv,
+ struct ieee80211_supported_band *sband,
+ struct ieee80211_sta *sta)
{
struct ath_rate_table *rate_table = NULL;
- struct ath_rate_softc *asc = (struct ath_rate_softc *)sc->sc_rc;
- struct ath_rateset *rateset = negotiated_rates;
- u8 *ht_mcs = (u8 *)negotiated_htrates;
- struct ath_tx_ratectrl *rate_ctrl =
- (struct ath_tx_ratectrl *)ath_rc_priv;
+ struct ath_rateset *rateset = &ath_rc_priv->neg_rates;
+ u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates;
u8 i, j, k, hi = 0, hthi = 0;
- rate_table = (struct ath_rate_table *)
- asc->hw_rate_table[sc->sc_curmode];
+ /* FIXME: Adhoc */
+ if ((sc->sc_ah->ah_opmode == NL80211_IFTYPE_STATION) ||
+ (sc->sc_ah->ah_opmode == NL80211_IFTYPE_ADHOC)) {
+ bool is_cw_40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+ rate_table = ath_choose_rate_table(sc, sband->band,
+ sta->ht_cap.ht_supported,
+ is_cw_40);
+ } else if (sc->sc_ah->ah_opmode == NL80211_IFTYPE_AP) {
+ /* cur_rate_table would be set on init through config() */
+ rate_table = sc->cur_rate_table;
+ }
+
+ if (!rate_table) {
+ DPRINTF(sc, ATH_DBG_FATAL, "Rate table not initialized\n");
+ return;
+ }
+
+ if (sta->ht_cap.ht_supported) {
+ ath_rc_priv->ht_cap = (WLAN_RC_HT_FLAG | WLAN_RC_DS_FLAG);
+ if (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
+ ath_rc_priv->ht_cap |= WLAN_RC_40_FLAG;
+ }
/* Initial rate table size. Will change depending
* on the working rate set */
- rate_ctrl->rate_table_size = MAX_TX_RATE_TBL;
+ ath_rc_priv->rate_table_size = RATE_TABLE_SIZE;
/* Initialize thresholds according to the global rate table */
- for (i = 0 ; (i < rate_ctrl->rate_table_size) && (!keep_state); i++) {
- rate_ctrl->state[i].rssi_thres =
+ for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) {
+ ath_rc_priv->state[i].rssi_thres =
rate_table->info[i].rssi_ack_validmin;
- rate_ctrl->state[i].per = 0;
+ ath_rc_priv->state[i].per = 0;
}
/* Determine the valid rates */
- ath_rc_init_valid_txmask(rate_ctrl);
+ ath_rc_init_valid_txmask(ath_rc_priv);
for (i = 0; i < WLAN_RC_PHY_MAX; i++) {
for (j = 0; j < MAX_TX_RATE_PHY; j++)
- rate_ctrl->valid_phy_rateidx[i][j] = 0;
- rate_ctrl->valid_phy_ratecnt[i] = 0;
+ ath_rc_priv->valid_phy_rateidx[i][j] = 0;
+ ath_rc_priv->valid_phy_ratecnt[i] = 0;
}
- rate_ctrl->rc_phy_mode = (capflag & WLAN_RC_40_FLAG);
+ ath_rc_priv->rc_phy_mode = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG);
/* Set stream capability */
- ath_rc_priv->single_stream = (capflag & WLAN_RC_DS_FLAG) ? 0 : 1;
+ ath_rc_priv->single_stream = (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? 0 : 1;
if (!rateset->rs_nrates) {
/* No working rate, just initialize valid rates */
- hi = ath_rc_sib_init_validrates(ath_rc_priv, rate_table,
- capflag);
+ hi = ath_rc_init_validrates(ath_rc_priv, rate_table,
+ ath_rc_priv->ht_cap);
} else {
/* Use intersection of working rates and valid rates */
- hi = ath_rc_sib_setvalid_rates(ath_rc_priv, rate_table,
- rateset, capflag);
- if (capflag & WLAN_RC_HT_FLAG) {
- hthi = ath_rc_sib_setvalid_htrates(ath_rc_priv,
+ hi = ath_rc_setvalid_rates(ath_rc_priv, rate_table,
+ rateset, ath_rc_priv->ht_cap);
+ if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) {
+ hthi = ath_rc_setvalid_htrates(ath_rc_priv,
rate_table,
ht_mcs,
- capflag);
+ ath_rc_priv->ht_cap);
}
hi = A_MAX(hi, hthi);
}
- rate_ctrl->rate_table_size = hi + 1;
- rate_ctrl->rate_max_phy = 0;
- ASSERT(rate_ctrl->rate_table_size <= MAX_TX_RATE_TBL);
+ ath_rc_priv->rate_table_size = hi + 1;
+ ath_rc_priv->rate_max_phy = 0;
+ ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE);
for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) {
- for (j = 0; j < rate_ctrl->valid_phy_ratecnt[i]; j++) {
- rate_ctrl->valid_rate_index[k++] =
- rate_ctrl->valid_phy_rateidx[i][j];
+ for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) {
+ ath_rc_priv->valid_rate_index[k++] =
+ ath_rc_priv->valid_phy_rateidx[i][j];
}
- if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, TRUE)
- || !rate_ctrl->valid_phy_ratecnt[i])
+ if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, 1)
+ || !ath_rc_priv->valid_phy_ratecnt[i])
continue;
- rate_ctrl->rate_max_phy = rate_ctrl->valid_phy_rateidx[i][j-1];
+ ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1];
}
- ASSERT(rate_ctrl->rate_table_size <= MAX_TX_RATE_TBL);
- ASSERT(k <= MAX_TX_RATE_TBL);
-
- rate_ctrl->max_valid_rate = k;
- /*
- * Some third party vendors don't send the supported rate series in
- * order. So sorting to make sure its in order, otherwise our RateFind
- * Algo will select wrong rates
- */
- ath_rc_sort_validrates(rate_table, rate_ctrl);
- rate_ctrl->rate_max_phy = rate_ctrl->valid_rate_index[k-4];
-}
-
-/*
- * Update rate-control state on station associate/reassociate.
- */
-static int ath_rate_newassoc(struct ath_softc *sc,
- struct ath_rate_node *ath_rc_priv,
- unsigned int capflag,
- struct ath_rateset *negotiated_rates,
- struct ath_rateset *negotiated_htrates)
-{
-
-
- ath_rc_priv->ht_cap =
- ((capflag & ATH_RC_DS_FLAG) ? WLAN_RC_DS_FLAG : 0) |
- ((capflag & ATH_RC_SGI_FLAG) ? WLAN_RC_SGI_FLAG : 0) |
- ((capflag & ATH_RC_HT_FLAG) ? WLAN_RC_HT_FLAG : 0) |
- ((capflag & ATH_RC_CW40_FLAG) ? WLAN_RC_40_FLAG : 0);
-
- ath_rc_sib_update(sc, ath_rc_priv, ath_rc_priv->ht_cap, 0,
- negotiated_rates, negotiated_htrates);
-
- return 0;
-}
-
-/*
- * This routine is called to initialize the rate control parameters
- * in the SIB. It is called initially during system initialization
- * or when a station is associated with the AP.
- */
-static void ath_rc_sib_init(struct ath_rate_node *ath_rc_priv)
-{
- struct ath_tx_ratectrl *rate_ctrl;
-
- rate_ctrl = (struct ath_tx_ratectrl *)(ath_rc_priv);
- rate_ctrl->rssi_down_time = jiffies_to_msecs(jiffies);
-}
-
-
-static void ath_setup_rates(struct ath_softc *sc,
- struct ieee80211_supported_band *sband,
- struct ieee80211_sta *sta,
- struct ath_rate_node *rc_priv)
-
-{
- int i, j = 0;
-
- DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
-
- for (i = 0; i < sband->n_bitrates; i++) {
- if (sta->supp_rates[sband->band] & BIT(i)) {
- rc_priv->neg_rates.rs_rates[j]
- = (sband->bitrates[i].bitrate * 2) / 10;
- j++;
- }
- }
- rc_priv->neg_rates.rs_nrates = j;
-}
-
-void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv)
-{
- struct ath_softc *sc = hw->priv;
- u32 capflag = 0;
-
- if (hw->conf.ht_conf.ht_supported) {
- capflag |= ATH_RC_HT_FLAG | ATH_RC_DS_FLAG;
- if (sc->sc_ht_info.tx_chan_width == ATH9K_HT_MACMODE_2040)
- capflag |= ATH_RC_CW40_FLAG;
- }
-
- ath_rate_newassoc(sc, rc_priv, capflag,
- &rc_priv->neg_rates,
- &rc_priv->neg_ht_rates);
+ ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE);
+ ASSERT(k <= RATE_TABLE_SIZE);
+ ath_rc_priv->max_valid_rate = k;
+ ath_rc_sort_validrates(rate_table, ath_rc_priv);
+ ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4];
+ sc->cur_rate_table = rate_table;
}
/* Rate Control callbacks */
@@ -1856,163 +1440,88 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
struct sk_buff *skb)
{
struct ath_softc *sc = priv;
- struct ath_tx_info_priv *tx_info_priv;
- struct ath_node *an;
+ struct ath_rate_priv *ath_rc_priv = priv_sta;
+ struct ath_tx_info_priv *tx_info_priv = NULL;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr;
+ int final_ts_idx, tx_status = 0, is_underrun = 0;
__le16 fc;
hdr = (struct ieee80211_hdr *)skb->data;
fc = hdr->frame_control;
- tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
+ tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
+ final_ts_idx = tx_info_priv->tx.ts_rateindex;
- spin_lock_bh(&sc->node_lock);
- an = ath_node_find(sc, hdr->addr1);
- spin_unlock_bh(&sc->node_lock);
+ if (!priv_sta || !ieee80211_is_data(fc) ||
+ !tx_info_priv->update_rc)
+ goto exit;
- if (!an || !priv_sta || !ieee80211_is_data(fc)) {
- if (tx_info->driver_data[0] != NULL) {
- kfree(tx_info->driver_data[0]);
- tx_info->driver_data[0] = NULL;
- }
- return;
- }
- if (tx_info->driver_data[0] != NULL) {
- ath_rate_tx_complete(sc, an, priv_sta, tx_info_priv);
- kfree(tx_info->driver_data[0]);
- tx_info->driver_data[0] = NULL;
- }
-}
-
-static void ath_tx_aggr_resp(struct ath_softc *sc,
- struct ieee80211_supported_band *sband,
- struct ieee80211_sta *sta,
- struct ath_node *an,
- u8 tidno)
-{
- struct ath_atx_tid *txtid;
- u16 buffersize = 0;
- int state;
- struct sta_info *si;
-
- if (!(sc->sc_flags & SC_OP_TXAGGR))
- return;
-
- txtid = ATH_AN_2_TID(an, tidno);
- if (!txtid->paused)
- return;
+ if (tx_info_priv->tx.ts_status & ATH9K_TXERR_FILT)
+ goto exit;
/*
- * XXX: This is entirely busted, we aren't supposed to
- * access the sta from here because it's internal
- * to mac80211, and looking at the state without
- * locking is wrong too.
+ * If underrun error is seen assume it as an excessive retry only
+ * if prefetch trigger level have reached the max (0x3f for 5416)
+ * Adjust the long retry as if the frame was tried ATH_11N_TXMAXTRY
+ * times. This affects how ratectrl updates PER for the failed rate.
*/
- si = container_of(sta, struct sta_info, sta);
- buffersize = IEEE80211_MIN_AMPDU_BUF <<
- sband->ht_info.ampdu_factor; /* FIXME */
- state = si->ampdu_mlme.tid_state_tx[tidno];
-
- if (state & HT_ADDBA_RECEIVED_MSK) {
- txtid->addba_exchangecomplete = 1;
- txtid->addba_exchangeinprogress = 0;
- txtid->baw_size = buffersize;
-
- DPRINTF(sc, ATH_DBG_AGGR,
- "%s: Resuming tid, buffersize: %d\n",
- __func__,
- buffersize);
-
- ath_tx_resume_tid(sc, txtid);
+ if (tx_info_priv->tx.ts_flags &
+ (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN) &&
+ ((sc->sc_ah->ah_txTrigLevel) >= ath_rc_priv->tx_triglevel_max)) {
+ tx_status = 1;
+ is_underrun = 1;
}
+
+ if ((tx_info_priv->tx.ts_status & ATH9K_TXERR_XRETRY) ||
+ (tx_info_priv->tx.ts_status & ATH9K_TXERR_FIFO))
+ tx_status = 1;
+
+ ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status,
+ (is_underrun) ? ATH_11N_TXMAXTRY :
+ tx_info_priv->tx.ts_longretry);
+
+exit:
+ kfree(tx_info_priv);
}
-static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband,
- struct ieee80211_sta *sta, void *priv_sta,
- struct sk_buff *skb, struct rate_selection *sel)
+static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
+ struct ieee80211_tx_rate_control *txrc)
{
+ struct ieee80211_supported_band *sband = txrc->sband;
+ struct sk_buff *skb = txrc->skb;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ath_softc *sc = priv;
struct ieee80211_hw *hw = sc->hw;
- struct ath_tx_info_priv *tx_info_priv;
- struct ath_rate_node *ath_rc_priv = priv_sta;
- struct ath_node *an;
+ struct ath_rate_priv *ath_rc_priv = priv_sta;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- int is_probe = FALSE, chk, ret;
- s8 lowest_idx;
+ int is_probe = 0;
__le16 fc = hdr->frame_control;
- u8 *qc, tid;
- DECLARE_MAC_BUF(mac);
-
- DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
-
- /* allocate driver private area of tx_info */
- tx_info->driver_data[0] = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC);
- ASSERT(tx_info->driver_data[0] != NULL);
- tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
- lowest_idx = rate_lowest_index(sband, sta);
- tx_info_priv->min_rate = (sband->bitrates[lowest_idx].bitrate * 2) / 10;
/* lowest rate for management and multicast/broadcast frames */
- if (!ieee80211_is_data(fc) ||
- is_multicast_ether_addr(hdr->addr1) || !sta) {
- sel->rate_idx = lowest_idx;
+ if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) ||
+ !sta) {
+ tx_info->control.rates[0].idx = rate_lowest_index(sband, sta);
+ tx_info->control.rates[0].count =
+ is_multicast_ether_addr(hdr->addr1) ? 1 : ATH_MGT_TXMAXTRY;
return;
}
/* Find tx rate for unicast frames */
- ath_rate_findrate(sc, ath_rc_priv,
- ATH_11N_TXMAXTRY, 4,
- ATH_RC_PROBE_ALLOWED,
- tx_info_priv->rcs,
- &is_probe,
- false);
- if (is_probe)
- sel->probe_idx = ath_rc_priv->tx_ratectrl.probe_rate;
-
- /* Ratecontrol sometimes returns invalid rate index */
- if (tx_info_priv->rcs[0].rix != 0xff)
- ath_rc_priv->prev_data_rix = tx_info_priv->rcs[0].rix;
- else
- tx_info_priv->rcs[0].rix = ath_rc_priv->prev_data_rix;
-
- sel->rate_idx = tx_info_priv->rcs[0].rix;
+ ath_rc_ratefind(sc, ath_rc_priv, ATH_11N_TXMAXTRY, 4,
+ tx_info, &is_probe, false);
/* Check if aggregation has to be enabled for this tid */
-
- if (hw->conf.ht_conf.ht_supported) {
+ if (hw->conf.ht.enabled) {
if (ieee80211_is_data_qos(fc)) {
+ u8 *qc, tid;
+ struct ath_node *an;
+
qc = ieee80211_get_qos_ctl(hdr);
tid = qc[0] & 0xf;
+ an = (struct ath_node *)sta->drv_priv;
- spin_lock_bh(&sc->node_lock);
- an = ath_node_find(sc, hdr->addr1);
- spin_unlock_bh(&sc->node_lock);
-
- if (!an) {
- DPRINTF(sc, ATH_DBG_AGGR,
- "%s: Node not found to "
- "init/chk TX aggr\n", __func__);
- return;
- }
-
- chk = ath_tx_aggr_check(sc, an, tid);
- if (chk == AGGR_REQUIRED) {
- ret = ieee80211_start_tx_ba_session(hw,
- hdr->addr1, tid);
- if (ret)
- DPRINTF(sc, ATH_DBG_AGGR,
- "%s: Unable to start tx "
- "aggr for: %s\n",
- __func__,
- print_mac(mac, hdr->addr1));
- else
- DPRINTF(sc, ATH_DBG_AGGR,
- "%s: Started tx aggr for: %s\n",
- __func__,
- print_mac(mac, hdr->addr1));
- } else if (chk == AGGR_EXCHANGE_PROGRESS)
- ath_tx_aggr_resp(sc, sband, sta, an, tid);
+ if(ath_tx_aggr_check(sc, an, tid))
+ ieee80211_start_tx_ba_session(hw, hdr->addr1, tid);
}
}
}
@@ -2021,34 +1530,33 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta)
{
struct ath_softc *sc = priv;
- struct ath_rate_node *ath_rc_priv = priv_sta;
+ struct ath_rate_priv *ath_rc_priv = priv_sta;
int i, j = 0;
- DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
+ for (i = 0; i < sband->n_bitrates; i++) {
+ if (sta->supp_rates[sband->band] & BIT(i)) {
+ ath_rc_priv->neg_rates.rs_rates[j]
+ = (sband->bitrates[i].bitrate * 2) / 10;
+ j++;
+ }
+ }
+ ath_rc_priv->neg_rates.rs_nrates = j;
- ath_setup_rates(sc, sband, sta, ath_rc_priv);
- if (sc->hw->conf.flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
- for (i = 0; i < MCS_SET_SIZE; i++) {
- if (sc->hw->conf.ht_conf.supp_mcs_set[i/8] & (1<<(i%8)))
+ if (sta->ht_cap.ht_supported) {
+ for (i = 0, j = 0; i < 77; i++) {
+ if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8)))
ath_rc_priv->neg_ht_rates.rs_rates[j++] = i;
if (j == ATH_RATE_MAX)
break;
}
ath_rc_priv->neg_ht_rates.rs_nrates = j;
}
- ath_rc_node_update(sc->hw, priv_sta);
-}
-static void ath_rate_clear(void *priv)
-{
- return;
+ ath_rc_init(sc, priv_sta, sband, sta);
}
static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
{
- struct ath_softc *sc = hw->priv;
-
- DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
return hw->priv;
}
@@ -2060,19 +1568,17 @@ static void ath_rate_free(void *priv)
static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
{
struct ath_softc *sc = priv;
- struct ath_vap *avp = sc->sc_vaps[0];
- struct ath_rate_node *rate_priv;
-
- DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
+ struct ath_rate_priv *rate_priv;
- rate_priv = ath_rate_node_alloc(avp, sc->sc_rc, gfp);
+ rate_priv = kzalloc(sizeof(struct ath_rate_priv), gfp);
if (!rate_priv) {
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: Unable to allocate private rc structure\n",
- __func__);
+ "Unable to allocate private rc structure\n");
return NULL;
}
- ath_rc_sib_init(rate_priv);
+
+ rate_priv->rssi_down_time = jiffies_to_msecs(jiffies);
+ rate_priv->tx_triglevel_max = sc->sc_ah->ah_caps.tx_triglevel_max;
return rate_priv;
}
@@ -2080,11 +1586,8 @@ static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp
static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta,
void *priv_sta)
{
- struct ath_rate_node *rate_priv = priv_sta;
- struct ath_softc *sc = priv;
-
- DPRINTF(sc, ATH_DBG_RATE, "%s", __func__);
- ath_rate_node_free(rate_priv);
+ struct ath_rate_priv *rate_priv = priv_sta;
+ kfree(rate_priv);
}
static struct rate_control_ops ath_rate_ops = {
@@ -2093,13 +1596,69 @@ static struct rate_control_ops ath_rate_ops = {
.tx_status = ath_tx_status,
.get_rate = ath_get_rate,
.rate_init = ath_rate_init,
- .clear = ath_rate_clear,
.alloc = ath_rate_alloc,
.free = ath_rate_free,
.alloc_sta = ath_rate_alloc_sta,
.free_sta = ath_rate_free_sta,
};
+static void ath_setup_rate_table(struct ath_softc *sc,
+ struct ath_rate_table *rate_table)
+{
+ int i;
+
+ for (i = 0; i < 256; i++)
+ rate_table->rateCodeToIndex[i] = (u8)-1;
+
+ for (i = 0; i < rate_table->rate_cnt; i++) {
+ u8 code = rate_table->info[i].ratecode;
+ u8 cix = rate_table->info[i].ctrl_rate;
+ u8 sh = rate_table->info[i].short_preamble;
+
+ rate_table->rateCodeToIndex[code] = i;
+ rate_table->rateCodeToIndex[code | sh] = i;
+
+ rate_table->info[i].lpAckDuration =
+ ath9k_hw_computetxtime(sc->sc_ah, rate_table,
+ WLAN_CTRL_FRAME_SIZE,
+ cix,
+ false);
+ rate_table->info[i].spAckDuration =
+ ath9k_hw_computetxtime(sc->sc_ah, rate_table,
+ WLAN_CTRL_FRAME_SIZE,
+ cix,
+ true);
+ }
+}
+
+void ath_rate_attach(struct ath_softc *sc)
+{
+ sc->hw_rate_table[ATH9K_MODE_11B] =
+ &ar5416_11b_ratetable;
+ sc->hw_rate_table[ATH9K_MODE_11A] =
+ &ar5416_11a_ratetable;
+ sc->hw_rate_table[ATH9K_MODE_11G] =
+ &ar5416_11g_ratetable;
+ sc->hw_rate_table[ATH9K_MODE_11NA_HT20] =
+ &ar5416_11na_ratetable;
+ sc->hw_rate_table[ATH9K_MODE_11NG_HT20] =
+ &ar5416_11ng_ratetable;
+ sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] =
+ &ar5416_11na_ratetable;
+ sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] =
+ &ar5416_11na_ratetable;
+ sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] =
+ &ar5416_11ng_ratetable;
+ sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS] =
+ &ar5416_11ng_ratetable;
+
+ ath_setup_rate_table(sc, &ar5416_11b_ratetable);
+ ath_setup_rate_table(sc, &ar5416_11a_ratetable);
+ ath_setup_rate_table(sc, &ar5416_11g_ratetable);
+ ath_setup_rate_table(sc, &ar5416_11na_ratetable);
+ ath_setup_rate_table(sc, &ar5416_11ng_ratetable);
+}
+
int ath_rate_control_register(void)
{
return ieee80211_rate_control_register(&ath_rate_ops);
@@ -2109,4 +1668,3 @@ void ath_rate_control_unregister(void)
{
ieee80211_rate_control_unregister(&ath_rate_ops);
}
-
diff --git a/drivers/net/wireless/ath9k/rc.h b/drivers/net/wireless/ath9k/rc.h
index b95b41508b98..97c60d12e8aa 100644
--- a/drivers/net/wireless/ath9k/rc.h
+++ b/drivers/net/wireless/ath9k/rc.h
@@ -20,84 +20,24 @@
#define RC_H
#include "ath9k.h"
-/*
- * Interface definitions for transmit rate control modules for the
- * Atheros driver.
- *
- * A rate control module is responsible for choosing the transmit rate
- * for each data frame. Management+control frames are always sent at
- * a fixed rate.
- *
- * Only one module may be present at a time; the driver references
- * rate control interfaces by symbol name. If multiple modules are
- * to be supported we'll need to switch to a registration-based scheme
- * as is currently done, for example, for authentication modules.
- *
- * An instance of the rate control module is attached to each device
- * at attach time and detached when the device is destroyed. The module
- * may associate data with each device and each node (station). Both
- * sets of storage are opaque except for the size of the per-node storage
- * which must be provided when the module is attached.
- *
- * The rate control module is notified for each state transition and
- * station association/reassociation. Otherwise it is queried for a
- * rate for each outgoing frame and provided status from each transmitted
- * frame. Any ancillary processing is the responsibility of the module
- * (e.g. if periodic processing is required then the module should setup
- * it's own timer).
- *
- * In addition to the transmit rate for each frame the module must also
- * indicate the number of attempts to make at the specified rate. If this
- * number is != ATH_TXMAXTRY then an additional callback is made to setup
- * additional transmit state. The rate control code is assumed to write
- * this additional data directly to the transmit descriptor.
- */
struct ath_softc;
-#define TRUE 1
-#define FALSE 0
+#define ATH_RATE_MAX 30
+#define RATE_TABLE_SIZE 64
+#define MAX_TX_RATE_PHY 48
-#define ATH_RATE_MAX 30
-#define MCS_SET_SIZE 128
+/* VALID_ALL - valid for 20/40/Legacy,
+ * VALID - Legacy only,
+ * VALID_20 - HT 20 only,
+ * VALID_40 - HT 40 only */
-enum ieee80211_fixed_rate_mode {
- IEEE80211_FIXED_RATE_NONE = 0,
- IEEE80211_FIXED_RATE_MCS = 1 /* HT rates */
-};
-
-/*
- * Use the hal os glue code to get ms time
- */
-#define IEEE80211_RATE_IDX_ENTRY(val, idx) (((val&(0xff<<(idx*8)))>>(idx*8)))
-
-#define WLAN_PHY_HT_20_SS WLAN_RC_PHY_HT_20_SS
-#define WLAN_PHY_HT_20_DS WLAN_RC_PHY_HT_20_DS
-#define WLAN_PHY_HT_20_DS_HGI WLAN_RC_PHY_HT_20_DS_HGI
-#define WLAN_PHY_HT_40_SS WLAN_RC_PHY_HT_40_SS
-#define WLAN_PHY_HT_40_SS_HGI WLAN_RC_PHY_HT_40_SS_HGI
-#define WLAN_PHY_HT_40_DS WLAN_RC_PHY_HT_40_DS
-#define WLAN_PHY_HT_40_DS_HGI WLAN_RC_PHY_HT_40_DS_HGI
-
-#define WLAN_PHY_OFDM PHY_OFDM
-#define WLAN_PHY_CCK PHY_CCK
-
-#define TRUE_20 0x2
-#define TRUE_40 0x4
-#define TRUE_2040 (TRUE_20|TRUE_40)
-#define TRUE_ALL (TRUE_2040|TRUE)
-
-enum {
- WLAN_RC_PHY_HT_20_SS = 4,
- WLAN_RC_PHY_HT_20_DS,
- WLAN_RC_PHY_HT_40_SS,
- WLAN_RC_PHY_HT_40_DS,
- WLAN_RC_PHY_HT_20_SS_HGI,
- WLAN_RC_PHY_HT_20_DS_HGI,
- WLAN_RC_PHY_HT_40_SS_HGI,
- WLAN_RC_PHY_HT_40_DS_HGI,
- WLAN_RC_PHY_MAX
-};
+#define INVALID 0x0
+#define VALID 0x1
+#define VALID_20 0x2
+#define VALID_40 0x4
+#define VALID_2040 (VALID_20|VALID_40)
+#define VALID_ALL (VALID_2040|VALID)
#define WLAN_RC_PHY_DS(_phy) ((_phy == WLAN_RC_PHY_HT_20_DS) \
|| (_phy == WLAN_RC_PHY_HT_40_DS) \
@@ -114,26 +54,22 @@ enum {
#define WLAN_RC_PHY_HT(_phy) (_phy >= WLAN_RC_PHY_HT_20_SS)
-/* Returns the capflag mode */
#define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ? \
- (capflag & WLAN_RC_40_FLAG) ? TRUE_40 : TRUE_20 : TRUE))
+ (capflag & WLAN_RC_40_FLAG) ? VALID_40 : VALID_20 : VALID))
/* Return TRUE if flag supports HT20 && client supports HT20 or
* return TRUE if flag supports HT40 && client supports HT40.
* This is used becos some rates overlap between HT20/HT40.
*/
-
-#define WLAN_RC_PHY_HT_VALID(flag, capflag) (((flag & TRUE_20) && !(capflag \
- & WLAN_RC_40_FLAG)) || ((flag & TRUE_40) && \
- (capflag & WLAN_RC_40_FLAG)))
+#define WLAN_RC_PHY_HT_VALID(flag, capflag) \
+ (((flag & VALID_20) && !(capflag & WLAN_RC_40_FLAG)) || \
+ ((flag & VALID_40) && (capflag & WLAN_RC_40_FLAG)))
#define WLAN_RC_DS_FLAG (0x01)
#define WLAN_RC_40_FLAG (0x02)
#define WLAN_RC_SGI_FLAG (0x04)
#define WLAN_RC_HT_FLAG (0x08)
-#define RATE_TABLE_SIZE 64
-
/**
* struct ath_rate_table - Rate Control table
* @valid: valid for use in rate control
@@ -150,10 +86,11 @@ enum {
* @max_4ms_framelen: maximum frame length(bytes) for tx duration
* @probe_interval: interval for rate control to probe for other rates
* @rssi_reduce_interval: interval for rate control to reduce rssi
- * @initial_ratemax: initial ratemax value used in ath_rc_sib_update()
+ * @initial_ratemax: initial ratemax value
*/
struct ath_rate_table {
int rate_cnt;
+ u8 rateCodeToIndex[256];
struct {
int valid;
int valid_single_stream;
@@ -171,42 +108,26 @@ struct ath_rate_table {
u8 sgi_index;
u8 ht_index;
u32 max_4ms_framelen;
+ u16 lpAckDuration;
+ u16 spAckDuration;
} info[RATE_TABLE_SIZE];
u32 probe_interval;
u32 rssi_reduce_interval;
u8 initial_ratemax;
};
-#define ATH_RC_PROBE_ALLOWED 0x00000001
-#define ATH_RC_MINRATE_LASTRATE 0x00000002
-
-struct ath_rc_series {
- u8 rix;
- u8 tries;
- u8 flags;
- u32 max_4ms_framelen;
-};
-
-/* rcs_flags definition */
-#define ATH_RC_DS_FLAG 0x01
-#define ATH_RC_CW40_FLAG 0x02 /* CW 40 */
-#define ATH_RC_SGI_FLAG 0x04 /* Short Guard Interval */
-#define ATH_RC_HT_FLAG 0x08 /* HT */
-#define ATH_RC_RTSCTS_FLAG 0x10 /* RTS-CTS */
-
-/*
- * State structures for new rate adaptation code
- */
-#define MAX_TX_RATE_TBL 64
-#define MAX_TX_RATE_PHY 48
-
struct ath_tx_ratectrl_state {
int8_t rssi_thres; /* required rssi for this rate (dB) */
u8 per; /* recent estimate of packet error rate (%) */
};
+struct ath_rateset {
+ u8 rs_nrates;
+ u8 rs_rates[ATH_RATE_MAX];
+};
+
/**
- * struct ath_tx_ratectrl - TX Rate control Information
+ * struct ath_rate_priv - Rate Control priv data
* @state: RC state
* @rssi_last: last ACK rssi
* @rssi_last_lookup: last ACK rssi used for lookup
@@ -225,9 +146,13 @@ struct ath_tx_ratectrl_state {
* @valid_phy_ratecnt: valid rate count
* @rate_max_phy: phy index for the max rate
* @probe_interval: interval for ratectrl to probe for other rates
+ * @prev_data_rix: rate idx of last data frame
+ * @ht_cap: HT capabilities
+ * @single_stream: When TRUE, only single TX stream possible
+ * @neg_rates: Negotatied rates
+ * @neg_ht_rates: Negotiated HT rates
*/
-struct ath_tx_ratectrl {
- struct ath_tx_ratectrl_state state[MAX_TX_RATE_TBL];
+struct ath_rate_priv {
int8_t rssi_last;
int8_t rssi_last_lookup;
int8_t rssi_last_prev;
@@ -237,89 +162,40 @@ struct ath_tx_ratectrl {
int32_t rssi_sum;
u8 rate_table_size;
u8 probe_rate;
- u32 rssi_time;
- u32 rssi_down_time;
- u32 probe_time;
u8 hw_maxretry_pktcnt;
u8 max_valid_rate;
- u8 valid_rate_index[MAX_TX_RATE_TBL];
- u32 per_down_time;
-
- /* 11n state */
+ u8 valid_rate_index[RATE_TABLE_SIZE];
+ u8 ht_cap;
+ u8 single_stream;
u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX];
- u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][MAX_TX_RATE_TBL];
+ u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE];
u8 rc_phy_mode;
u8 rate_max_phy;
+ u32 rssi_time;
+ u32 rssi_down_time;
+ u32 probe_time;
+ u32 per_down_time;
u32 probe_interval;
-};
-
-struct ath_rateset {
- u8 rs_nrates;
- u8 rs_rates[ATH_RATE_MAX];
-};
-
-/* per-device state */
-struct ath_rate_softc {
- /* phy tables that contain rate control data */
- const void *hw_rate_table[ATH9K_MODE_MAX];
-
- /* -1 or index of fixed rate */
- int fixedrix;
-};
-
-/* per-node state */
-struct ath_rate_node {
- struct ath_tx_ratectrl tx_ratectrl;
-
- /* rate idx of last data frame */
u32 prev_data_rix;
-
- /* ht capabilities */
- u8 ht_cap;
-
- /* When TRUE, only single stream Tx possible */
- u8 single_stream;
-
- /* Negotiated rates */
+ u32 tx_triglevel_max;
+ struct ath_tx_ratectrl_state state[RATE_TABLE_SIZE];
struct ath_rateset neg_rates;
-
- /* Negotiated HT rates */
struct ath_rateset neg_ht_rates;
-
struct ath_rate_softc *asc;
- struct ath_vap *avp;
};
-/* Driver data of ieee80211_tx_info */
struct ath_tx_info_priv {
- struct ath_rc_series rcs[4];
struct ath_tx_status tx;
int n_frames;
int n_bad_frames;
- u8 min_rate;
+ bool update_rc;
};
-/*
- * Attach/detach a rate control module.
- */
-struct ath_rate_softc *ath_rate_attach(struct ath_hal *ah);
-void ath_rate_detach(struct ath_rate_softc *asc);
-
-/*
- * Update/reset rate control state for 802.11 state transitions.
- * Important mostly as the analog to ath_rate_newassoc when operating
- * in station mode.
- */
-void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv);
-void ath_rate_newstate(struct ath_softc *sc, struct ath_vap *avp);
-
-/*
- * Return rate index for given Dot11 Rate.
- */
-u8 ath_rate_findrateix(struct ath_softc *sc,
- u8 dot11_rate);
+#define ATH_TX_INFO_PRIV(tx_info) \
+ ((struct ath_tx_info_priv *)((tx_info)->rate_driver_data[0]))
-/* Routines to register/unregister rate control algorithm */
+void ath_rate_attach(struct ath_softc *sc);
+u8 ath_rate_findrateix(struct ath_softc *sc, u8 dot11_rate);
int ath_rate_control_register(void);
void ath_rate_control_unregister(void);
diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c
index 504a0444d89f..462e08c3d09d 100644
--- a/drivers/net/wireless/ath9k/recv.c
+++ b/drivers/net/wireless/ath9k/recv.c
@@ -14,10 +14,6 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/*
- * Implementation of receive path.
- */
-
#include "core.h"
/*
@@ -27,10 +23,7 @@
* MAC acknowledges BA status as long as it copies frames to host
* buffer (or rx fifo). This can incorrectly acknowledge packets
* to a sender if last desc is self-linked.
- *
- * NOTE: Caller should hold the rxbuf lock.
*/
-
static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
{
struct ath_hal *ah = sc->sc_ah;
@@ -40,356 +33,53 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf)
ATH_RXBUF_RESET(bf);
ds = bf->bf_desc;
- ds->ds_link = 0; /* link to null */
+ ds->ds_link = 0; /* link to null */
ds->ds_data = bf->bf_buf_addr;
- /* XXX For RADAR?
- * virtual addr of the beginning of the buffer. */
+ /* virtual addr of the beginning of the buffer. */
skb = bf->bf_mpdu;
ASSERT(skb != NULL);
ds->ds_vdata = skb->data;
- /* setup rx descriptors. The sc_rxbufsize here tells the harware
+ /* setup rx descriptors. The rx.bufsize here tells the harware
* how much data it can DMA to us and that we are prepared
* to process */
- ath9k_hw_setuprxdesc(ah,
- ds,
- sc->sc_rxbufsize,
+ ath9k_hw_setuprxdesc(ah, ds,
+ sc->rx.bufsize,
0);
- if (sc->sc_rxlink == NULL)
+ if (sc->rx.rxlink == NULL)
ath9k_hw_putrxbuf(ah, bf->bf_daddr);
else
- *sc->sc_rxlink = bf->bf_daddr;
+ *sc->rx.rxlink = bf->bf_daddr;
- sc->sc_rxlink = &ds->ds_link;
+ sc->rx.rxlink = &ds->ds_link;
ath9k_hw_rxena(ah);
}
-/* Process received BAR frame */
-
-static int ath_bar_rx(struct ath_softc *sc,
- struct ath_node *an,
- struct sk_buff *skb)
-{
- struct ieee80211_bar *bar;
- struct ath_arx_tid *rxtid;
- struct sk_buff *tskb;
- struct ath_recv_status *rx_status;
- int tidno, index, cindex;
- u16 seqno;
-
- /* look at BAR contents */
-
- bar = (struct ieee80211_bar *)skb->data;
- tidno = (le16_to_cpu(bar->control) & IEEE80211_BAR_CTL_TID_M)
- >> IEEE80211_BAR_CTL_TID_S;
- seqno = le16_to_cpu(bar->start_seq_num) >> IEEE80211_SEQ_SEQ_SHIFT;
-
- /* process BAR - indicate all pending RX frames till the BAR seqno */
-
- rxtid = &an->an_aggr.rx.tid[tidno];
-
- spin_lock_bh(&rxtid->tidlock);
-
- /* get relative index */
-
- index = ATH_BA_INDEX(rxtid->seq_next, seqno);
-
- /* drop BAR if old sequence (index is too large) */
-
- if ((index > rxtid->baw_size) &&
- (index > (IEEE80211_SEQ_MAX - (rxtid->baw_size << 2))))
- /* discard frame, ieee layer may not treat frame as a dup */
- goto unlock_and_free;
-
- /* complete receive processing for all pending frames upto BAR seqno */
-
- cindex = (rxtid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
- while ((rxtid->baw_head != rxtid->baw_tail) &&
- (rxtid->baw_head != cindex)) {
- tskb = rxtid->rxbuf[rxtid->baw_head].rx_wbuf;
- rx_status = &rxtid->rxbuf[rxtid->baw_head].rx_status;
- rxtid->rxbuf[rxtid->baw_head].rx_wbuf = NULL;
-
- if (tskb != NULL)
- ath_rx_subframe(an, tskb, rx_status);
-
- INCR(rxtid->baw_head, ATH_TID_MAX_BUFS);
- INCR(rxtid->seq_next, IEEE80211_SEQ_MAX);
- }
-
- /* ... and indicate rest of the frames in-order */
-
- while (rxtid->baw_head != rxtid->baw_tail &&
- rxtid->rxbuf[rxtid->baw_head].rx_wbuf != NULL) {
- tskb = rxtid->rxbuf[rxtid->baw_head].rx_wbuf;
- rx_status = &rxtid->rxbuf[rxtid->baw_head].rx_status;
- rxtid->rxbuf[rxtid->baw_head].rx_wbuf = NULL;
-
- ath_rx_subframe(an, tskb, rx_status);
-
- INCR(rxtid->baw_head, ATH_TID_MAX_BUFS);
- INCR(rxtid->seq_next, IEEE80211_SEQ_MAX);
- }
-
-unlock_and_free:
- spin_unlock_bh(&rxtid->tidlock);
- /* free bar itself */
- dev_kfree_skb(skb);
- return IEEE80211_FTYPE_CTL;
-}
-
-/* Function to handle a subframe of aggregation when HT is enabled */
-
-static int ath_ampdu_input(struct ath_softc *sc,
- struct ath_node *an,
- struct sk_buff *skb,
- struct ath_recv_status *rx_status)
-{
- struct ieee80211_hdr *hdr;
- struct ath_arx_tid *rxtid;
- struct ath_rxbuf *rxbuf;
- u8 type, subtype;
- u16 rxseq;
- int tid = 0, index, cindex, rxdiff;
- __le16 fc;
- u8 *qc;
-
- hdr = (struct ieee80211_hdr *)skb->data;
- fc = hdr->frame_control;
-
- /* collect stats of frames with non-zero version */
-
- if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_VERS) != 0) {
- dev_kfree_skb(skb);
- return -1;
- }
-
- type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE;
- subtype = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_STYPE;
-
- if (ieee80211_is_back_req(fc))
- return ath_bar_rx(sc, an, skb);
-
- /* special aggregate processing only for qos unicast data frames */
-
- if (!ieee80211_is_data(fc) ||
- !ieee80211_is_data_qos(fc) ||
- is_multicast_ether_addr(hdr->addr1))
- return ath_rx_subframe(an, skb, rx_status);
-
- /* lookup rx tid state */
-
- if (ieee80211_is_data_qos(fc)) {
- qc = ieee80211_get_qos_ctl(hdr);
- tid = qc[0] & 0xf;
- }
-
- if (sc->sc_ah->ah_opmode == ATH9K_M_STA) {
- /* Drop the frame not belonging to me. */
- if (memcmp(hdr->addr1, sc->sc_myaddr, ETH_ALEN)) {
- dev_kfree_skb(skb);
- return -1;
- }
- }
-
- rxtid = &an->an_aggr.rx.tid[tid];
-
- spin_lock(&rxtid->tidlock);
-
- rxdiff = (rxtid->baw_tail - rxtid->baw_head) &
- (ATH_TID_MAX_BUFS - 1);
-
- /*
- * If the ADDBA exchange has not been completed by the source,
- * process via legacy path (i.e. no reordering buffer is needed)
- */
- if (!rxtid->addba_exchangecomplete) {
- spin_unlock(&rxtid->tidlock);
- return ath_rx_subframe(an, skb, rx_status);
- }
-
- /* extract sequence number from recvd frame */
-
- rxseq = le16_to_cpu(hdr->seq_ctrl) >> IEEE80211_SEQ_SEQ_SHIFT;
-
- if (rxtid->seq_reset) {
- rxtid->seq_reset = 0;
- rxtid->seq_next = rxseq;
- }
-
- index = ATH_BA_INDEX(rxtid->seq_next, rxseq);
-
- /* drop frame if old sequence (index is too large) */
-
- if (index > (IEEE80211_SEQ_MAX - (rxtid->baw_size << 2))) {
- /* discard frame, ieee layer may not treat frame as a dup */
- spin_unlock(&rxtid->tidlock);
- dev_kfree_skb(skb);
- return IEEE80211_FTYPE_DATA;
- }
-
- /* sequence number is beyond block-ack window */
-
- if (index >= rxtid->baw_size) {
-
- /* complete receive processing for all pending frames */
-
- while (index >= rxtid->baw_size) {
-
- rxbuf = rxtid->rxbuf + rxtid->baw_head;
-
- if (rxbuf->rx_wbuf != NULL) {
- ath_rx_subframe(an, rxbuf->rx_wbuf,
- &rxbuf->rx_status);
- rxbuf->rx_wbuf = NULL;
- }
-
- INCR(rxtid->baw_head, ATH_TID_MAX_BUFS);
- INCR(rxtid->seq_next, IEEE80211_SEQ_MAX);
-
- index--;
- }
- }
-
- /* add buffer to the recv ba window */
-
- cindex = (rxtid->baw_head + index) & (ATH_TID_MAX_BUFS - 1);
- rxbuf = rxtid->rxbuf + cindex;
-
- if (rxbuf->rx_wbuf != NULL) {
- spin_unlock(&rxtid->tidlock);
- /* duplicate frame */
- dev_kfree_skb(skb);
- return IEEE80211_FTYPE_DATA;
- }
-
- rxbuf->rx_wbuf = skb;
- rxbuf->rx_time = get_timestamp();
- rxbuf->rx_status = *rx_status;
-
- /* advance tail if sequence received is newer
- * than any received so far */
-
- if (index >= rxdiff) {
- rxtid->baw_tail = cindex;
- INCR(rxtid->baw_tail, ATH_TID_MAX_BUFS);
- }
-
- /* indicate all in-order received frames */
-
- while (rxtid->baw_head != rxtid->baw_tail) {
- rxbuf = rxtid->rxbuf + rxtid->baw_head;
- if (!rxbuf->rx_wbuf)
- break;
-
- ath_rx_subframe(an, rxbuf->rx_wbuf, &rxbuf->rx_status);
- rxbuf->rx_wbuf = NULL;
-
- INCR(rxtid->baw_head, ATH_TID_MAX_BUFS);
- INCR(rxtid->seq_next, IEEE80211_SEQ_MAX);
- }
-
- /*
- * start a timer to flush all received frames if there are pending
- * receive frames
- */
- if (rxtid->baw_head != rxtid->baw_tail)
- mod_timer(&rxtid->timer, ATH_RX_TIMEOUT);
- else
- del_timer_sync(&rxtid->timer);
-
- spin_unlock(&rxtid->tidlock);
- return IEEE80211_FTYPE_DATA;
-}
-
-/* Timer to flush all received sub-frames */
-
-static void ath_rx_timer(unsigned long data)
+static void ath_setdefantenna(struct ath_softc *sc, u32 antenna)
{
- struct ath_arx_tid *rxtid = (struct ath_arx_tid *)data;
- struct ath_node *an = rxtid->an;
- struct ath_rxbuf *rxbuf;
- int nosched;
-
- spin_lock_bh(&rxtid->tidlock);
- while (rxtid->baw_head != rxtid->baw_tail) {
- rxbuf = rxtid->rxbuf + rxtid->baw_head;
- if (!rxbuf->rx_wbuf) {
- INCR(rxtid->baw_head, ATH_TID_MAX_BUFS);
- INCR(rxtid->seq_next, IEEE80211_SEQ_MAX);
- continue;
- }
-
- /*
- * Stop if the next one is a very recent frame.
- *
- * Call get_timestamp in every iteration to protect against the
- * case in which a new frame is received while we are executing
- * this function. Using a timestamp obtained before entering
- * the loop could lead to a very large time interval
- * (a negative value typecast to unsigned), breaking the
- * function's logic.
- */
- if ((get_timestamp() - rxbuf->rx_time) <
- (ATH_RX_TIMEOUT * HZ / 1000))
- break;
-
- ath_rx_subframe(an, rxbuf->rx_wbuf,
- &rxbuf->rx_status);
- rxbuf->rx_wbuf = NULL;
-
- INCR(rxtid->baw_head, ATH_TID_MAX_BUFS);
- INCR(rxtid->seq_next, IEEE80211_SEQ_MAX);
- }
-
- /*
- * start a timer to flush all received frames if there are pending
- * receive frames
- */
- if (rxtid->baw_head != rxtid->baw_tail)
- nosched = 0;
- else
- nosched = 1; /* no need to re-arm the timer again */
-
- spin_unlock_bh(&rxtid->tidlock);
+ /* XXX block beacon interrupts */
+ ath9k_hw_setantenna(sc->sc_ah, antenna);
+ sc->rx.defant = antenna;
+ sc->rx.rxotherant = 0;
}
-/* Free all pending sub-frames in the re-ordering buffer */
-
-static void ath_rx_flush_tid(struct ath_softc *sc,
- struct ath_arx_tid *rxtid, int drop)
+/*
+ * Extend 15-bit time stamp from rx descriptor to
+ * a full 64-bit TSF using the current h/w TSF.
+*/
+static u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp)
{
- struct ath_rxbuf *rxbuf;
- unsigned long flag;
-
- spin_lock_irqsave(&rxtid->tidlock, flag);
- while (rxtid->baw_head != rxtid->baw_tail) {
- rxbuf = rxtid->rxbuf + rxtid->baw_head;
- if (!rxbuf->rx_wbuf) {
- INCR(rxtid->baw_head, ATH_TID_MAX_BUFS);
- INCR(rxtid->seq_next, IEEE80211_SEQ_MAX);
- continue;
- }
-
- if (drop)
- dev_kfree_skb(rxbuf->rx_wbuf);
- else
- ath_rx_subframe(rxtid->an,
- rxbuf->rx_wbuf,
- &rxbuf->rx_status);
-
- rxbuf->rx_wbuf = NULL;
+ u64 tsf;
- INCR(rxtid->baw_head, ATH_TID_MAX_BUFS);
- INCR(rxtid->seq_next, IEEE80211_SEQ_MAX);
- }
- spin_unlock_irqrestore(&rxtid->tidlock, flag);
+ tsf = ath9k_hw_gettsf64(sc->sc_ah);
+ if ((tsf & 0x7fff) < rstamp)
+ tsf -= 0x8000;
+ return (tsf & ~0x7fff) | rstamp;
}
-static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc,
- u32 len)
+static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len)
{
struct sk_buff *skb;
u32 off;
@@ -414,67 +104,131 @@ static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc,
skb_reserve(skb, sc->sc_cachelsz - off);
} else {
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: skbuff alloc of size %u failed\n",
- __func__, len);
+ "skbuff alloc of size %u failed\n", len);
return NULL;
}
return skb;
}
-static void ath_rx_requeue(struct ath_softc *sc, struct sk_buff *skb)
+/*
+ * For Decrypt or Demic errors, we only mark packet status here and always push
+ * up the frame up to let mac80211 handle the actual error case, be it no
+ * decryption key or real decryption error. This let us keep statistics there.
+ */
+static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds,
+ struct ieee80211_rx_status *rx_status, bool *decrypt_error,
+ struct ath_softc *sc)
{
- struct ath_buf *bf = ATH_RX_CONTEXT(skb)->ctx_rxbuf;
+ struct ieee80211_hdr *hdr;
+ u8 ratecode;
+ __le16 fc;
- ASSERT(bf != NULL);
+ hdr = (struct ieee80211_hdr *)skb->data;
+ fc = hdr->frame_control;
+ memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
- spin_lock_bh(&sc->sc_rxbuflock);
- if (bf->bf_status & ATH_BUFSTATUS_STALE) {
+ if (ds->ds_rxstat.rs_more) {
/*
- * This buffer is still held for hw acess.
- * Mark it as free to be re-queued it later.
+ * Frame spans multiple descriptors; this cannot happen yet
+ * as we don't support jumbograms. If not in monitor mode,
+ * discard the frame. Enable this if you want to see
+ * error frames in Monitor mode.
*/
- bf->bf_status |= ATH_BUFSTATUS_FREE;
- } else {
- /* XXX: we probably never enter here, remove after
- * verification */
- list_add_tail(&bf->list, &sc->sc_rxbuf);
- ath_rx_buf_link(sc, bf);
+ if (sc->sc_ah->ah_opmode != NL80211_IFTYPE_MONITOR)
+ goto rx_next;
+ } else if (ds->ds_rxstat.rs_status != 0) {
+ if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC)
+ rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+ if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY)
+ goto rx_next;
+
+ if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) {
+ *decrypt_error = true;
+ } else if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) {
+ if (ieee80211_is_ctl(fc))
+ /*
+ * Sometimes, we get invalid
+ * MIC failures on valid control frames.
+ * Remove these mic errors.
+ */
+ ds->ds_rxstat.rs_status &= ~ATH9K_RXERR_MIC;
+ else
+ rx_status->flag |= RX_FLAG_MMIC_ERROR;
+ }
+ /*
+ * Reject error frames with the exception of
+ * decryption and MIC failures. For monitor mode,
+ * we also ignore the CRC error.
+ */
+ if (sc->sc_ah->ah_opmode == NL80211_IFTYPE_MONITOR) {
+ if (ds->ds_rxstat.rs_status &
+ ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
+ ATH9K_RXERR_CRC))
+ goto rx_next;
+ } else {
+ if (ds->ds_rxstat.rs_status &
+ ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
+ goto rx_next;
+ }
+ }
}
- spin_unlock_bh(&sc->sc_rxbuflock);
-}
-/*
- * The skb indicated to upper stack won't be returned to us.
- * So we have to allocate a new one and queue it by ourselves.
- */
-static int ath_rx_indicate(struct ath_softc *sc,
- struct sk_buff *skb,
- struct ath_recv_status *status,
- u16 keyix)
-{
- struct ath_buf *bf = ATH_RX_CONTEXT(skb)->ctx_rxbuf;
- struct sk_buff *nskb;
- int type;
-
- /* indicate frame to the stack, which will free the old skb. */
- type = _ath_rx_indicate(sc, skb, status, keyix);
-
- /* allocate a new skb and queue it to for H/W processing */
- nskb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize);
- if (nskb != NULL) {
- bf->bf_mpdu = nskb;
- bf->bf_buf_addr = pci_map_single(sc->pdev, nskb->data,
- sc->sc_rxbufsize,
- PCI_DMA_FROMDEVICE);
- bf->bf_dmacontext = bf->bf_buf_addr;
- ATH_RX_CONTEXT(nskb)->ctx_rxbuf = bf;
+ ratecode = ds->ds_rxstat.rs_rate;
+
+ if (ratecode & 0x80) {
+ /* HT rate */
+ rx_status->flag |= RX_FLAG_HT;
+ if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040)
+ rx_status->flag |= RX_FLAG_40MHZ;
+ if (ds->ds_rxstat.rs_flags & ATH9K_RX_GI)
+ rx_status->flag |= RX_FLAG_SHORT_GI;
+ rx_status->rate_idx = ratecode & 0x7f;
+ } else {
+ int i = 0, cur_band, n_rates;
+ struct ieee80211_hw *hw = sc->hw;
- /* queue the new wbuf to H/W */
- ath_rx_requeue(sc, nskb);
+ cur_band = hw->conf.channel->band;
+ n_rates = sc->sbands[cur_band].n_bitrates;
+
+ for (i = 0; i < n_rates; i++) {
+ if (sc->sbands[cur_band].bitrates[i].hw_value ==
+ ratecode) {
+ rx_status->rate_idx = i;
+ break;
+ }
+
+ if (sc->sbands[cur_band].bitrates[i].hw_value_short ==
+ ratecode) {
+ rx_status->rate_idx = i;
+ rx_status->flag |= RX_FLAG_SHORTPRE;
+ break;
+ }
+ }
}
- return type;
+ rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp);
+ rx_status->band = sc->hw->conf.channel->band;
+ rx_status->freq = sc->hw->conf.channel->center_freq;
+ rx_status->noise = sc->sc_ani.sc_noise_floor;
+ rx_status->signal = rx_status->noise + ds->ds_rxstat.rs_rssi;
+ rx_status->antenna = ds->ds_rxstat.rs_antenna;
+
+ /* at 45 you will be able to use MCS 15 reliably. A more elaborate
+ * scheme can be used here but it requires tables of SNR/throughput for
+ * each possible mode used. */
+ rx_status->qual = ds->ds_rxstat.rs_rssi * 100 / 45;
+
+ /* rssi can be more than 45 though, anything above that
+ * should be considered at 100% */
+ if (rx_status->qual > 100)
+ rx_status->qual = 100;
+
+ rx_status->flag |= RX_FLAG_TSFT;
+
+ return 1;
+rx_next:
+ return 0;
}
static void ath_opmode_init(struct ath_softc *sc)
@@ -498,11 +252,7 @@ static void ath_opmode_init(struct ath_softc *sc)
/* calculate and install multicast filter */
mfilt[0] = mfilt[1] = ~0;
-
ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]);
- DPRINTF(sc, ATH_DBG_CONFIG ,
- "%s: RX filter 0x%x, MC filter %08x:%08x\n",
- __func__, rfilt, mfilt[0], mfilt[1]);
}
int ath_rx_init(struct ath_softc *sc, int nbufs)
@@ -512,38 +262,29 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
int error = 0;
do {
- spin_lock_init(&sc->sc_rxflushlock);
+ spin_lock_init(&sc->rx.rxflushlock);
sc->sc_flags &= ~SC_OP_RXFLUSH;
- spin_lock_init(&sc->sc_rxbuflock);
+ spin_lock_init(&sc->rx.rxbuflock);
- /*
- * Cisco's VPN software requires that drivers be able to
- * receive encapsulated frames that are larger than the MTU.
- * Since we can't be sure how large a frame we'll get, setup
- * to handle the larges on possible.
- */
- sc->sc_rxbufsize = roundup(IEEE80211_MAX_MPDU_LEN,
+ sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
min(sc->sc_cachelsz,
(u16)64));
- DPRINTF(sc, ATH_DBG_CONFIG, "%s: cachelsz %u rxbufsize %u\n",
- __func__, sc->sc_cachelsz, sc->sc_rxbufsize);
+ DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
+ sc->sc_cachelsz, sc->rx.bufsize);
/* Initialize rx descriptors */
- error = ath_descdma_setup(sc, &sc->sc_rxdma, &sc->sc_rxbuf,
+ error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf,
"rx", nbufs, 1);
if (error != 0) {
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: failed to allocate rx descriptors: %d\n",
- __func__, error);
+ "failed to allocate rx descriptors: %d\n", error);
break;
}
- /* Pre-allocate a wbuf for each rx buffer */
-
- list_for_each_entry(bf, &sc->sc_rxbuf, list) {
- skb = ath_rxbuf_alloc(sc, sc->sc_rxbufsize);
+ list_for_each_entry(bf, &sc->rx.rxbuf, list) {
+ skb = ath_rxbuf_alloc(sc, sc->rx.bufsize);
if (skb == NULL) {
error = -ENOMEM;
break;
@@ -551,12 +292,20 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
bf->bf_mpdu = skb;
bf->bf_buf_addr = pci_map_single(sc->pdev, skb->data,
- sc->sc_rxbufsize,
- PCI_DMA_FROMDEVICE);
+ sc->rx.bufsize,
+ PCI_DMA_FROMDEVICE);
+ if (unlikely(pci_dma_mapping_error(sc->pdev,
+ bf->bf_buf_addr))) {
+ dev_kfree_skb_any(skb);
+ bf->bf_mpdu = NULL;
+ DPRINTF(sc, ATH_DBG_CONFIG,
+ "pci_dma_mapping_error() on RX init\n");
+ error = -ENOMEM;
+ break;
+ }
bf->bf_dmacontext = bf->bf_buf_addr;
- ATH_RX_CONTEXT(skb)->ctx_rxbuf = bf;
}
- sc->sc_rxlink = NULL;
+ sc->rx.rxlink = NULL;
} while (0);
@@ -566,23 +315,19 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
return error;
}
-/* Reclaim all rx queue resources */
-
void ath_rx_cleanup(struct ath_softc *sc)
{
struct sk_buff *skb;
struct ath_buf *bf;
- list_for_each_entry(bf, &sc->sc_rxbuf, list) {
+ list_for_each_entry(bf, &sc->rx.rxbuf, list) {
skb = bf->bf_mpdu;
if (skb)
dev_kfree_skb(skb);
}
- /* cleanup rx descriptors */
-
- if (sc->sc_rxdma.dd_desc_len != 0)
- ath_descdma_cleanup(sc, &sc->sc_rxdma, &sc->sc_rxbuf);
+ if (sc->rx.rxdma.dd_desc_len != 0)
+ ath_descdma_cleanup(sc, &sc->rx.rxdma, &sc->rx.rxbuf);
}
/*
@@ -615,201 +360,115 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
| ATH9K_RX_FILTER_MCAST;
/* If not a STA, enable processing of Probe Requests */
- if (sc->sc_ah->ah_opmode != ATH9K_M_STA)
+ if (sc->sc_ah->ah_opmode != NL80211_IFTYPE_STATION)
rfilt |= ATH9K_RX_FILTER_PROBEREQ;
/* Can't set HOSTAP into promiscous mode */
- if (((sc->sc_ah->ah_opmode != ATH9K_M_HOSTAP) &&
- (sc->rx_filter & FIF_PROMISC_IN_BSS)) ||
- (sc->sc_ah->ah_opmode == ATH9K_M_MONITOR)) {
+ if (((sc->sc_ah->ah_opmode != NL80211_IFTYPE_AP) &&
+ (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) ||
+ (sc->sc_ah->ah_opmode == NL80211_IFTYPE_MONITOR)) {
rfilt |= ATH9K_RX_FILTER_PROM;
/* ??? To prevent from sending ACK */
rfilt &= ~ATH9K_RX_FILTER_UCAST;
}
- if (((sc->sc_ah->ah_opmode == ATH9K_M_STA) &&
- (sc->rx_filter & FIF_BCN_PRBRESP_PROMISC)) ||
- (sc->sc_ah->ah_opmode == ATH9K_M_IBSS))
+ if (sc->sc_ah->ah_opmode == NL80211_IFTYPE_STATION ||
+ sc->sc_ah->ah_opmode == NL80211_IFTYPE_ADHOC)
rfilt |= ATH9K_RX_FILTER_BEACON;
/* If in HOSTAP mode, want to enable reception of PSPOLL frames
& beacon frames */
- if (sc->sc_ah->ah_opmode == ATH9K_M_HOSTAP)
+ if (sc->sc_ah->ah_opmode == NL80211_IFTYPE_AP)
rfilt |= (ATH9K_RX_FILTER_BEACON | ATH9K_RX_FILTER_PSPOLL);
+
return rfilt;
#undef RX_FILTER_PRESERVE
}
-/* Enable the receive h/w following a reset. */
-
int ath_startrecv(struct ath_softc *sc)
{
struct ath_hal *ah = sc->sc_ah;
struct ath_buf *bf, *tbf;
- spin_lock_bh(&sc->sc_rxbuflock);
- if (list_empty(&sc->sc_rxbuf))
+ spin_lock_bh(&sc->rx.rxbuflock);
+ if (list_empty(&sc->rx.rxbuf))
goto start_recv;
- sc->sc_rxlink = NULL;
- list_for_each_entry_safe(bf, tbf, &sc->sc_rxbuf, list) {
- if (bf->bf_status & ATH_BUFSTATUS_STALE) {
- /* restarting h/w, no need for holding descriptors */
- bf->bf_status &= ~ATH_BUFSTATUS_STALE;
- /*
- * Upper layer may not be done with the frame yet so
- * we can't just re-queue it to hardware. Remove it
- * from h/w queue. It'll be re-queued when upper layer
- * returns the frame and ath_rx_requeue_mpdu is called.
- */
- if (!(bf->bf_status & ATH_BUFSTATUS_FREE)) {
- list_del(&bf->list);
- continue;
- }
- }
- /* chain descriptors */
+ sc->rx.rxlink = NULL;
+ list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
ath_rx_buf_link(sc, bf);
}
/* We could have deleted elements so the list may be empty now */
- if (list_empty(&sc->sc_rxbuf))
+ if (list_empty(&sc->rx.rxbuf))
goto start_recv;
- bf = list_first_entry(&sc->sc_rxbuf, struct ath_buf, list);
+ bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
ath9k_hw_putrxbuf(ah, bf->bf_daddr);
- ath9k_hw_rxena(ah); /* enable recv descriptors */
+ ath9k_hw_rxena(ah);
start_recv:
- spin_unlock_bh(&sc->sc_rxbuflock);
- ath_opmode_init(sc); /* set filters, etc. */
- ath9k_hw_startpcureceive(ah); /* re-enable PCU/DMA engine */
+ spin_unlock_bh(&sc->rx.rxbuflock);
+ ath_opmode_init(sc);
+ ath9k_hw_startpcureceive(ah);
+
return 0;
}
-/* Disable the receive h/w in preparation for a reset. */
-
bool ath_stoprecv(struct ath_softc *sc)
{
struct ath_hal *ah = sc->sc_ah;
- u64 tsf;
bool stopped;
- ath9k_hw_stoppcurecv(ah); /* disable PCU */
- ath9k_hw_setrxfilter(ah, 0); /* clear recv filter */
- stopped = ath9k_hw_stopdmarecv(ah); /* disable DMA engine */
- mdelay(3); /* 3ms is long enough for 1 frame */
- tsf = ath9k_hw_gettsf64(ah);
- sc->sc_rxlink = NULL; /* just in case */
+ ath9k_hw_stoppcurecv(ah);
+ ath9k_hw_setrxfilter(ah, 0);
+ stopped = ath9k_hw_stopdmarecv(ah);
+ mdelay(3); /* 3ms is long enough for 1 frame */
+ sc->rx.rxlink = NULL;
+
return stopped;
}
-/* Flush receive queue */
-
void ath_flushrecv(struct ath_softc *sc)
{
- /*
- * ath_rx_tasklet may be used to handle rx interrupt and flush receive
- * queue at the same time. Use a lock to serialize the access of rx
- * queue.
- * ath_rx_tasklet cannot hold the spinlock while indicating packets.
- * Instead, do not claim the spinlock but check for a flush in
- * progress (see references to sc_rxflush)
- */
- spin_lock_bh(&sc->sc_rxflushlock);
+ spin_lock_bh(&sc->rx.rxflushlock);
sc->sc_flags |= SC_OP_RXFLUSH;
-
ath_rx_tasklet(sc, 1);
-
sc->sc_flags &= ~SC_OP_RXFLUSH;
- spin_unlock_bh(&sc->sc_rxflushlock);
+ spin_unlock_bh(&sc->rx.rxflushlock);
}
-/* Process an individual frame */
-
-int ath_rx_input(struct ath_softc *sc,
- struct ath_node *an,
- int is_ampdu,
- struct sk_buff *skb,
- struct ath_recv_status *rx_status,
- enum ATH_RX_TYPE *status)
-{
- if (is_ampdu && (sc->sc_flags & SC_OP_RXAGGR)) {
- *status = ATH_RX_CONSUMED;
- return ath_ampdu_input(sc, an, skb, rx_status);
- } else {
- *status = ATH_RX_NON_CONSUMED;
- return -1;
- }
-}
-
-/* Process receive queue, as well as LED, etc. */
-
int ath_rx_tasklet(struct ath_softc *sc, int flush)
{
#define PA2DESC(_sc, _pa) \
- ((struct ath_desc *)((caddr_t)(_sc)->sc_rxdma.dd_desc + \
- ((_pa) - (_sc)->sc_rxdma.dd_desc_paddr)))
+ ((struct ath_desc *)((caddr_t)(_sc)->rx.rxdma.dd_desc + \
+ ((_pa) - (_sc)->rx.rxdma.dd_desc_paddr)))
- struct ath_buf *bf, *bf_held = NULL;
+ struct ath_buf *bf;
struct ath_desc *ds;
- struct ieee80211_hdr *hdr;
- struct sk_buff *skb = NULL;
- struct ath_recv_status rx_status;
+ struct sk_buff *skb = NULL, *requeue_skb;
+ struct ieee80211_rx_status rx_status;
struct ath_hal *ah = sc->sc_ah;
- int type, rx_processed = 0;
- u32 phyerr;
- u8 chainreset = 0;
- int retval;
- __le16 fc;
+ struct ieee80211_hdr *hdr;
+ int hdrlen, padsize, retval;
+ bool decrypt_error = false;
+ u8 keyix;
+
+ spin_lock_bh(&sc->rx.rxbuflock);
do {
/* If handling rx interrupt and flush is in progress => exit */
if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0))
break;
- spin_lock_bh(&sc->sc_rxbuflock);
- if (list_empty(&sc->sc_rxbuf)) {
- sc->sc_rxlink = NULL;
- spin_unlock_bh(&sc->sc_rxbuflock);
+ if (list_empty(&sc->rx.rxbuf)) {
+ sc->rx.rxlink = NULL;
break;
}
- bf = list_first_entry(&sc->sc_rxbuf, struct ath_buf, list);
-
- /*
- * There is a race condition that BH gets scheduled after sw
- * writes RxE and before hw re-load the last descriptor to get
- * the newly chained one. Software must keep the last DONE
- * descriptor as a holding descriptor - software does so by
- * marking it with the STALE flag.
- */
- if (bf->bf_status & ATH_BUFSTATUS_STALE) {
- bf_held = bf;
- if (list_is_last(&bf_held->list, &sc->sc_rxbuf)) {
- /*
- * The holding descriptor is the last
- * descriptor in queue. It's safe to
- * remove the last holding descriptor
- * in BH context.
- */
- list_del(&bf_held->list);
- bf_held->bf_status &= ~ATH_BUFSTATUS_STALE;
- sc->sc_rxlink = NULL;
-
- if (bf_held->bf_status & ATH_BUFSTATUS_FREE) {
- list_add_tail(&bf_held->list,
- &sc->sc_rxbuf);
- ath_rx_buf_link(sc, bf_held);
- }
- spin_unlock_bh(&sc->sc_rxbuflock);
- break;
- }
- bf = list_entry(bf->list.next, struct ath_buf, list);
- }
-
+ bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list);
ds = bf->bf_desc;
- ++rx_processed;
/*
* Must provide the virtual address of the current
@@ -822,8 +481,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
* on. All this is necessary because of our use of
* a self-linked list to avoid rx overruns.
*/
- retval = ath9k_hw_rxprocdesc(ah,
- ds,
+ retval = ath9k_hw_rxprocdesc(ah, ds,
bf->bf_daddr,
PA2DESC(sc, ds->ds_link),
0);
@@ -831,8 +489,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
struct ath_buf *tbf;
struct ath_desc *tds;
- if (list_is_last(&bf->list, &sc->sc_rxbuf)) {
- spin_unlock_bh(&sc->sc_rxbuflock);
+ if (list_is_last(&bf->list, &sc->rx.rxbuf)) {
+ sc->rx.rxlink = NULL;
break;
}
@@ -850,451 +508,127 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
*/
tds = tbf->bf_desc;
- retval = ath9k_hw_rxprocdesc(ah,
- tds, tbf->bf_daddr,
- PA2DESC(sc, tds->ds_link), 0);
+ retval = ath9k_hw_rxprocdesc(ah, tds, tbf->bf_daddr,
+ PA2DESC(sc, tds->ds_link), 0);
if (retval == -EINPROGRESS) {
- spin_unlock_bh(&sc->sc_rxbuflock);
break;
}
}
- /* XXX: we do not support frames spanning
- * multiple descriptors */
- bf->bf_status |= ATH_BUFSTATUS_DONE;
-
skb = bf->bf_mpdu;
- if (skb == NULL) { /* XXX ??? can this happen */
- spin_unlock_bh(&sc->sc_rxbuflock);
+ if (!skb)
continue;
- }
+
/*
- * Now we know it's a completed frame, we can indicate the
- * frame. Remove the previous holding descriptor and leave
- * this one in the queue as the new holding descriptor.
+ * Synchronize the DMA transfer with CPU before
+ * 1. accessing the frame
+ * 2. requeueing the same buffer to h/w
*/
- if (bf_held) {
- list_del(&bf_held->list);
- bf_held->bf_status &= ~ATH_BUFSTATUS_STALE;
- if (bf_held->bf_status & ATH_BUFSTATUS_FREE) {
- list_add_tail(&bf_held->list, &sc->sc_rxbuf);
- /* try to requeue this descriptor */
- ath_rx_buf_link(sc, bf_held);
- }
- }
+ pci_dma_sync_single_for_cpu(sc->pdev, bf->bf_buf_addr,
+ sc->rx.bufsize,
+ PCI_DMA_FROMDEVICE);
- bf->bf_status |= ATH_BUFSTATUS_STALE;
- bf_held = bf;
/*
- * Release the lock here in case ieee80211_input() return
- * the frame immediately by calling ath_rx_mpdu_requeue().
+ * If we're asked to flush receive queue, directly
+ * chain it back at the queue without processing it.
*/
- spin_unlock_bh(&sc->sc_rxbuflock);
+ if (flush)
+ goto requeue;
- if (flush) {
- /*
- * If we're asked to flush receive queue, directly
- * chain it back at the queue without processing it.
- */
- goto rx_next;
- }
+ if (!ds->ds_rxstat.rs_datalen)
+ goto requeue;
- hdr = (struct ieee80211_hdr *)skb->data;
- fc = hdr->frame_control;
- memset(&rx_status, 0, sizeof(struct ath_recv_status));
+ /* The status portion of the descriptor could get corrupted. */
+ if (sc->rx.bufsize < ds->ds_rxstat.rs_datalen)
+ goto requeue;
- if (ds->ds_rxstat.rs_more) {
- /*
- * Frame spans multiple descriptors; this
- * cannot happen yet as we don't support
- * jumbograms. If not in monitor mode,
- * discard the frame.
- */
-#ifndef ERROR_FRAMES
- /*
- * Enable this if you want to see
- * error frames in Monitor mode.
- */
- if (sc->sc_ah->ah_opmode != ATH9K_M_MONITOR)
- goto rx_next;
-#endif
- /* fall thru for monitor mode handling... */
- } else if (ds->ds_rxstat.rs_status != 0) {
- if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC)
- rx_status.flags |= ATH_RX_FCS_ERROR;
- if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY) {
- phyerr = ds->ds_rxstat.rs_phyerr & 0x1f;
- goto rx_next;
- }
+ if (!ath_rx_prepare(skb, ds, &rx_status, &decrypt_error, sc))
+ goto requeue;
+
+ /* Ensure we always have an skb to requeue once we are done
+ * processing the current buffer's skb */
+ requeue_skb = ath_rxbuf_alloc(sc, sc->rx.bufsize);
+
+ /* If there is no memory we ignore the current RX'd frame,
+ * tell hardware it can give us a new frame using the old
+ * skb and put it at the tail of the sc->rx.rxbuf list for
+ * processing. */
+ if (!requeue_skb)
+ goto requeue;
+
+ /* Unmap the frame */
+ pci_unmap_single(sc->pdev, bf->bf_buf_addr,
+ sc->rx.bufsize,
+ PCI_DMA_FROMDEVICE);
- if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) {
- /*
- * Decrypt error. We only mark packet status
- * here and always push up the frame up to let
- * mac80211 handle the actual error case, be
- * it no decryption key or real decryption
- * error. This let us keep statistics there.
- */
- rx_status.flags |= ATH_RX_DECRYPT_ERROR;
- } else if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) {
- /*
- * Demic error. We only mark frame status here
- * and always push up the frame up to let
- * mac80211 handle the actual error case. This
- * let us keep statistics there. Hardware may
- * post a false-positive MIC error.
- */
- if (ieee80211_is_ctl(fc))
- /*
- * Sometimes, we get invalid
- * MIC failures on valid control frames.
- * Remove these mic errors.
- */
- ds->ds_rxstat.rs_status &=
- ~ATH9K_RXERR_MIC;
- else
- rx_status.flags |= ATH_RX_MIC_ERROR;
- }
- /*
- * Reject error frames with the exception of
- * decryption and MIC failures. For monitor mode,
- * we also ignore the CRC error.
- */
- if (sc->sc_ah->ah_opmode == ATH9K_M_MONITOR) {
- if (ds->ds_rxstat.rs_status &
- ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
- ATH9K_RXERR_CRC))
- goto rx_next;
- } else {
- if (ds->ds_rxstat.rs_status &
- ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
- goto rx_next;
- }
- }
- }
- /*
- * The status portion of the descriptor could get corrupted.
- */
- if (sc->sc_rxbufsize < ds->ds_rxstat.rs_datalen)
- goto rx_next;
- /*
- * Sync and unmap the frame. At this point we're
- * committed to passing the sk_buff somewhere so
- * clear buf_skb; this means a new sk_buff must be
- * allocated when the rx descriptor is setup again
- * to receive another frame.
- */
skb_put(skb, ds->ds_rxstat.rs_datalen);
skb->protocol = cpu_to_be16(ETH_P_CONTROL);
- rx_status.tsf = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp);
- rx_status.rateieee =
- sc->sc_hwmap[ds->ds_rxstat.rs_rate].ieeerate;
- rx_status.rateKbps =
- sc->sc_hwmap[ds->ds_rxstat.rs_rate].rateKbps;
- rx_status.ratecode = ds->ds_rxstat.rs_rate;
- /* HT rate */
- if (rx_status.ratecode & 0x80) {
- /* TODO - add table to avoid division */
- if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040) {
- rx_status.flags |= ATH_RX_40MHZ;
- rx_status.rateKbps =
- (rx_status.rateKbps * 27) / 13;
- }
- if (ds->ds_rxstat.rs_flags & ATH9K_RX_GI)
- rx_status.rateKbps =
- (rx_status.rateKbps * 10) / 9;
- else
- rx_status.flags |= ATH_RX_SHORT_GI;
+ /* see if any padding is done by the hw and remove it */
+ hdr = (struct ieee80211_hdr *)skb->data;
+ hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+
+ /* The MAC header is padded to have 32-bit boundary if the
+ * packet payload is non-zero. The general calculation for
+ * padsize would take into account odd header lengths:
+ * padsize = (4 - hdrlen % 4) % 4; However, since only
+ * even-length headers are used, padding can only be 0 or 2
+ * bytes and we can optimize this a bit. In addition, we must
+ * not try to remove padding from short control frames that do
+ * not have payload. */
+ padsize = hdrlen & 3;
+ if (padsize && hdrlen >= 24) {
+ memmove(skb->data + padsize, skb->data, hdrlen);
+ skb_pull(skb, padsize);
}
- /* sc_noise_floor is only available when the station
- attaches to an AP, so we use a default value
- if we are not yet attached. */
- rx_status.abs_rssi =
- ds->ds_rxstat.rs_rssi + sc->sc_ani.sc_noise_floor;
-
- pci_dma_sync_single_for_cpu(sc->pdev,
- bf->bf_buf_addr,
- sc->sc_rxbufsize,
- PCI_DMA_FROMDEVICE);
- pci_unmap_single(sc->pdev,
- bf->bf_buf_addr,
- sc->sc_rxbufsize,
- PCI_DMA_FROMDEVICE);
+ keyix = ds->ds_rxstat.rs_keyix;
- /* XXX: Ah! make me more readable, use a helper */
- if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) {
- if (ds->ds_rxstat.rs_moreaggr == 0) {
- rx_status.rssictl[0] =
- ds->ds_rxstat.rs_rssi_ctl0;
- rx_status.rssictl[1] =
- ds->ds_rxstat.rs_rssi_ctl1;
- rx_status.rssictl[2] =
- ds->ds_rxstat.rs_rssi_ctl2;
- rx_status.rssi = ds->ds_rxstat.rs_rssi;
- if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040) {
- rx_status.rssiextn[0] =
- ds->ds_rxstat.rs_rssi_ext0;
- rx_status.rssiextn[1] =
- ds->ds_rxstat.rs_rssi_ext1;
- rx_status.rssiextn[2] =
- ds->ds_rxstat.rs_rssi_ext2;
- rx_status.flags |=
- ATH_RX_RSSI_EXTN_VALID;
- }
- rx_status.flags |= ATH_RX_RSSI_VALID |
- ATH_RX_CHAIN_RSSI_VALID;
- }
- } else {
- /*
- * Need to insert the "combined" rssi into the
- * status structure for upper layer processing
- */
- rx_status.rssi = ds->ds_rxstat.rs_rssi;
- rx_status.flags |= ATH_RX_RSSI_VALID;
+ if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) {
+ rx_status.flag |= RX_FLAG_DECRYPTED;
+ } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED)
+ && !decrypt_error && skb->len >= hdrlen + 4) {
+ keyix = skb->data[hdrlen + 3] >> 6;
+
+ if (test_bit(keyix, sc->sc_keymap))
+ rx_status.flag |= RX_FLAG_DECRYPTED;
}
- /* Pass frames up to the stack. */
+ /* Send the frame to mac80211 */
+ __ieee80211_rx(sc->hw, skb, &rx_status);
- type = ath_rx_indicate(sc, skb,
- &rx_status, ds->ds_rxstat.rs_keyix);
+ /* We will now give hardware our shiny new allocated skb */
+ bf->bf_mpdu = requeue_skb;
+ bf->bf_buf_addr = pci_map_single(sc->pdev, requeue_skb->data,
+ sc->rx.bufsize,
+ PCI_DMA_FROMDEVICE);
+ if (unlikely(pci_dma_mapping_error(sc->pdev,
+ bf->bf_buf_addr))) {
+ dev_kfree_skb_any(requeue_skb);
+ bf->bf_mpdu = NULL;
+ DPRINTF(sc, ATH_DBG_CONFIG,
+ "pci_dma_mapping_error() on RX\n");
+ break;
+ }
+ bf->bf_dmacontext = bf->bf_buf_addr;
/*
* change the default rx antenna if rx diversity chooses the
* other antenna 3 times in a row.
*/
- if (sc->sc_defant != ds->ds_rxstat.rs_antenna) {
- if (++sc->sc_rxotherant >= 3)
- ath_setdefantenna(sc,
- ds->ds_rxstat.rs_antenna);
+ if (sc->rx.defant != ds->ds_rxstat.rs_antenna) {
+ if (++sc->rx.rxotherant >= 3)
+ ath_setdefantenna(sc, ds->ds_rxstat.rs_antenna);
} else {
- sc->sc_rxotherant = 0;
+ sc->rx.rxotherant = 0;
}
+requeue:
+ list_move_tail(&bf->list, &sc->rx.rxbuf);
+ ath_rx_buf_link(sc, bf);
+ } while (1);
-#ifdef CONFIG_SLOW_ANT_DIV
- if ((rx_status.flags & ATH_RX_RSSI_VALID) &&
- ieee80211_is_beacon(fc)) {
- ath_slow_ant_div(&sc->sc_antdiv, hdr, &ds->ds_rxstat);
- }
-#endif
- /*
- * For frames successfully indicated, the buffer will be
- * returned to us by upper layers by calling
- * ath_rx_mpdu_requeue, either synchronusly or asynchronously.
- * So we don't want to do it here in this loop.
- */
- continue;
-
-rx_next:
- bf->bf_status |= ATH_BUFSTATUS_FREE;
- } while (TRUE);
-
- if (chainreset) {
- DPRINTF(sc, ATH_DBG_CONFIG,
- "%s: Reset rx chain mask. "
- "Do internal reset\n", __func__);
- ASSERT(flush == 0);
- ath_reset(sc, false);
- }
+ spin_unlock_bh(&sc->rx.rxbuflock);
return 0;
#undef PA2DESC
}
-
-/* Process ADDBA request in per-TID data structure */
-
-int ath_rx_aggr_start(struct ath_softc *sc,
- const u8 *addr,
- u16 tid,
- u16 *ssn)
-{
- struct ath_arx_tid *rxtid;
- struct ath_node *an;
- struct ieee80211_hw *hw = sc->hw;
- struct ieee80211_supported_band *sband;
- u16 buffersize = 0;
-
- spin_lock_bh(&sc->node_lock);
- an = ath_node_find(sc, (u8 *) addr);
- spin_unlock_bh(&sc->node_lock);
-
- if (!an) {
- DPRINTF(sc, ATH_DBG_AGGR,
- "%s: Node not found to initialize RX aggregation\n",
- __func__);
- return -1;
- }
-
- sband = hw->wiphy->bands[hw->conf.channel->band];
- buffersize = IEEE80211_MIN_AMPDU_BUF <<
- sband->ht_info.ampdu_factor; /* FIXME */
-
- rxtid = &an->an_aggr.rx.tid[tid];
-
- spin_lock_bh(&rxtid->tidlock);
- if (sc->sc_flags & SC_OP_RXAGGR) {
- /* Allow aggregation reception
- * Adjust rx BA window size. Peer might indicate a
- * zero buffer size for a _dont_care_ condition.
- */
- if (buffersize)
- rxtid->baw_size = min(buffersize, rxtid->baw_size);
-
- /* set rx sequence number */
- rxtid->seq_next = *ssn;
-
- /* Allocate the receive buffers for this TID */
- DPRINTF(sc, ATH_DBG_AGGR,
- "%s: Allcating rxbuffer for TID %d\n", __func__, tid);
-
- if (rxtid->rxbuf == NULL) {
- /*
- * If the rxbuff is not NULL at this point, we *probably*
- * already allocated the buffer on a previous ADDBA,
- * and this is a subsequent ADDBA that got through.
- * Don't allocate, but use the value in the pointer,
- * we zero it out when we de-allocate.
- */
- rxtid->rxbuf = kmalloc(ATH_TID_MAX_BUFS *
- sizeof(struct ath_rxbuf), GFP_ATOMIC);
- }
- if (rxtid->rxbuf == NULL) {
- DPRINTF(sc, ATH_DBG_AGGR,
- "%s: Unable to allocate RX buffer, "
- "refusing ADDBA\n", __func__);
- } else {
- /* Ensure the memory is zeroed out (all internal
- * pointers are null) */
- memset(rxtid->rxbuf, 0, ATH_TID_MAX_BUFS *
- sizeof(struct ath_rxbuf));
- DPRINTF(sc, ATH_DBG_AGGR,
- "%s: Allocated @%p\n", __func__, rxtid->rxbuf);
-
- /* Allow aggregation reception */
- rxtid->addba_exchangecomplete = 1;
- }
- }
- spin_unlock_bh(&rxtid->tidlock);
-
- return 0;
-}
-
-/* Process DELBA */
-
-int ath_rx_aggr_stop(struct ath_softc *sc,
- const u8 *addr,
- u16 tid)
-{
- struct ath_node *an;
-
- spin_lock_bh(&sc->node_lock);
- an = ath_node_find(sc, (u8 *) addr);
- spin_unlock_bh(&sc->node_lock);
-
- if (!an) {
- DPRINTF(sc, ATH_DBG_AGGR,
- "%s: RX aggr stop for non-existent node\n", __func__);
- return -1;
- }
-
- ath_rx_aggr_teardown(sc, an, tid);
- return 0;
-}
-
-/* Rx aggregation tear down */
-
-void ath_rx_aggr_teardown(struct ath_softc *sc,
- struct ath_node *an, u8 tid)
-{
- struct ath_arx_tid *rxtid = &an->an_aggr.rx.tid[tid];
-
- if (!rxtid->addba_exchangecomplete)
- return;
-
- del_timer_sync(&rxtid->timer);
- ath_rx_flush_tid(sc, rxtid, 0);
- rxtid->addba_exchangecomplete = 0;
-
- /* De-allocate the receive buffer array allocated when addba started */
-
- if (rxtid->rxbuf) {
- DPRINTF(sc, ATH_DBG_AGGR,
- "%s: Deallocating TID %d rxbuff @%p\n",
- __func__, tid, rxtid->rxbuf);
- kfree(rxtid->rxbuf);
-
- /* Set pointer to null to avoid reuse*/
- rxtid->rxbuf = NULL;
- }
-}
-
-/* Initialize per-node receive state */
-
-void ath_rx_node_init(struct ath_softc *sc, struct ath_node *an)
-{
- if (sc->sc_flags & SC_OP_RXAGGR) {
- struct ath_arx_tid *rxtid;
- int tidno;
-
- /* Init per tid rx state */
- for (tidno = 0, rxtid = &an->an_aggr.rx.tid[tidno];
- tidno < WME_NUM_TID;
- tidno++, rxtid++) {
- rxtid->an = an;
- rxtid->seq_reset = 1;
- rxtid->seq_next = 0;
- rxtid->baw_size = WME_MAX_BA;
- rxtid->baw_head = rxtid->baw_tail = 0;
-
- /*
- * Ensure the buffer pointer is null at this point
- * (needs to be allocated when addba is received)
- */
-
- rxtid->rxbuf = NULL;
- setup_timer(&rxtid->timer, ath_rx_timer,
- (unsigned long)rxtid);
- spin_lock_init(&rxtid->tidlock);
-
- /* ADDBA state */
- rxtid->addba_exchangecomplete = 0;
- }
- }
-}
-
-void ath_rx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
-{
- if (sc->sc_flags & SC_OP_RXAGGR) {
- struct ath_arx_tid *rxtid;
- int tidno, i;
-
- /* Init per tid rx state */
- for (tidno = 0, rxtid = &an->an_aggr.rx.tid[tidno];
- tidno < WME_NUM_TID;
- tidno++, rxtid++) {
-
- if (!rxtid->addba_exchangecomplete)
- continue;
-
- /* must cancel timer first */
- del_timer_sync(&rxtid->timer);
-
- /* drop any pending sub-frames */
- ath_rx_flush_tid(sc, rxtid, 1);
-
- for (i = 0; i < ATH_TID_MAX_BUFS; i++)
- ASSERT(rxtid->rxbuf[i].rx_wbuf == NULL);
-
- rxtid->addba_exchangecomplete = 0;
- }
- }
-
-}
-
-/* Cleanup per-node receive state */
-
-void ath_rx_node_free(struct ath_softc *sc, struct ath_node *an)
-{
- ath_rx_node_cleanup(sc, an);
-}
diff --git a/drivers/net/wireless/ath9k/reg.h b/drivers/net/wireless/ath9k/reg.h
index 60617ae66209..9fedb4911bc3 100644
--- a/drivers/net/wireless/ath9k/reg.h
+++ b/drivers/net/wireless/ath9k/reg.h
@@ -671,7 +671,11 @@
#define AR_RC_APB 0x00000002
#define AR_RC_HOSTIF 0x00000100
-#define AR_WA 0x4004
+#define AR_WA 0x4004
+#define AR9285_WA_DEFAULT 0x004a05cb
+#define AR9280_WA_DEFAULT 0x0040073f
+#define AR_WA_DEFAULT 0x0000073f
+
#define AR_PM_STATE 0x4008
#define AR_PM_STATE_PME_D3COLD_VAUX 0x00100000
@@ -738,6 +742,8 @@
#define AR_SREV_REVISION_9280_21 2
#define AR_SREV_VERSION_9285 0xC0
#define AR_SREV_REVISION_9285_10 0
+#define AR_SREV_REVISION_9285_11 1
+#define AR_SREV_REVISION_9285_12 2
#define AR_SREV_9100_OR_LATER(_ah) \
(((_ah)->ah_macVersion >= AR_SREV_VERSION_5416_PCIE))
@@ -768,6 +774,16 @@
#define AR_SREV_9285(_ah) (((_ah)->ah_macVersion == AR_SREV_VERSION_9285))
#define AR_SREV_9285_10_OR_LATER(_ah) \
(((_ah)->ah_macVersion >= AR_SREV_VERSION_9285))
+#define AR_SREV_9285_11(_ah) \
+ (AR_SREV_9280(ah) && ((_ah)->ah_macRev == AR_SREV_REVISION_9285_11))
+#define AR_SREV_9285_11_OR_LATER(_ah) \
+ (((_ah)->ah_macVersion > AR_SREV_VERSION_9285) || \
+ (AR_SREV_9285(ah) && ((_ah)->ah_macRev >= AR_SREV_REVISION_9285_11)))
+#define AR_SREV_9285_12(_ah) \
+ (AR_SREV_9280(ah) && ((_ah)->ah_macRev == AR_SREV_REVISION_9285_12))
+#define AR_SREV_9285_12_OR_LATER(_ah) \
+ (((_ah)->ah_macVersion > AR_SREV_VERSION_9285) || \
+ (AR_SREV_9285(ah) && ((_ah)->ah_macRev >= AR_SREV_REVISION_9285_12)))
#define AR_RADIO_SREV_MAJOR 0xf0
#define AR_RAD5133_SREV_MAJOR 0xc0
@@ -1017,6 +1033,97 @@ enum {
#define AR_AN_SYNTH9_REFDIVA 0xf8000000
#define AR_AN_SYNTH9_REFDIVA_S 27
+#define AR9285_AN_RF2G1 0x7820
+#define AR9285_AN_RF2G1_ENPACAL 0x00000800
+#define AR9285_AN_RF2G1_ENPACAL_S 11
+#define AR9285_AN_RF2G1_PDPADRV1 0x02000000
+#define AR9285_AN_RF2G1_PDPADRV1_S 25
+#define AR9285_AN_RF2G1_PDPADRV2 0x01000000
+#define AR9285_AN_RF2G1_PDPADRV2_S 24
+#define AR9285_AN_RF2G1_PDPAOUT 0x00800000
+#define AR9285_AN_RF2G1_PDPAOUT_S 23
+
+
+#define AR9285_AN_RF2G2 0x7824
+#define AR9285_AN_RF2G2_OFFCAL 0x00001000
+#define AR9285_AN_RF2G2_OFFCAL_S 12
+
+#define AR9285_AN_RF2G3 0x7828
+#define AR9285_AN_RF2G3_PDVCCOMP 0x02000000
+#define AR9285_AN_RF2G3_PDVCCOMP_S 25
+#define AR9285_AN_RF2G3_OB_0 0x00E00000
+#define AR9285_AN_RF2G3_OB_0_S 21
+#define AR9285_AN_RF2G3_OB_1 0x001C0000
+#define AR9285_AN_RF2G3_OB_1_S 18
+#define AR9285_AN_RF2G3_OB_2 0x00038000
+#define AR9285_AN_RF2G3_OB_2_S 15
+#define AR9285_AN_RF2G3_OB_3 0x00007000
+#define AR9285_AN_RF2G3_OB_3_S 12
+#define AR9285_AN_RF2G3_OB_4 0x00000E00
+#define AR9285_AN_RF2G3_OB_4_S 9
+
+#define AR9285_AN_RF2G3_DB1_0 0x000001C0
+#define AR9285_AN_RF2G3_DB1_0_S 6
+#define AR9285_AN_RF2G3_DB1_1 0x00000038
+#define AR9285_AN_RF2G3_DB1_1_S 3
+#define AR9285_AN_RF2G3_DB1_2 0x00000007
+#define AR9285_AN_RF2G3_DB1_2_S 0
+#define AR9285_AN_RF2G4 0x782C
+#define AR9285_AN_RF2G4_DB1_3 0xE0000000
+#define AR9285_AN_RF2G4_DB1_3_S 29
+#define AR9285_AN_RF2G4_DB1_4 0x1C000000
+#define AR9285_AN_RF2G4_DB1_4_S 26
+
+#define AR9285_AN_RF2G4_DB2_0 0x03800000
+#define AR9285_AN_RF2G4_DB2_0_S 23
+#define AR9285_AN_RF2G4_DB2_1 0x00700000
+#define AR9285_AN_RF2G4_DB2_1_S 20
+#define AR9285_AN_RF2G4_DB2_2 0x000E0000
+#define AR9285_AN_RF2G4_DB2_2_S 17
+#define AR9285_AN_RF2G4_DB2_3 0x0001C000
+#define AR9285_AN_RF2G4_DB2_3_S 14
+#define AR9285_AN_RF2G4_DB2_4 0x00003800
+#define AR9285_AN_RF2G4_DB2_4_S 11
+
+#define AR9285_AN_RF2G6 0x7834
+#define AR9285_AN_RF2G6_CCOMP 0x00007800
+#define AR9285_AN_RF2G6_CCOMP_S 11
+#define AR9285_AN_RF2G6_OFFS 0x03f00000
+#define AR9285_AN_RF2G6_OFFS_S 20
+
+#define AR9285_AN_RF2G7 0x7838
+#define AR9285_AN_RF2G7_PWDDB 0x00000002
+#define AR9285_AN_RF2G7_PWDDB_S 1
+#define AR9285_AN_RF2G7_PADRVGN2TAB0 0xE0000000
+#define AR9285_AN_RF2G7_PADRVGN2TAB0_S 29
+
+#define AR9285_AN_RF2G8 0x783C
+#define AR9285_AN_RF2G8_PADRVGN2TAB0 0x0001C000
+#define AR9285_AN_RF2G8_PADRVGN2TAB0_S 14
+
+
+#define AR9285_AN_RF2G9 0x7840
+#define AR9285_AN_RXTXBB1 0x7854
+#define AR9285_AN_RXTXBB1_PDRXTXBB1 0x00000020
+#define AR9285_AN_RXTXBB1_PDRXTXBB1_S 5
+#define AR9285_AN_RXTXBB1_PDV2I 0x00000080
+#define AR9285_AN_RXTXBB1_PDV2I_S 7
+#define AR9285_AN_RXTXBB1_PDDACIF 0x00000100
+#define AR9285_AN_RXTXBB1_PDDACIF_S 8
+#define AR9285_AN_RXTXBB1_SPARE9 0x00000001
+#define AR9285_AN_RXTXBB1_SPARE9_S 0
+
+#define AR9285_AN_TOP2 0x7868
+
+#define AR9285_AN_TOP3 0x786c
+#define AR9285_AN_TOP3_XPABIAS_LVL 0x0000000C
+#define AR9285_AN_TOP3_XPABIAS_LVL_S 2
+#define AR9285_AN_TOP3_PWDDAC 0x00800000
+#define AR9285_AN_TOP3_PWDDAC_S 23
+
+#define AR9285_AN_TOP4 0x7870
+#define AR9285_AN_TOP4_DEFAULT 0x10142c00
+
#define AR_STA_ID0 0x8000
#define AR_STA_ID1 0x8004
#define AR_STA_ID1_SADH_MASK 0x0000FFFF
diff --git a/drivers/net/wireless/ath9k/regd.c b/drivers/net/wireless/ath9k/regd.c
index 62e28887ccd3..64043e99facf 100644
--- a/drivers/net/wireless/ath9k/regd.c
+++ b/drivers/net/wireless/ath9k/regd.c
@@ -42,7 +42,7 @@ ath9k_regd_sort(void *a, u32 n, u32 size, ath_hal_cmp_t *cmp)
u8 *u = t - size;
if (cmp(u, t) <= 0)
break;
- swap(u, t, size);
+ swap_array(u, t, size);
}
}
@@ -78,8 +78,7 @@ static bool ath9k_regd_is_eeprom_valid(struct ath_hal *ah)
return true;
}
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: invalid regulatory domain/country code 0x%x\n",
- __func__, rd);
+ "invalid regulatory domain/country code 0x%x\n", rd);
return false;
}
@@ -107,13 +106,12 @@ static bool ath9k_regd_is_ccode_valid(struct ath_hal *ah,
return true;
rd = ath9k_regd_get_eepromRD(ah);
- DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "%s: EEPROM regdomain 0x%x\n",
- __func__, rd);
+ DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "EEPROM regdomain 0x%x\n", rd);
if (rd & COUNTRY_ERD_FLAG) {
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: EEPROM setting is country code %u\n",
- __func__, rd & ~COUNTRY_ERD_FLAG);
+ "EEPROM setting is country code %u\n",
+ rd & ~COUNTRY_ERD_FLAG);
return cc == (rd & ~COUNTRY_ERD_FLAG);
}
@@ -290,8 +288,7 @@ ath9k_regd_get_wmode_regdomain(struct ath_hal *ah, int regDmn,
}
if (!found) {
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: Failed to find reg domain pair %u\n",
- __func__, regDmn);
+ "Failed to find reg domain pair %u\n", regDmn);
return false;
}
if (!(channelFlag & CHANNEL_2GHZ)) {
@@ -307,8 +304,7 @@ ath9k_regd_get_wmode_regdomain(struct ath_hal *ah, int regDmn,
found = ath9k_regd_is_valid_reg_domain(regDmn, rd);
if (!found) {
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: Failed to find unitary reg domain %u\n",
- __func__, regDmn);
+ "Failed to find unitary reg domain %u\n", regDmn);
return false;
} else {
rd->pscan &= regPair->pscanMask;
@@ -430,30 +426,27 @@ ath9k_regd_add_channel(struct ath_hal *ah,
if (!(c_lo <= c && c <= c_hi)) {
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: c %u out of range [%u..%u]\n",
- __func__, c, c_lo, c_hi);
+ "c %u out of range [%u..%u]\n",
+ c, c_lo, c_hi);
return false;
}
if ((fband->channelBW == CHANNEL_HALF_BW) &&
!(ah->ah_caps.hw_caps & ATH9K_HW_CAP_CHAN_HALFRATE)) {
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: Skipping %u half rate channel\n",
- __func__, c);
+ "Skipping %u half rate channel\n", c);
return false;
}
if ((fband->channelBW == CHANNEL_QUARTER_BW) &&
!(ah->ah_caps.hw_caps & ATH9K_HW_CAP_CHAN_QUARTERRATE)) {
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: Skipping %u quarter rate channel\n",
- __func__, c);
+ "Skipping %u quarter rate channel\n", c);
return false;
}
if (((c + fband->channelSep) / 2) > (maxChan + HALF_MAXCHANBW)) {
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: c %u > maxChan %u\n",
- __func__, c, maxChan);
+ "c %u > maxChan %u\n", c, maxChan);
return false;
}
@@ -463,7 +456,7 @@ ath9k_regd_add_channel(struct ath_hal *ah,
return false;
}
- if ((rd->flags & NO_HOSTAP) && (ah->ah_opmode == ATH9K_M_HOSTAP)) {
+ if ((rd->flags & NO_HOSTAP) && (ah->ah_opmode == NL80211_IFTYPE_AP)) {
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
"Skipping HOSTAP channel\n");
return false;
@@ -606,8 +599,7 @@ static bool ath9k_regd_japan_check(struct ath_hal *ah,
}
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: Skipping %d freq band\n",
- __func__, j_bandcheck[i].freqbandbit);
+ "Skipping %d freq band\n", j_bandcheck[i].freqbandbit);
return skipband;
}
@@ -632,20 +624,19 @@ ath9k_regd_init_channels(struct ath_hal *ah,
unsigned long *modes_avail;
DECLARE_BITMAP(modes_allowed, ATH9K_MODE_MAX);
- DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "%s: cc %u %s %s\n",
- __func__, cc,
+ DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "cc %u %s %s\n", cc,
enableOutdoor ? "Enable outdoor" : "",
enableExtendedChannels ? "Enable ecm" : "");
if (!ath9k_regd_is_ccode_valid(ah, cc)) {
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: invalid country code %d\n", __func__, cc);
+ "Invalid country code %d\n", cc);
return false;
}
if (!ath9k_regd_is_eeprom_valid(ah)) {
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: invalid EEPROM contents\n", __func__);
+ "Invalid EEPROM contents\n");
return false;
}
@@ -693,9 +684,9 @@ ath9k_regd_init_channels(struct ath_hal *ah,
~CHANNEL_2GHZ,
&rd5GHz)) {
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: couldn't find unitary "
+ "Couldn't find unitary "
"5GHz reg domain for country %u\n",
- __func__, ah->ah_countryCode);
+ ah->ah_countryCode);
return false;
}
if (!ath9k_regd_get_wmode_regdomain(ah,
@@ -703,9 +694,9 @@ ath9k_regd_init_channels(struct ath_hal *ah,
CHANNEL_2GHZ,
&rd2GHz)) {
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: couldn't find unitary 2GHz "
+ "Couldn't find unitary 2GHz "
"reg domain for country %u\n",
- __func__, ah->ah_countryCode);
+ ah->ah_countryCode);
return false;
}
@@ -717,9 +708,9 @@ ath9k_regd_init_channels(struct ath_hal *ah,
~CHANNEL_2GHZ,
&rd5GHz)) {
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: couldn't find unitary 5GHz "
+ "Couldn't find unitary 5GHz "
"reg domain for country %u\n",
- __func__, ah->ah_countryCode);
+ ah->ah_countryCode);
return false;
}
}
@@ -749,15 +740,14 @@ ath9k_regd_init_channels(struct ath_hal *ah,
if (!test_bit(cm->mode, modes_avail)) {
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: !avail mode %d flags 0x%x\n",
- __func__, cm->mode, cm->flags);
+ "!avail mode %d flags 0x%x\n",
+ cm->mode, cm->flags);
continue;
}
if (!ath9k_get_channel_edges(ah, cm->flags, &c_lo, &c_hi)) {
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: channels 0x%x not supported "
- "by hardware\n",
- __func__, cm->flags);
+ "channels 0x%x not supported "
+ "by hardware\n", cm->flags);
continue;
}
@@ -788,8 +778,7 @@ ath9k_regd_init_channels(struct ath_hal *ah,
break;
default:
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: Unknown HAL mode 0x%x\n", __func__,
- cm->mode);
+ "Unknown HAL mode 0x%x\n", cm->mode);
continue;
}
@@ -841,9 +830,8 @@ ath9k_regd_init_channels(struct ath_hal *ah,
if (next >= maxchans) {
DPRINTF(ah->ah_sc,
ATH_DBG_REGULATORY,
- "%s: too many channels "
- "for channel table\n",
- __func__);
+ "too many channels "
+ "for channel table\n");
goto done;
}
if (ath9k_regd_add_channel(ah,
@@ -869,9 +857,8 @@ done:
if (next > ARRAY_SIZE(ah->ah_channels)) {
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: too many channels %u; truncating to %u\n",
- __func__, next,
- (int) ARRAY_SIZE(ah->ah_channels));
+ "too many channels %u; truncating to %u\n",
+ next, (int) ARRAY_SIZE(ah->ah_channels));
next = ARRAY_SIZE(ah->ah_channels);
}
#ifdef ATH_NF_PER_CHAN
@@ -919,7 +906,7 @@ ath9k_regd_check_channel(struct ath_hal *ah,
int n, lim;
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: channel %u/0x%x (0x%x) requested\n", __func__,
+ "channel %u/0x%x (0x%x) requested\n",
c->channel, c->channelFlags, flags);
cc = ah->ah_curchan;
@@ -950,15 +937,15 @@ ath9k_regd_check_channel(struct ath_hal *ah,
d = flags - (cc->channelFlags & CHAN_FLAGS);
}
DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY,
- "%s: channel %u/0x%x d %d\n", __func__,
+ "channel %u/0x%x d %d\n",
cc->channel, cc->channelFlags, d);
if (d > 0) {
base = cc + 1;
lim--;
}
}
- DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "%s: no match for %u/0x%x\n",
- __func__, c->channel, c->channelFlags);
+ DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, "no match for %u/0x%x\n",
+ c->channel, c->channelFlags);
return NULL;
}
diff --git a/drivers/net/wireless/ath9k/regd.h b/drivers/net/wireless/ath9k/regd.h
index 0ecd344fbd98..512d990aa7ea 100644
--- a/drivers/net/wireless/ath9k/regd.h
+++ b/drivers/net/wireless/ath9k/regd.h
@@ -125,7 +125,7 @@
#define CHAN_FLAGS (CHANNEL_ALL|CHANNEL_HALF|CHANNEL_QUARTER)
-#define swap(_a, _b, _size) { \
+#define swap_array(_a, _b, _size) { \
u8 *s = _b; \
int i = _size; \
do { \
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c
index 3a4757942b3f..3bfc3b90f256 100644
--- a/drivers/net/wireless/ath9k/xmit.c
+++ b/drivers/net/wireless/ath9k/xmit.c
@@ -14,10 +14,6 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/*
- * Implementation of transmit path.
- */
-
#include "core.h"
#define BITS_PER_BYTE 8
@@ -65,11 +61,12 @@ static u32 bits_per_symbol[][2] = {
* NB: must be called with txq lock held
*/
-static void ath_tx_txqaddbuf(struct ath_softc *sc,
- struct ath_txq *txq, struct list_head *head)
+static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
+ struct list_head *head)
{
struct ath_hal *ah = sc->sc_ah;
struct ath_buf *bf;
+
/*
* Insert the frame on the outbound list and
* pass it on to the hardware.
@@ -86,18 +83,16 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc,
txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list);
DPRINTF(sc, ATH_DBG_QUEUE,
- "%s: txq depth = %d\n", __func__, txq->axq_depth);
+ "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth);
if (txq->axq_link == NULL) {
ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
DPRINTF(sc, ATH_DBG_XMIT,
- "%s: TXDP[%u] = %llx (%p)\n",
- __func__, txq->axq_qnum,
- ito64(bf->bf_daddr), bf->bf_desc);
+ "TXDP[%u] = %llx (%p)\n",
+ txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
} else {
*txq->axq_link = bf->bf_daddr;
- DPRINTF(sc, ATH_DBG_XMIT, "%s: link[%u] (%p)=%llx (%p)\n",
- __func__,
+ DPRINTF(sc, ATH_DBG_XMIT, "link[%u] (%p)=%llx (%p)\n",
txq->axq_qnum, txq->axq_link,
ito64(bf->bf_daddr), bf->bf_desc);
}
@@ -105,46 +100,94 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc,
ath9k_hw_txstart(ah, txq->axq_qnum);
}
-/* Get transmit rate index using rate in Kbps */
-
-static int ath_tx_findindex(const struct ath9k_rate_table *rt, int rate)
+static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
+ struct ath_xmit_status *tx_status)
{
- int i;
- int ndx = 0;
+ struct ieee80211_hw *hw = sc->hw;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+ struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
+ int hdrlen, padsize;
- for (i = 0; i < rt->rateCount; i++) {
- if (rt->info[i].rateKbps == rate) {
- ndx = i;
- break;
- }
+ DPRINTF(sc, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
+
+ if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK ||
+ tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) {
+ kfree(tx_info_priv);
+ tx_info->rate_driver_data[0] = NULL;
+ }
+
+ if (tx_status->flags & ATH_TX_BAR) {
+ tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
+ tx_status->flags &= ~ATH_TX_BAR;
+ }
+
+ if (!(tx_status->flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) {
+ /* Frame was ACKed */
+ tx_info->flags |= IEEE80211_TX_STAT_ACK;
+ }
+
+ tx_info->status.rates[0].count = tx_status->retries;
+ if (tx_info->status.rates[0].flags & IEEE80211_TX_RC_MCS) {
+ /* Change idx from internal table index to MCS index */
+ int idx = tx_info->status.rates[0].idx;
+ struct ath_rate_table *rate_table = sc->cur_rate_table;
+ if (idx >= 0 && idx < rate_table->rate_cnt)
+ tx_info->status.rates[0].idx =
+ rate_table->info[idx].ratecode & 0x7f;
+ }
+
+ hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+ padsize = hdrlen & 3;
+ if (padsize && hdrlen >= 24) {
+ /*
+ * Remove MAC header padding before giving the frame back to
+ * mac80211.
+ */
+ memmove(skb->data + padsize, skb->data, hdrlen);
+ skb_pull(skb, padsize);
}
- return ndx;
+ ieee80211_tx_status(hw, skb);
}
/* Check if it's okay to send out aggregates */
-static int ath_aggr_query(struct ath_softc *sc,
- struct ath_node *an, u8 tidno)
+static int ath_aggr_query(struct ath_softc *sc, struct ath_node *an, u8 tidno)
{
struct ath_atx_tid *tid;
tid = ATH_AN_2_TID(an, tidno);
- if (tid->addba_exchangecomplete || tid->addba_exchangeinprogress)
+ if (tid->state & AGGR_ADDBA_COMPLETE ||
+ tid->state & AGGR_ADDBA_PROGRESS)
return 1;
else
return 0;
}
-static enum ath9k_pkt_type get_hal_packet_type(struct ieee80211_hdr *hdr)
+static void ath_get_beaconconfig(struct ath_softc *sc, int if_id,
+ struct ath_beacon_config *conf)
+{
+ struct ieee80211_hw *hw = sc->hw;
+
+ /* fill in beacon config data */
+
+ conf->beacon_interval = hw->conf.beacon_int;
+ conf->listen_interval = 100;
+ conf->dtim_count = 1;
+ conf->bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf->listen_interval;
+}
+
+/* Calculate Atheros packet type from IEEE80211 packet header */
+
+static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
{
+ struct ieee80211_hdr *hdr;
enum ath9k_pkt_type htype;
__le16 fc;
+ hdr = (struct ieee80211_hdr *)skb->data;
fc = hdr->frame_control;
- /* Calculate Atheros packet type from IEEE80211 packet header */
-
if (ieee80211_is_beacon(fc))
htype = ATH9K_PKT_TYPE_BEACON;
else if (ieee80211_is_probe_resp(fc))
@@ -159,232 +202,123 @@ static enum ath9k_pkt_type get_hal_packet_type(struct ieee80211_hdr *hdr)
return htype;
}
-static void fill_min_rates(struct sk_buff *skb, struct ath_tx_control *txctl)
+static bool is_pae(struct sk_buff *skb)
{
struct ieee80211_hdr *hdr;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- struct ath_tx_info_priv *tx_info_priv;
__le16 fc;
hdr = (struct ieee80211_hdr *)skb->data;
fc = hdr->frame_control;
- tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
- if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) {
- txctl->use_minrate = 1;
- txctl->min_rate = tx_info_priv->min_rate;
- } else if (ieee80211_is_data(fc)) {
+ if (ieee80211_is_data(fc)) {
if (ieee80211_is_nullfunc(fc) ||
- /* Port Access Entity (IEEE 802.1X) */
- (skb->protocol == cpu_to_be16(0x888E))) {
- txctl->use_minrate = 1;
- txctl->min_rate = tx_info_priv->min_rate;
+ /* Port Access Entity (IEEE 802.1X) */
+ (skb->protocol == cpu_to_be16(ETH_P_PAE))) {
+ return true;
}
- if (is_multicast_ether_addr(hdr->addr1))
- txctl->mcast_rate = tx_info_priv->min_rate;
}
+ return false;
}
-/* This function will setup additional txctl information, mostly rate stuff */
-/* FIXME: seqno, ps */
-static int ath_tx_prepare(struct ath_softc *sc,
- struct sk_buff *skb,
- struct ath_tx_control *txctl)
+static int get_hw_crypto_keytype(struct sk_buff *skb)
{
- struct ieee80211_hw *hw = sc->hw;
- struct ieee80211_hdr *hdr;
- struct ath_rc_series *rcs;
- struct ath_txq *txq = NULL;
- const struct ath9k_rate_table *rt;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- struct ath_tx_info_priv *tx_info_priv;
- int hdrlen;
- u8 rix, antenna;
- __le16 fc;
- u8 *qc;
-
- txctl->dev = sc;
- hdr = (struct ieee80211_hdr *)skb->data;
- hdrlen = ieee80211_get_hdrlen_from_skb(skb);
- fc = hdr->frame_control;
-
- rt = sc->sc_currates;
- BUG_ON(!rt);
-
- /* Fill misc fields */
-
- spin_lock_bh(&sc->node_lock);
- txctl->an = ath_node_get(sc, hdr->addr1);
- /* create a temp node, if the node is not there already */
- if (!txctl->an)
- txctl->an = ath_node_attach(sc, hdr->addr1, 0);
- spin_unlock_bh(&sc->node_lock);
-
- if (ieee80211_is_data_qos(fc)) {
- qc = ieee80211_get_qos_ctl(hdr);
- txctl->tidno = qc[0] & 0xf;
- }
-
- txctl->if_id = 0;
- txctl->frmlen = skb->len + FCS_LEN - (hdrlen & 3);
- txctl->txpower = MAX_RATE_POWER; /* FIXME */
-
- /* Fill Key related fields */
-
- txctl->keytype = ATH9K_KEY_TYPE_CLEAR;
- txctl->keyix = ATH9K_TXKEYIX_INVALID;
if (tx_info->control.hw_key) {
- txctl->keyix = tx_info->control.hw_key->hw_key_idx;
- txctl->frmlen += tx_info->control.hw_key->icv_len;
-
if (tx_info->control.hw_key->alg == ALG_WEP)
- txctl->keytype = ATH9K_KEY_TYPE_WEP;
+ return ATH9K_KEY_TYPE_WEP;
else if (tx_info->control.hw_key->alg == ALG_TKIP)
- txctl->keytype = ATH9K_KEY_TYPE_TKIP;
+ return ATH9K_KEY_TYPE_TKIP;
else if (tx_info->control.hw_key->alg == ALG_CCMP)
- txctl->keytype = ATH9K_KEY_TYPE_AES;
- }
-
- /* Fill packet type */
-
- txctl->atype = get_hal_packet_type(hdr);
-
- /* Fill qnum */
-
- if (unlikely(txctl->flags & ATH9K_TXDESC_CAB)) {
- txctl->qnum = 0;
- txq = sc->sc_cabq;
- } else {
- txctl->qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
- txq = &sc->sc_txq[txctl->qnum];
- }
- spin_lock_bh(&txq->axq_lock);
-
- /* Try to avoid running out of descriptors */
- if (txq->axq_depth >= (ATH_TXBUF - 20) &&
- !(txctl->flags & ATH9K_TXDESC_CAB)) {
- DPRINTF(sc, ATH_DBG_FATAL,
- "%s: TX queue: %d is full, depth: %d\n",
- __func__,
- txctl->qnum,
- txq->axq_depth);
- ieee80211_stop_queue(hw, skb_get_queue_mapping(skb));
- txq->stopped = 1;
- spin_unlock_bh(&txq->axq_lock);
- return -1;
+ return ATH9K_KEY_TYPE_AES;
}
- spin_unlock_bh(&txq->axq_lock);
-
- /* Fill rate */
-
- fill_min_rates(skb, txctl);
+ return ATH9K_KEY_TYPE_CLEAR;
+}
- /* Fill flags */
+/* Called only when tx aggregation is enabled and HT is supported */
- txctl->flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */
+static void assign_aggr_tid_seqno(struct sk_buff *skb,
+ struct ath_buf *bf)
+{
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+ struct ieee80211_hdr *hdr;
+ struct ath_node *an;
+ struct ath_atx_tid *tid;
+ __le16 fc;
+ u8 *qc;
- if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
- txctl->flags |= ATH9K_TXDESC_NOACK;
- if (tx_info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
- txctl->flags |= ATH9K_TXDESC_RTSENA;
+ if (!tx_info->control.sta)
+ return;
- /*
- * Setup for rate calculations.
- */
- tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
- rcs = tx_info_priv->rcs;
+ an = (struct ath_node *)tx_info->control.sta->drv_priv;
+ hdr = (struct ieee80211_hdr *)skb->data;
+ fc = hdr->frame_control;
- if (ieee80211_is_data(fc) && !txctl->use_minrate) {
+ /* Get tidno */
- /* Enable HT only for DATA frames and not for EAPOL */
- txctl->ht = (hw->conf.ht_conf.ht_supported &&
- (tx_info->flags & IEEE80211_TX_CTL_AMPDU));
+ if (ieee80211_is_data_qos(fc)) {
+ qc = ieee80211_get_qos_ctl(hdr);
+ bf->bf_tidno = qc[0] & 0xf;
+ }
- if (is_multicast_ether_addr(hdr->addr1)) {
- rcs[0].rix = (u8)
- ath_tx_findindex(rt, txctl->mcast_rate);
+ /* Get seqno */
- /*
- * mcast packets are not re-tried.
- */
- rcs[0].tries = 1;
- }
+ if (ieee80211_is_data(fc) && !is_pae(skb)) {
/* For HT capable stations, we save tidno for later use.
* We also override seqno set by upper layer with the one
* in tx aggregation state.
*
- * First, the fragmentation stat is determined.
* If fragmentation is on, the sequence number is
* not overridden, since it has been
* incremented by the fragmentation routine.
+ *
+ * FIXME: check if the fragmentation threshold exceeds
+ * IEEE80211 max.
*/
- if (likely(!(txctl->flags & ATH9K_TXDESC_FRAG_IS_ON)) &&
- txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) {
- struct ath_atx_tid *tid;
+ tid = ATH_AN_2_TID(an, bf->bf_tidno);
+ hdr->seq_ctrl = cpu_to_le16(tid->seq_next <<
+ IEEE80211_SEQ_SEQ_SHIFT);
+ bf->bf_seqno = tid->seq_next;
+ INCR(tid->seq_next, IEEE80211_SEQ_MAX);
+ }
+}
- tid = ATH_AN_2_TID(txctl->an, txctl->tidno);
+static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb,
+ struct ath_txq *txq)
+{
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+ int flags = 0;
- hdr->seq_ctrl = cpu_to_le16(tid->seq_next <<
- IEEE80211_SEQ_SEQ_SHIFT);
- txctl->seqno = tid->seq_next;
- INCR(tid->seq_next, IEEE80211_SEQ_MAX);
- }
- } else {
- /* for management and control frames,
- * or for NULL and EAPOL frames */
- if (txctl->min_rate)
- rcs[0].rix = ath_rate_findrateix(sc, txctl->min_rate);
- else
- rcs[0].rix = 0;
- rcs[0].tries = ATH_MGT_TXMAXTRY;
- }
- rix = rcs[0].rix;
+ flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */
+ flags |= ATH9K_TXDESC_INTREQ;
- if (ieee80211_has_morefrags(fc) ||
- (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) {
- /*
- ** Force hardware to use computed duration for next
- ** fragment by disabling multi-rate retry, which
- ** updates duration based on the multi-rate
- ** duration table.
- */
- rcs[1].tries = rcs[2].tries = rcs[3].tries = 0;
- rcs[1].rix = rcs[2].rix = rcs[3].rix = 0;
- /* reset tries but keep rate index */
- rcs[0].tries = ATH_TXMAXTRY;
- }
+ if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
+ flags |= ATH9K_TXDESC_NOACK;
+ if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
+ flags |= ATH9K_TXDESC_RTSENA;
- /*
- * Determine if a tx interrupt should be generated for
- * this descriptor. We take a tx interrupt to reap
- * descriptors when the h/w hits an EOL condition or
- * when the descriptor is specifically marked to generate
- * an interrupt. We periodically mark descriptors in this
- * way to insure timely replenishing of the supply needed
- * for sending frames. Defering interrupts reduces system
- * load and potentially allows more concurrent work to be
- * done but if done to aggressively can cause senders to
- * backup.
- *
- * NB: use >= to deal with sc_txintrperiod changing
- * dynamically through sysctl.
- */
- spin_lock_bh(&txq->axq_lock);
- if ((++txq->axq_intrcnt >= sc->sc_txintrperiod)) {
- txctl->flags |= ATH9K_TXDESC_INTREQ;
- txq->axq_intrcnt = 0;
- }
- spin_unlock_bh(&txq->axq_lock);
+ return flags;
+}
+
+static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
+{
+ struct ath_buf *bf = NULL;
- if (is_multicast_ether_addr(hdr->addr1)) {
- antenna = sc->sc_mcastantenna + 1;
- sc->sc_mcastantenna = (sc->sc_mcastantenna + 1) & 0x1;
+ spin_lock_bh(&sc->tx.txbuflock);
+
+ if (unlikely(list_empty(&sc->tx.txbuf))) {
+ spin_unlock_bh(&sc->tx.txbuflock);
+ return NULL;
}
- return 0;
+ bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
+ list_del(&bf->list);
+
+ spin_unlock_bh(&sc->tx.txbuflock);
+
+ return bf;
}
/* To complete a chain of buffers associated a frame */
@@ -396,6 +330,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc,
{
struct sk_buff *skb = bf->bf_mpdu;
struct ath_xmit_status tx_status;
+ unsigned long flags;
/*
* Set retry information.
@@ -414,20 +349,21 @@ static void ath_tx_complete_buf(struct ath_softc *sc,
if (bf_isxretried(bf))
tx_status.flags |= ATH_TX_XRETRY;
}
+
/* Unmap this frame */
pci_unmap_single(sc->pdev,
bf->bf_dmacontext,
skb->len,
PCI_DMA_TODEVICE);
/* complete this frame */
- ath_tx_complete(sc, skb, &tx_status, bf->bf_node);
+ ath_tx_complete(sc, skb, &tx_status);
/*
* Return the list of ath_buf of this mpdu to free queue
*/
- spin_lock_bh(&sc->sc_txbuflock);
- list_splice_tail_init(bf_q, &sc->sc_txbuf);
- spin_unlock_bh(&sc->sc_txbuflock);
+ spin_lock_irqsave(&sc->tx.txbuflock, flags);
+ list_splice_tail_init(bf_q, &sc->tx.txbuf);
+ spin_unlock_irqrestore(&sc->tx.txbuflock, flags);
}
/*
@@ -468,7 +404,7 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
static void ath_tx_pause_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
{
- struct ath_txq *txq = &sc->sc_txq[tid->ac->qnum];
+ struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
spin_lock_bh(&txq->axq_lock);
@@ -481,7 +417,7 @@ static void ath_tx_pause_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
{
- struct ath_txq *txq = &sc->sc_txq[tid->ac->qnum];
+ struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
ASSERT(tid->paused > 0);
spin_lock_bh(&txq->axq_lock);
@@ -505,11 +441,9 @@ unlock:
/* Compute the number of bad frames */
-static int ath_tx_num_badfrms(struct ath_softc *sc,
- struct ath_buf *bf, int txok)
+static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
+ int txok)
{
- struct ath_node *an = bf->bf_node;
- int isnodegone = (an->an_flags & ATH_NODE_CLEAN);
struct ath_buf *bf_last = bf->bf_lastbf;
struct ath_desc *ds = bf_last->bf_desc;
u16 seq_st = 0;
@@ -518,7 +452,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc,
int nbad = 0;
int isaggr = 0;
- if (isnodegone || ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED)
+ if (ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED)
return 0;
isaggr = bf_isaggr(bf);
@@ -553,8 +487,8 @@ static void ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf)
/* Update block ack window */
-static void ath_tx_update_baw(struct ath_softc *sc,
- struct ath_atx_tid *tid, int seqno)
+static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
+ int seqno)
{
int index, cindex;
@@ -577,34 +511,23 @@ static void ath_tx_update_baw(struct ath_softc *sc,
* width - 0 for 20 MHz, 1 for 40 MHz
* half_gi - to use 4us v/s 3.6 us for symbol time
*/
-
-static u32 ath_pkt_duration(struct ath_softc *sc,
- u8 rix,
- struct ath_buf *bf,
- int width,
- int half_gi,
- bool shortPreamble)
+static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf,
+ int width, int half_gi, bool shortPreamble)
{
- const struct ath9k_rate_table *rt = sc->sc_currates;
+ struct ath_rate_table *rate_table = sc->cur_rate_table;
u32 nbits, nsymbits, duration, nsymbols;
u8 rc;
int streams, pktlen;
pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen;
- rc = rt->info[rix].rateCode;
+ rc = rate_table->info[rix].ratecode;
- /*
- * for legacy rates, use old function to compute packet duration
- */
+ /* for legacy rates, use old function to compute packet duration */
if (!IS_HT_RATE(rc))
- return ath9k_hw_computetxtime(sc->sc_ah,
- rt,
- pktlen,
- rix,
- shortPreamble);
- /*
- * find number of symbols: PLCP + data
- */
+ return ath9k_hw_computetxtime(sc->sc_ah, rate_table, pktlen,
+ rix, shortPreamble);
+
+ /* find number of symbols: PLCP + data */
nbits = (pktlen << 3) + OFDM_PLCP_BITS;
nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width];
nsymbols = (nbits + nsymbits - 1) / nsymbits;
@@ -614,11 +537,10 @@ static u32 ath_pkt_duration(struct ath_softc *sc,
else
duration = SYMBOL_TIME_HALFGI(nsymbols);
- /*
- * addup duration for legacy/ht training and signal fields
- */
+ /* addup duration for legacy/ht training and signal fields */
streams = HT_RC_2_STREAMS(rc);
duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
+
return duration;
}
@@ -627,207 +549,127 @@ static u32 ath_pkt_duration(struct ath_softc *sc,
static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
{
struct ath_hal *ah = sc->sc_ah;
- const struct ath9k_rate_table *rt;
+ struct ath_rate_table *rt;
struct ath_desc *ds = bf->bf_desc;
struct ath_desc *lastds = bf->bf_lastbf->bf_desc;
struct ath9k_11n_rate_series series[4];
- int i, flags, rtsctsena = 0, dynamic_mimops = 0;
+ struct sk_buff *skb;
+ struct ieee80211_tx_info *tx_info;
+ struct ieee80211_tx_rate *rates;
+ struct ieee80211_hdr *hdr;
+ int i, flags, rtsctsena = 0;
u32 ctsduration = 0;
u8 rix = 0, cix, ctsrate = 0;
- u32 aggr_limit_with_rts = ah->ah_caps.rts_aggr_limit;
- struct ath_node *an = (struct ath_node *) bf->bf_node;
+ __le16 fc;
- /*
- * get the cix for the lowest valid rix.
- */
- rt = sc->sc_currates;
- for (i = 4; i--;) {
- if (bf->bf_rcs[i].tries) {
- rix = bf->bf_rcs[i].rix;
+ memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
+
+ skb = (struct sk_buff *)bf->bf_mpdu;
+ hdr = (struct ieee80211_hdr *)skb->data;
+ fc = hdr->frame_control;
+ tx_info = IEEE80211_SKB_CB(skb);
+ rates = tx_info->control.rates;
+
+ if (ieee80211_has_morefrags(fc) ||
+ (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) {
+ rates[1].count = rates[2].count = rates[3].count = 0;
+ rates[1].idx = rates[2].idx = rates[3].idx = 0;
+ rates[0].count = ATH_TXMAXTRY;
+ }
+
+ /* get the cix for the lowest valid rix */
+ rt = sc->cur_rate_table;
+ for (i = 3; i >= 0; i--) {
+ if (rates[i].count && (rates[i].idx >= 0)) {
+ rix = rates[i].idx;
break;
}
}
+
flags = (bf->bf_flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA));
- cix = rt->info[rix].controlRate;
+ cix = rt->info[rix].ctrl_rate;
/*
- * If 802.11g protection is enabled, determine whether
- * to use RTS/CTS or just CTS. Note that this is only
- * done for OFDM/HT unicast frames.
+ * If 802.11g protection is enabled, determine whether to use RTS/CTS or
+ * just CTS. Note that this is only done for OFDM/HT unicast frames.
*/
- if (sc->sc_protmode != PROT_M_NONE &&
- (rt->info[rix].phy == PHY_OFDM ||
- rt->info[rix].phy == PHY_HT) &&
- (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) {
+ if (sc->sc_protmode != PROT_M_NONE && !(bf->bf_flags & ATH9K_TXDESC_NOACK)
+ && (rt->info[rix].phy == WLAN_RC_PHY_OFDM ||
+ WLAN_RC_PHY_HT(rt->info[rix].phy))) {
if (sc->sc_protmode == PROT_M_RTSCTS)
flags = ATH9K_TXDESC_RTSENA;
else if (sc->sc_protmode == PROT_M_CTSONLY)
flags = ATH9K_TXDESC_CTSENA;
- cix = rt->info[sc->sc_protrix].controlRate;
+ cix = rt->info[sc->sc_protrix].ctrl_rate;
rtsctsena = 1;
}
- /* For 11n, the default behavior is to enable RTS for
- * hw retried frames. We enable the global flag here and
- * let rate series flags determine which rates will actually
- * use RTS.
+ /* For 11n, the default behavior is to enable RTS for hw retried frames.
+ * We enable the global flag here and let rate series flags determine
+ * which rates will actually use RTS.
*/
if ((ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) && bf_isdata(bf)) {
- BUG_ON(!an);
- /*
- * 802.11g protection not needed, use our default behavior
- */
+ /* 802.11g protection not needed, use our default behavior */
if (!rtsctsena)
flags = ATH9K_TXDESC_RTSENA;
- /*
- * For dynamic MIMO PS, RTS needs to precede the first aggregate
- * and the second aggregate should have any protection at all.
- */
- if (an->an_smmode == ATH_SM_PWRSAV_DYNAMIC) {
- if (!bf_isaggrburst(bf)) {
- flags = ATH9K_TXDESC_RTSENA;
- dynamic_mimops = 1;
- } else {
- flags = 0;
- }
- }
}
- /*
- * Set protection if aggregate protection on
- */
+ /* Set protection if aggregate protection on */
if (sc->sc_config.ath_aggr_prot &&
(!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) {
flags = ATH9K_TXDESC_RTSENA;
- cix = rt->info[sc->sc_protrix].controlRate;
+ cix = rt->info[sc->sc_protrix].ctrl_rate;
rtsctsena = 1;
}
- /*
- * For AR5416 - RTS cannot be followed by a frame larger than 8K.
- */
- if (bf_isaggr(bf) && (bf->bf_al > aggr_limit_with_rts)) {
- /*
- * Ensure that in the case of SM Dynamic power save
- * while we are bursting the second aggregate the
- * RTS is cleared.
- */
+ /* For AR5416 - RTS cannot be followed by a frame larger than 8K */
+ if (bf_isaggr(bf) && (bf->bf_al > ah->ah_caps.rts_aggr_limit))
flags &= ~(ATH9K_TXDESC_RTSENA);
- }
/*
- * CTS transmit rate is derived from the transmit rate
- * by looking in the h/w rate table. We must also factor
- * in whether or not a short preamble is to be used.
+ * CTS transmit rate is derived from the transmit rate by looking in the
+ * h/w rate table. We must also factor in whether or not a short
+ * preamble is to be used. NB: cix is set above where RTS/CTS is enabled
*/
- /* NB: cix is set above where RTS/CTS is enabled */
- BUG_ON(cix == 0xff);
- ctsrate = rt->info[cix].rateCode |
- (bf_isshpreamble(bf) ? rt->info[cix].shortPreamble : 0);
-
- /*
- * Setup HAL rate series
- */
- memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
+ ctsrate = rt->info[cix].ratecode |
+ (bf_isshpreamble(bf) ? rt->info[cix].short_preamble : 0);
for (i = 0; i < 4; i++) {
- if (!bf->bf_rcs[i].tries)
+ if (!rates[i].count || (rates[i].idx < 0))
continue;
- rix = bf->bf_rcs[i].rix;
+ rix = rates[i].idx;
- series[i].Rate = rt->info[rix].rateCode |
- (bf_isshpreamble(bf) ? rt->info[rix].shortPreamble : 0);
+ series[i].Rate = rt->info[rix].ratecode |
+ (bf_isshpreamble(bf) ? rt->info[rix].short_preamble : 0);
- series[i].Tries = bf->bf_rcs[i].tries;
+ series[i].Tries = rates[i].count;
series[i].RateFlags = (
- (bf->bf_rcs[i].flags & ATH_RC_RTSCTS_FLAG) ?
+ (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) ?
ATH9K_RATESERIES_RTS_CTS : 0) |
- ((bf->bf_rcs[i].flags & ATH_RC_CW40_FLAG) ?
+ ((rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ?
ATH9K_RATESERIES_2040 : 0) |
- ((bf->bf_rcs[i].flags & ATH_RC_SGI_FLAG) ?
+ ((rates[i].flags & IEEE80211_TX_RC_SHORT_GI) ?
ATH9K_RATESERIES_HALFGI : 0);
- series[i].PktDuration = ath_pkt_duration(
- sc, rix, bf,
- (bf->bf_rcs[i].flags & ATH_RC_CW40_FLAG) != 0,
- (bf->bf_rcs[i].flags & ATH_RC_SGI_FLAG),
- bf_isshpreamble(bf));
+ series[i].PktDuration = ath_pkt_duration(sc, rix, bf,
+ (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) != 0,
+ (rates[i].flags & IEEE80211_TX_RC_SHORT_GI),
+ bf_isshpreamble(bf));
- if ((an->an_smmode == ATH_SM_PWRSAV_STATIC) &&
- (bf->bf_rcs[i].flags & ATH_RC_DS_FLAG) == 0) {
- /*
- * When sending to an HT node that has enabled static
- * SM/MIMO power save, send at single stream rates but
- * use maximum allowed transmit chains per user,
- * hardware, regulatory, or country limits for
- * better range.
- */
- series[i].ChSel = sc->sc_tx_chainmask;
- } else {
- if (bf_isht(bf))
- series[i].ChSel =
- ath_chainmask_sel_logic(sc, an);
- else
- series[i].ChSel = sc->sc_tx_chainmask;
- }
+ series[i].ChSel = sc->sc_tx_chainmask;
if (rtsctsena)
series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
-
- /*
- * Set RTS for all rates if node is in dynamic powersave
- * mode and we are using dual stream rates.
- */
- if (dynamic_mimops && (bf->bf_rcs[i].flags & ATH_RC_DS_FLAG))
- series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
- }
-
- /*
- * For non-HT devices, calculate RTS/CTS duration in software
- * and disable multi-rate retry.
- */
- if (flags && !(ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT)) {
- /*
- * Compute the transmit duration based on the frame
- * size and the size of an ACK frame. We call into the
- * HAL to do the computation since it depends on the
- * characteristics of the actual PHY being used.
- *
- * NB: CTS is assumed the same size as an ACK so we can
- * use the precalculated ACK durations.
- */
- if (flags & ATH9K_TXDESC_RTSENA) { /* SIFS + CTS */
- ctsduration += bf_isshpreamble(bf) ?
- rt->info[cix].spAckDuration :
- rt->info[cix].lpAckDuration;
- }
-
- ctsduration += series[0].PktDuration;
-
- if ((bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) { /* SIFS + ACK */
- ctsduration += bf_isshpreamble(bf) ?
- rt->info[rix].spAckDuration :
- rt->info[rix].lpAckDuration;
- }
-
- /*
- * Disable multi-rate retry when using RTS/CTS by clearing
- * series 1, 2 and 3.
- */
- memset(&series[1], 0, sizeof(struct ath9k_11n_rate_series) * 3);
}
- /*
- * set dur_update_en for l-sig computation except for PS-Poll frames
- */
- ath9k_hw_set11n_ratescenario(ah, ds, lastds,
- !bf_ispspoll(bf),
- ctsrate,
- ctsduration,
+ /* set dur_update_en for l-sig computation except for PS-Poll frames */
+ ath9k_hw_set11n_ratescenario(ah, ds, lastds, !bf_ispspoll(bf),
+ ctsrate, ctsduration,
series, 4, flags);
+
if (sc->sc_config.ath_aggr_prot && flags)
ath9k_hw_set11n_burstduration(ah, ds, 8192);
}
@@ -836,27 +678,18 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
* Function to send a normal HT (non-AMPDU) frame
* NB: must be called with txq lock held
*/
-
static int ath_tx_send_normal(struct ath_softc *sc,
struct ath_txq *txq,
struct ath_atx_tid *tid,
struct list_head *bf_head)
{
struct ath_buf *bf;
- struct sk_buff *skb;
- struct ieee80211_tx_info *tx_info;
- struct ath_tx_info_priv *tx_info_priv;
BUG_ON(list_empty(bf_head));
bf = list_first_entry(bf_head, struct ath_buf, list);
bf->bf_state.bf_type &= ~BUF_AMPDU; /* regular HT frame */
- skb = (struct sk_buff *)bf->bf_mpdu;
- tx_info = IEEE80211_SKB_CB(skb);
- tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
- memcpy(bf->bf_rcs, tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0]));
-
/* update starting sequence number for subsequent ADDBA request */
INCR(tid->seq_start, IEEE80211_SEQ_MAX);
@@ -873,7 +706,7 @@ static int ath_tx_send_normal(struct ath_softc *sc,
static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
{
- struct ath_txq *txq = &sc->sc_txq[tid->ac->qnum];
+ struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum];
struct ath_buf *bf;
struct list_head bf_head;
INIT_LIST_HEAD(&bf_head);
@@ -906,8 +739,10 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
struct list_head *bf_q,
int txok)
{
- struct ath_node *an = bf->bf_node;
- struct ath_atx_tid *tid = ATH_AN_2_TID(an, bf->bf_tidno);
+ struct ath_node *an = NULL;
+ struct sk_buff *skb;
+ struct ieee80211_tx_info *tx_info;
+ struct ath_atx_tid *tid = NULL;
struct ath_buf *bf_last = bf->bf_lastbf;
struct ath_desc *ds = bf_last->bf_desc;
struct ath_buf *bf_next, *bf_lastq = NULL;
@@ -915,7 +750,14 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
u16 seq_st = 0;
u32 ba[WME_BA_BMP_SIZE >> 5];
int isaggr, txfail, txpending, sendbar = 0, needreset = 0;
- int isnodegone = (an->an_flags & ATH_NODE_CLEAN);
+
+ skb = (struct sk_buff *)bf->bf_mpdu;
+ tx_info = IEEE80211_SKB_CB(skb);
+
+ if (tx_info->control.sta) {
+ an = (struct ath_node *)tx_info->control.sta->drv_priv;
+ tid = ATH_AN_2_TID(an, bf->bf_tidno);
+ }
isaggr = bf_isaggr(bf);
if (isaggr) {
@@ -939,7 +781,8 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
* when perform internal reset in this routine.
* Only enable reset in STA mode for now.
*/
- if (sc->sc_ah->ah_opmode == ATH9K_M_STA)
+ if (sc->sc_ah->ah_opmode ==
+ NL80211_IFTYPE_STATION)
needreset = 1;
}
} else {
@@ -961,7 +804,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
/* transmit completion */
} else {
- if (!tid->cleanup_inprogress && !isnodegone &&
+ if (!(tid->state & AGGR_CLEANUP) &&
ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) {
if (bf->bf_retries < ATH_MAX_SW_RETRIES) {
ath_tx_set_retry(sc, bf);
@@ -1038,18 +881,17 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
struct ath_buf *tbf;
/* allocate new descriptor */
- spin_lock_bh(&sc->sc_txbuflock);
- ASSERT(!list_empty((&sc->sc_txbuf)));
- tbf = list_first_entry(&sc->sc_txbuf,
+ spin_lock_bh(&sc->tx.txbuflock);
+ ASSERT(!list_empty((&sc->tx.txbuf)));
+ tbf = list_first_entry(&sc->tx.txbuf,
struct ath_buf, list);
list_del(&tbf->list);
- spin_unlock_bh(&sc->sc_txbuflock);
+ spin_unlock_bh(&sc->tx.txbuflock);
ATH_TXBUF_RESET(tbf);
/* copy descriptor content */
tbf->bf_mpdu = bf_last->bf_mpdu;
- tbf->bf_node = bf_last->bf_node;
tbf->bf_buf_addr = bf_last->bf_buf_addr;
*(tbf->bf_desc) = *(bf_last->bf_desc);
@@ -1090,25 +932,16 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
bf = bf_next;
}
- /*
- * node is already gone. no more assocication
- * with the node. the node might have been freed
- * any node acces can result in panic.note tid
- * is part of the node.
- */
- if (isnodegone)
- return;
-
- if (tid->cleanup_inprogress) {
+ if (tid->state & AGGR_CLEANUP) {
/* check to see if we're done with cleaning the h/w queue */
spin_lock_bh(&txq->axq_lock);
if (tid->baw_head == tid->baw_tail) {
- tid->addba_exchangecomplete = 0;
+ tid->state &= ~AGGR_ADDBA_COMPLETE;
tid->addba_exchangeattempts = 0;
spin_unlock_bh(&txq->axq_lock);
- tid->cleanup_inprogress = false;
+ tid->state &= ~AGGR_CLEANUP;
/* send buffered frames as singles */
ath_tx_flush_tid(sc, tid);
@@ -1136,29 +969,45 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc,
return;
}
+static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, int nbad)
+{
+ struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+ struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info);
+
+ tx_info_priv->update_rc = false;
+ if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT)
+ tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+
+ if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 &&
+ (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) {
+ if (bf_isdata(bf)) {
+ memcpy(&tx_info_priv->tx, &ds->ds_txstat,
+ sizeof(tx_info_priv->tx));
+ tx_info_priv->n_frames = bf->bf_nframes;
+ tx_info_priv->n_bad_frames = nbad;
+ tx_info_priv->update_rc = true;
+ }
+ }
+}
+
/* Process completed xmit descriptors from the specified queue */
-static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
+static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
{
struct ath_hal *ah = sc->sc_ah;
struct ath_buf *bf, *lastbf, *bf_held = NULL;
struct list_head bf_head;
- struct ath_desc *ds, *tmp_ds;
- struct sk_buff *skb;
- struct ieee80211_tx_info *tx_info;
- struct ath_tx_info_priv *tx_info_priv;
- int nacked, txok, nbad = 0, isrifs = 0;
+ struct ath_desc *ds;
+ int txok, nbad = 0;
int status;
- DPRINTF(sc, ATH_DBG_QUEUE,
- "%s: tx queue %d (%x), link %p\n", __func__,
+ DPRINTF(sc, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
txq->axq_link);
- nacked = 0;
for (;;) {
spin_lock_bh(&txq->axq_lock);
- txq->axq_intrcnt = 0; /* reset periodic desc intr count */
if (list_empty(&txq->axq_q)) {
txq->axq_link = NULL;
txq->axq_linkbuf = NULL;
@@ -1229,9 +1078,9 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
if (bf_held) {
list_del(&bf_held->list);
- spin_lock_bh(&sc->sc_txbuflock);
- list_add_tail(&bf_held->list, &sc->sc_txbuf);
- spin_unlock_bh(&sc->sc_txbuflock);
+ spin_lock_bh(&sc->tx.txbuflock);
+ list_add_tail(&bf_held->list, &sc->tx.txbuf);
+ spin_unlock_bh(&sc->tx.txbuflock);
}
if (!bf_isampdu(bf)) {
@@ -1246,29 +1095,8 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
} else {
nbad = ath_tx_num_badfrms(sc, bf, txok);
}
- skb = bf->bf_mpdu;
- tx_info = IEEE80211_SKB_CB(skb);
- tx_info_priv = (struct ath_tx_info_priv *)
- tx_info->driver_data[0];
- if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT)
- tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
- if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 &&
- (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0) {
- if (ds->ds_txstat.ts_status == 0)
- nacked++;
-
- if (bf_isdata(bf)) {
- if (isrifs)
- tmp_ds = bf->bf_rifslast->bf_desc;
- else
- tmp_ds = ds;
- memcpy(&tx_info_priv->tx,
- &tmp_ds->ds_txstat,
- sizeof(tx_info_priv->tx));
- tx_info_priv->n_frames = bf->bf_nframes;
- tx_info_priv->n_bad_frames = nbad;
- }
- }
+
+ ath_tx_rc_status(bf, ds, nbad);
/*
* Complete this transmit unit
@@ -1299,7 +1127,6 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
ath_txq_schedule(sc, txq);
spin_unlock_bh(&txq->axq_lock);
}
- return nacked;
}
static void ath_tx_stopdma(struct ath_softc *sc, struct ath_txq *txq)
@@ -1307,9 +1134,9 @@ static void ath_tx_stopdma(struct ath_softc *sc, struct ath_txq *txq)
struct ath_hal *ah = sc->sc_ah;
(void) ath9k_hw_stoptxdma(ah, txq->axq_qnum);
- DPRINTF(sc, ATH_DBG_XMIT, "%s: tx queue [%u] %x, link %p\n",
- __func__, txq->axq_qnum,
- ath9k_hw_gettxbuf(ah, txq->axq_qnum), txq->axq_link);
+ DPRINTF(sc, ATH_DBG_XMIT, "tx queue [%u] %x, link %p\n",
+ txq->axq_qnum, ath9k_hw_gettxbuf(ah, txq->axq_qnum),
+ txq->axq_link);
}
/* Drain only the data queues */
@@ -1317,40 +1144,33 @@ static void ath_tx_stopdma(struct ath_softc *sc, struct ath_txq *txq)
static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx)
{
struct ath_hal *ah = sc->sc_ah;
- int i;
- int npend = 0;
+ int i, status, npend = 0;
- /* XXX return value */
if (!(sc->sc_flags & SC_OP_INVALID)) {
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (ATH_TXQ_SETUP(sc, i)) {
- ath_tx_stopdma(sc, &sc->sc_txq[i]);
-
+ ath_tx_stopdma(sc, &sc->tx.txq[i]);
/* The TxDMA may not really be stopped.
* Double check the hal tx pending count */
npend += ath9k_hw_numtxpending(ah,
- sc->sc_txq[i].axq_qnum);
+ sc->tx.txq[i].axq_qnum);
}
}
}
if (npend) {
- int status;
-
/* TxDMA not stopped, reset the hal */
- DPRINTF(sc, ATH_DBG_XMIT,
- "%s: Unable to stop TxDMA. Reset HAL!\n", __func__);
+ DPRINTF(sc, ATH_DBG_XMIT, "Unable to stop TxDMA. Reset HAL!\n");
spin_lock_bh(&sc->sc_resetlock);
if (!ath9k_hw_reset(ah,
sc->sc_ah->ah_curchan,
- sc->sc_ht_info.tx_chan_width,
+ sc->tx_chan_width,
sc->sc_tx_chainmask, sc->sc_rx_chainmask,
sc->sc_ht_extprotspacing, true, &status)) {
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to reset hardware; hal status %u\n",
- __func__,
+ "Unable to reset hardware; hal status %u\n",
status);
}
spin_unlock_bh(&sc->sc_resetlock);
@@ -1358,7 +1178,7 @@ static void ath_drain_txdataq(struct ath_softc *sc, bool retry_tx)
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (ATH_TXQ_SETUP(sc, i))
- ath_tx_draintxq(sc, &sc->sc_txq[i], retry_tx);
+ ath_tx_draintxq(sc, &sc->tx.txq[i], retry_tx);
}
}
@@ -1390,24 +1210,17 @@ static void ath_tx_addto_baw(struct ath_softc *sc,
* Function to send an A-MPDU
* NB: must be called with txq lock held
*/
-
static int ath_tx_send_ampdu(struct ath_softc *sc,
- struct ath_txq *txq,
struct ath_atx_tid *tid,
struct list_head *bf_head,
struct ath_tx_control *txctl)
{
struct ath_buf *bf;
- struct sk_buff *skb;
- struct ieee80211_tx_info *tx_info;
- struct ath_tx_info_priv *tx_info_priv;
BUG_ON(list_empty(bf_head));
bf = list_first_entry(bf_head, struct ath_buf, list);
bf->bf_state.bf_type |= BUF_AMPDU;
- bf->bf_seqno = txctl->seqno; /* save seqno and tidno in buffer */
- bf->bf_tidno = txctl->tidno;
/*
* Do not queue to h/w when any of the following conditions is true:
@@ -1418,21 +1231,16 @@ static int ath_tx_send_ampdu(struct ath_softc *sc,
*/
if (!list_empty(&tid->buf_q) || tid->paused ||
!BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno) ||
- txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) {
+ txctl->txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) {
/*
* Add this frame to software queue for scheduling later
* for aggregation.
*/
list_splice_tail_init(bf_head, &tid->buf_q);
- ath_tx_queue_tid(txq, tid);
+ ath_tx_queue_tid(txctl->txq, tid);
return 0;
}
- skb = (struct sk_buff *)bf->bf_mpdu;
- tx_info = IEEE80211_SKB_CB(skb);
- tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
- memcpy(bf->bf_rcs, tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0]));
-
/* Add sub-frame to BAW */
ath_tx_addto_baw(sc, tid, bf);
@@ -1440,7 +1248,8 @@ static int ath_tx_send_ampdu(struct ath_softc *sc,
bf->bf_nframes = 1;
bf->bf_lastbf = bf->bf_lastfrm; /* one single frame */
ath_buf_set_rate(sc, bf);
- ath_tx_txqaddbuf(sc, txq, bf_head);
+ ath_tx_txqaddbuf(sc, txctl->txq, bf_head);
+
return 0;
}
@@ -1448,25 +1257,24 @@ static int ath_tx_send_ampdu(struct ath_softc *sc,
* looks up the rate
* returns aggr limit based on lowest of the rates
*/
-
static u32 ath_lookup_rate(struct ath_softc *sc,
- struct ath_buf *bf)
+ struct ath_buf *bf,
+ struct ath_atx_tid *tid)
{
- const struct ath9k_rate_table *rt = sc->sc_currates;
+ struct ath_rate_table *rate_table = sc->cur_rate_table;
struct sk_buff *skb;
struct ieee80211_tx_info *tx_info;
+ struct ieee80211_tx_rate *rates;
struct ath_tx_info_priv *tx_info_priv;
u32 max_4ms_framelen, frame_length;
u16 aggr_limit, legacy = 0, maxampdu;
int i;
-
skb = (struct sk_buff *)bf->bf_mpdu;
tx_info = IEEE80211_SKB_CB(skb);
- tx_info_priv = (struct ath_tx_info_priv *)
- tx_info->driver_data[0];
- memcpy(bf->bf_rcs,
- tx_info_priv->rcs, 4 * sizeof(tx_info_priv->rcs[0]));
+ rates = tx_info->control.rates;
+ tx_info_priv =
+ (struct ath_tx_info_priv *)tx_info->rate_driver_data[0];
/*
* Find the lowest frame length among the rate series that will have a
@@ -1476,14 +1284,14 @@ static u32 ath_lookup_rate(struct ath_softc *sc,
max_4ms_framelen = ATH_AMPDU_LIMIT_MAX;
for (i = 0; i < 4; i++) {
- if (bf->bf_rcs[i].tries) {
- frame_length = bf->bf_rcs[i].max_4ms_framelen;
-
- if (rt->info[bf->bf_rcs[i].rix].phy != PHY_HT) {
+ if (rates[i].count) {
+ if (!WLAN_RC_PHY_HT(rate_table->info[rates[i].idx].phy)) {
legacy = 1;
break;
}
+ frame_length =
+ rate_table->info[rates[i].idx].max_4ms_framelen;
max_4ms_framelen = min(max_4ms_framelen, frame_length);
}
}
@@ -1504,7 +1312,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc,
* The IE, however can hold upto 65536, which shows up here
* as zero. Ignore 65536 since we are constrained by hw.
*/
- maxampdu = sc->sc_ht_info.maxampdu;
+ maxampdu = tid->an->maxampdu;
if (maxampdu)
aggr_limit = min(aggr_limit, maxampdu);
@@ -1516,12 +1324,14 @@ static u32 ath_lookup_rate(struct ath_softc *sc,
* meet the minimum required mpdudensity.
* caller should make sure that the rate is HT rate .
*/
-
static int ath_compute_num_delims(struct ath_softc *sc,
+ struct ath_atx_tid *tid,
struct ath_buf *bf,
u16 frmlen)
{
- const struct ath9k_rate_table *rt = sc->sc_currates;
+ struct ath_rate_table *rt = sc->cur_rate_table;
+ struct sk_buff *skb = bf->bf_mpdu;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
u32 nsymbits, nsymbols, mpdudensity;
u16 minlen;
u8 rc, flags, rix;
@@ -1545,7 +1355,7 @@ static int ath_compute_num_delims(struct ath_softc *sc,
* required minimum length for subframe. Take into account
* whether high rate is 20 or 40Mhz and half or full GI.
*/
- mpdudensity = sc->sc_ht_info.mpdudensity;
+ mpdudensity = tid->an->mpdudensity;
/*
* If there is no mpdu density restriction, no further calculation
@@ -1554,11 +1364,11 @@ static int ath_compute_num_delims(struct ath_softc *sc,
if (mpdudensity == 0)
return ndelim;
- rix = bf->bf_rcs[0].rix;
- flags = bf->bf_rcs[0].flags;
- rc = rt->info[rix].rateCode;
- width = (flags & ATH_RC_CW40_FLAG) ? 1 : 0;
- half_gi = (flags & ATH_RC_SGI_FLAG) ? 1 : 0;
+ rix = tx_info->control.rates[0].idx;
+ flags = tx_info->control.rates[0].flags;
+ rc = rt->info[rix].ratecode;
+ width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0;
+ half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0;
if (half_gi)
nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity);
@@ -1585,7 +1395,6 @@ static int ath_compute_num_delims(struct ath_softc *sc,
* For aggregation from software buffer queue.
* NB: must be called with txq lock held
*/
-
static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
struct ath_atx_tid *tid,
struct list_head *bf_q,
@@ -1600,7 +1409,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
u16 aggr_limit = 0, al = 0, bpad = 0,
al_delta, h_baw = tid->baw_size / 2;
enum ATH_AGGR_STATUS status = ATH_AGGR_DONE;
- int prev_al = 0, is_ds_rate = 0;
+ int prev_al = 0;
INIT_LIST_HEAD(&bf_head);
BUG_ON(list_empty(&tid->buf_q));
@@ -1619,13 +1428,8 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
}
if (!rl) {
- aggr_limit = ath_lookup_rate(sc, bf);
+ aggr_limit = ath_lookup_rate(sc, bf, tid);
rl = 1;
- /*
- * Is rate dual stream
- */
- is_ds_rate =
- (bf->bf_rcs[0].flags & ATH_RC_DS_FLAG) ? 1 : 0;
}
/*
@@ -1657,7 +1461,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
* Get the delimiters needed to meet the MPDU
* density for this node.
*/
- ndelim = ath_compute_num_delims(sc, bf_first, bf->bf_frmlen);
+ ndelim = ath_compute_num_delims(sc, tid, bf_first, bf->bf_frmlen);
bpad = PADBYTES(al_delta) + (ndelim << 2);
@@ -1713,7 +1517,6 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
* process pending frames possibly doing a-mpdu aggregation
* NB: must be called with txq lock held
*/
-
static void ath_tx_sched_aggr(struct ath_softc *sc,
struct ath_txq *txq, struct ath_atx_tid *tid)
{
@@ -1799,8 +1602,8 @@ static void ath_tx_sched_aggr(struct ath_softc *sc,
static void ath_tid_drain(struct ath_softc *sc,
struct ath_txq *txq,
- struct ath_atx_tid *tid,
- bool bh_flag)
+ struct ath_atx_tid *tid)
+
{
struct ath_buf *bf;
struct list_head bf_head;
@@ -1821,18 +1624,12 @@ static void ath_tid_drain(struct ath_softc *sc,
* do not indicate packets while holding txq spinlock.
* unlock is intentional here
*/
- if (likely(bh_flag))
- spin_unlock_bh(&txq->axq_lock);
- else
- spin_unlock(&txq->axq_lock);
+ spin_unlock(&txq->axq_lock);
/* complete this sub-frame */
ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
- if (likely(bh_flag))
- spin_lock_bh(&txq->axq_lock);
- else
- spin_lock(&txq->axq_lock);
+ spin_lock(&txq->axq_lock);
}
/*
@@ -1849,10 +1646,8 @@ static void ath_tid_drain(struct ath_softc *sc,
* Drain all pending buffers
* NB: must be called with txq lock held
*/
-
static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
- struct ath_txq *txq,
- bool bh_flag)
+ struct ath_txq *txq)
{
struct ath_atx_ac *ac, *ac_tmp;
struct ath_atx_tid *tid, *tid_tmp;
@@ -1863,51 +1658,33 @@ static void ath_txq_drain_pending_buffers(struct ath_softc *sc,
list_for_each_entry_safe(tid, tid_tmp, &ac->tid_q, list) {
list_del(&tid->list);
tid->sched = false;
- ath_tid_drain(sc, txq, tid, bh_flag);
+ ath_tid_drain(sc, txq, tid);
}
}
}
-static int ath_tx_start_dma(struct ath_softc *sc,
- struct sk_buff *skb,
- struct scatterlist *sg,
- u32 n_sg,
- struct ath_tx_control *txctl)
+static int ath_tx_setup_buffer(struct ath_softc *sc, struct ath_buf *bf,
+ struct sk_buff *skb,
+ struct ath_tx_control *txctl)
{
- struct ath_node *an = txctl->an;
- struct ath_buf *bf = NULL;
- struct list_head bf_head;
- struct ath_desc *ds;
- struct ath_hal *ah = sc->sc_ah;
- struct ath_txq *txq;
- struct ath_tx_info_priv *tx_info_priv;
- struct ath_rc_series *rcs;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- __le16 fc = hdr->frame_control;
-
- if (unlikely(txctl->flags & ATH9K_TXDESC_CAB))
- txq = sc->sc_cabq;
- else
- txq = &sc->sc_txq[txctl->qnum];
+ struct ath_tx_info_priv *tx_info_priv;
+ int hdrlen;
+ __le16 fc;
- /* For each sglist entry, allocate an ath_buf for DMA */
- INIT_LIST_HEAD(&bf_head);
- spin_lock_bh(&sc->sc_txbuflock);
- if (unlikely(list_empty(&sc->sc_txbuf))) {
- spin_unlock_bh(&sc->sc_txbuflock);
+ tx_info_priv = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC);
+ if (unlikely(!tx_info_priv))
return -ENOMEM;
- }
+ tx_info->rate_driver_data[0] = tx_info_priv;
+ hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+ fc = hdr->frame_control;
- bf = list_first_entry(&sc->sc_txbuf, struct ath_buf, list);
- list_del(&bf->list);
- spin_unlock_bh(&sc->sc_txbuflock);
+ ATH_TXBUF_RESET(bf);
- list_add_tail(&bf->list, &bf_head);
+ /* Frame type */
- /* set up this buffer */
- ATH_TXBUF_RESET(bf);
- bf->bf_frmlen = txctl->frmlen;
+ bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3);
ieee80211_is_data(fc) ?
(bf->bf_state.bf_type |= BUF_DATA) :
@@ -1921,120 +1698,158 @@ static int ath_tx_start_dma(struct ath_softc *sc,
(sc->sc_flags & SC_OP_PREAMBLE_SHORT) ?
(bf->bf_state.bf_type |= BUF_SHORT_PREAMBLE) :
(bf->bf_state.bf_type &= ~BUF_SHORT_PREAMBLE);
+ (sc->hw->conf.ht.enabled && !is_pae(skb) &&
+ (tx_info->flags & IEEE80211_TX_CTL_AMPDU)) ?
+ (bf->bf_state.bf_type |= BUF_HT) :
+ (bf->bf_state.bf_type &= ~BUF_HT);
+
+ bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq);
+
+ /* Crypto */
+
+ bf->bf_keytype = get_hw_crypto_keytype(skb);
+
+ if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) {
+ bf->bf_frmlen += tx_info->control.hw_key->icv_len;
+ bf->bf_keyix = tx_info->control.hw_key->hw_key_idx;
+ } else {
+ bf->bf_keyix = ATH9K_TXKEYIX_INVALID;
+ }
+
+ /* Assign seqno, tidno */
+
+ if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR))
+ assign_aggr_tid_seqno(skb, bf);
+
+ /* DMA setup */
- bf->bf_flags = txctl->flags;
- bf->bf_keytype = txctl->keytype;
- tx_info_priv = (struct ath_tx_info_priv *)tx_info->driver_data[0];
- rcs = tx_info_priv->rcs;
- bf->bf_rcs[0] = rcs[0];
- bf->bf_rcs[1] = rcs[1];
- bf->bf_rcs[2] = rcs[2];
- bf->bf_rcs[3] = rcs[3];
- bf->bf_node = an;
bf->bf_mpdu = skb;
- bf->bf_buf_addr = sg_dma_address(sg);
+
+ bf->bf_dmacontext = pci_map_single(sc->pdev, skb->data,
+ skb->len, PCI_DMA_TODEVICE);
+ if (unlikely(pci_dma_mapping_error(sc->pdev, bf->bf_dmacontext))) {
+ bf->bf_mpdu = NULL;
+ DPRINTF(sc, ATH_DBG_CONFIG,
+ "pci_dma_mapping_error() on TX\n");
+ return -ENOMEM;
+ }
+
+ bf->bf_buf_addr = bf->bf_dmacontext;
+ return 0;
+}
+
+/* FIXME: tx power */
+static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
+ struct ath_tx_control *txctl)
+{
+ struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
+ struct ath_node *an = NULL;
+ struct list_head bf_head;
+ struct ath_desc *ds;
+ struct ath_atx_tid *tid;
+ struct ath_hal *ah = sc->sc_ah;
+ int frm_type;
+
+ frm_type = get_hw_packet_type(skb);
+
+ INIT_LIST_HEAD(&bf_head);
+ list_add_tail(&bf->list, &bf_head);
/* setup descriptor */
+
ds = bf->bf_desc;
ds->ds_link = 0;
ds->ds_data = bf->bf_buf_addr;
- /*
- * Save the DMA context in the first ath_buf
- */
- bf->bf_dmacontext = txctl->dmacontext;
+ /* Formulate first tx descriptor with tx controls */
- /*
- * Formulate first tx descriptor with tx controls.
- */
- ath9k_hw_set11n_txdesc(ah,
- ds,
- bf->bf_frmlen, /* frame length */
- txctl->atype, /* Atheros packet type */
- min(txctl->txpower, (u16)60), /* txpower */
- txctl->keyix, /* key cache index */
- txctl->keytype, /* key type */
- txctl->flags); /* flags */
- ath9k_hw_filltxdesc(ah,
- ds,
- sg_dma_len(sg), /* segment length */
- true, /* first segment */
- (n_sg == 1) ? true : false, /* last segment */
- ds); /* first descriptor */
+ ath9k_hw_set11n_txdesc(ah, ds, bf->bf_frmlen, frm_type, MAX_RATE_POWER,
+ bf->bf_keyix, bf->bf_keytype, bf->bf_flags);
+
+ ath9k_hw_filltxdesc(ah, ds,
+ skb->len, /* segment length */
+ true, /* first segment */
+ true, /* last segment */
+ ds); /* first descriptor */
bf->bf_lastfrm = bf;
- (txctl->ht) ?
- (bf->bf_state.bf_type |= BUF_HT) :
- (bf->bf_state.bf_type &= ~BUF_HT);
- spin_lock_bh(&txq->axq_lock);
+ spin_lock_bh(&txctl->txq->axq_lock);
- if (txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) {
- struct ath_atx_tid *tid = ATH_AN_2_TID(an, txctl->tidno);
- if (ath_aggr_query(sc, an, txctl->tidno)) {
+ if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) &&
+ tx_info->control.sta) {
+ an = (struct ath_node *)tx_info->control.sta->drv_priv;
+ tid = ATH_AN_2_TID(an, bf->bf_tidno);
+
+ if (ath_aggr_query(sc, an, bf->bf_tidno)) {
/*
* Try aggregation if it's a unicast data frame
* and the destination is HT capable.
*/
- ath_tx_send_ampdu(sc, txq, tid, &bf_head, txctl);
+ ath_tx_send_ampdu(sc, tid, &bf_head, txctl);
} else {
/*
- * Send this frame as regular when ADDBA exchange
- * is neither complete nor pending.
+ * Send this frame as regular when ADDBA
+ * exchange is neither complete nor pending.
*/
- ath_tx_send_normal(sc, txq, tid, &bf_head);
+ ath_tx_send_normal(sc, txctl->txq,
+ tid, &bf_head);
}
} else {
bf->bf_lastbf = bf;
bf->bf_nframes = 1;
- ath_buf_set_rate(sc, bf);
-
- if (ieee80211_is_back_req(fc)) {
- /* This is required for resuming tid
- * during BAR completion */
- bf->bf_tidno = txctl->tidno;
- }
- ath_tx_txqaddbuf(sc, txq, &bf_head);
+ ath_buf_set_rate(sc, bf);
+ ath_tx_txqaddbuf(sc, txctl->txq, &bf_head);
}
- spin_unlock_bh(&txq->axq_lock);
- return 0;
+
+ spin_unlock_bh(&txctl->txq->axq_lock);
}
-static void xmit_map_sg(struct ath_softc *sc,
- struct sk_buff *skb,
- struct ath_tx_control *txctl)
+/* Upon failure caller should free skb */
+int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb,
+ struct ath_tx_control *txctl)
{
- struct ath_xmit_status tx_status;
- struct ath_atx_tid *tid;
- struct scatterlist sg;
+ struct ath_buf *bf;
+ int r;
- txctl->dmacontext = pci_map_single(sc->pdev, skb->data,
- skb->len, PCI_DMA_TODEVICE);
+ /* Check if a tx buffer is available */
- /* setup S/G list */
- memset(&sg, 0, sizeof(struct scatterlist));
- sg_dma_address(&sg) = txctl->dmacontext;
- sg_dma_len(&sg) = skb->len;
+ bf = ath_tx_get_buffer(sc);
+ if (!bf) {
+ DPRINTF(sc, ATH_DBG_XMIT, "TX buffers are full\n");
+ return -1;
+ }
- if (ath_tx_start_dma(sc, skb, &sg, 1, txctl) != 0) {
- /*
- * We have to do drop frame here.
- */
- pci_unmap_single(sc->pdev, txctl->dmacontext,
- skb->len, PCI_DMA_TODEVICE);
+ r = ath_tx_setup_buffer(sc, bf, skb, txctl);
+ if (unlikely(r)) {
+ struct ath_txq *txq = txctl->txq;
- tx_status.retries = 0;
- tx_status.flags = ATH_TX_ERROR;
+ DPRINTF(sc, ATH_DBG_FATAL, "TX mem alloc failure\n");
- if (txctl->ht && (sc->sc_flags & SC_OP_TXAGGR)) {
- /* Reclaim the seqno. */
- tid = ATH_AN_2_TID((struct ath_node *)
- txctl->an, txctl->tidno);
- DECR(tid->seq_next, IEEE80211_SEQ_MAX);
+ /* upon ath_tx_processq() this TX queue will be resumed, we
+ * guarantee this will happen by knowing beforehand that
+ * we will at least have to run TX completionon one buffer
+ * on the queue */
+ spin_lock_bh(&txq->axq_lock);
+ if (ath_txq_depth(sc, txq->axq_qnum) > 1) {
+ ieee80211_stop_queue(sc->hw,
+ skb_get_queue_mapping(skb));
+ txq->stopped = 1;
}
- ath_tx_complete(sc, skb, &tx_status, txctl->an);
+ spin_unlock_bh(&txq->axq_lock);
+
+ spin_lock_bh(&sc->tx.txbuflock);
+ list_add_tail(&bf->list, &sc->tx.txbuf);
+ spin_unlock_bh(&sc->tx.txbuflock);
+
+ return r;
}
+
+ ath_tx_start_dma(sc, bf, txctl);
+
+ return 0;
}
/* Initialize TX queue and h/w */
@@ -2044,26 +1859,25 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)
int error = 0;
do {
- spin_lock_init(&sc->sc_txbuflock);
+ spin_lock_init(&sc->tx.txbuflock);
/* Setup tx descriptors */
- error = ath_descdma_setup(sc, &sc->sc_txdma, &sc->sc_txbuf,
+ error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf,
"tx", nbufs, 1);
if (error != 0) {
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: failed to allocate tx descriptors: %d\n",
- __func__, error);
+ "Failed to allocate tx descriptors: %d\n",
+ error);
break;
}
/* XXX allocate beacon state together with vap */
- error = ath_descdma_setup(sc, &sc->sc_bdma, &sc->sc_bbuf,
+ error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf,
"beacon", ATH_BCBUF, 1);
if (error != 0) {
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: failed to allocate "
- "beacon descripotrs: %d\n",
- __func__, error);
+ "Failed to allocate beacon descriptors: %d\n",
+ error);
break;
}
@@ -2080,12 +1894,12 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)
int ath_tx_cleanup(struct ath_softc *sc)
{
/* cleanup beacon descriptors */
- if (sc->sc_bdma.dd_desc_len != 0)
- ath_descdma_cleanup(sc, &sc->sc_bdma, &sc->sc_bbuf);
+ if (sc->beacon.bdma.dd_desc_len != 0)
+ ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf);
/* cleanup tx descriptors */
- if (sc->sc_txdma.dd_desc_len != 0)
- ath_descdma_cleanup(sc, &sc->sc_txdma, &sc->sc_txbuf);
+ if (sc->tx.txdma.dd_desc_len != 0)
+ ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf);
return 0;
}
@@ -2133,15 +1947,15 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
*/
return NULL;
}
- if (qnum >= ARRAY_SIZE(sc->sc_txq)) {
+ if (qnum >= ARRAY_SIZE(sc->tx.txq)) {
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: hal qnum %u out of range, max %u!\n",
- __func__, qnum, (unsigned int)ARRAY_SIZE(sc->sc_txq));
+ "qnum %u out of range, max %u!\n",
+ qnum, (unsigned int)ARRAY_SIZE(sc->tx.txq));
ath9k_hw_releasetxqueue(ah, qnum);
return NULL;
}
if (!ATH_TXQ_SETUP(sc, qnum)) {
- struct ath_txq *txq = &sc->sc_txq[qnum];
+ struct ath_txq *txq = &sc->tx.txq[qnum];
txq->axq_qnum = qnum;
txq->axq_link = NULL;
@@ -2151,11 +1965,10 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
txq->axq_depth = 0;
txq->axq_aggr_depth = 0;
txq->axq_totalqueued = 0;
- txq->axq_intrcnt = 0;
txq->axq_linkbuf = NULL;
- sc->sc_txqsetup |= 1<<qnum;
+ sc->tx.txqsetup |= 1<<qnum;
}
- return &sc->sc_txq[qnum];
+ return &sc->tx.txq[qnum];
}
/* Reclaim resources for a setup queue */
@@ -2163,7 +1976,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq)
{
ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum);
- sc->sc_txqsetup &= ~(1<<txq->axq_qnum);
+ sc->tx.txqsetup &= ~(1<<txq->axq_qnum);
}
/*
@@ -2180,15 +1993,15 @@ int ath_tx_setup(struct ath_softc *sc, int haltype)
{
struct ath_txq *txq;
- if (haltype >= ARRAY_SIZE(sc->sc_haltype2q)) {
+ if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: HAL AC %u out of range, max %zu!\n",
- __func__, haltype, ARRAY_SIZE(sc->sc_haltype2q));
+ "HAL AC %u out of range, max %zu!\n",
+ haltype, ARRAY_SIZE(sc->tx.hwq_map));
return 0;
}
txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype);
if (txq != NULL) {
- sc->sc_haltype2q[haltype] = txq->axq_qnum;
+ sc->tx.hwq_map[haltype] = txq->axq_qnum;
return 1;
} else
return 0;
@@ -2200,20 +2013,19 @@ int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype)
switch (qtype) {
case ATH9K_TX_QUEUE_DATA:
- if (haltype >= ARRAY_SIZE(sc->sc_haltype2q)) {
+ if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) {
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: HAL AC %u out of range, max %zu!\n",
- __func__,
- haltype, ARRAY_SIZE(sc->sc_haltype2q));
+ "HAL AC %u out of range, max %zu!\n",
+ haltype, ARRAY_SIZE(sc->tx.hwq_map));
return -1;
}
- qnum = sc->sc_haltype2q[haltype];
+ qnum = sc->tx.hwq_map[haltype];
break;
case ATH9K_TX_QUEUE_BEACON:
- qnum = sc->sc_bhalq;
+ qnum = sc->beacon.beaconq;
break;
case ATH9K_TX_QUEUE_CAB:
- qnum = sc->sc_cabq->axq_qnum;
+ qnum = sc->beacon.cabq->axq_qnum;
break;
default:
qnum = -1;
@@ -2221,6 +2033,34 @@ int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype)
return qnum;
}
+/* Get a transmit queue, if available */
+
+struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb)
+{
+ struct ath_txq *txq = NULL;
+ int qnum;
+
+ qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc);
+ txq = &sc->tx.txq[qnum];
+
+ spin_lock_bh(&txq->axq_lock);
+
+ /* Try to avoid running out of descriptors */
+ if (txq->axq_depth >= (ATH_TXBUF - 20)) {
+ DPRINTF(sc, ATH_DBG_FATAL,
+ "TX queue: %d is full, depth: %d\n",
+ qnum, txq->axq_depth);
+ ieee80211_stop_queue(sc->hw, skb_get_queue_mapping(skb));
+ txq->stopped = 1;
+ spin_unlock_bh(&txq->axq_lock);
+ return NULL;
+ }
+
+ spin_unlock_bh(&txq->axq_lock);
+
+ return txq;
+}
+
/* Update parameters for a transmit queue */
int ath_txq_update(struct ath_softc *sc, int qnum,
@@ -2230,17 +2070,17 @@ int ath_txq_update(struct ath_softc *sc, int qnum,
int error = 0;
struct ath9k_tx_queue_info qi;
- if (qnum == sc->sc_bhalq) {
+ if (qnum == sc->beacon.beaconq) {
/*
* XXX: for beacon queue, we just save the parameter.
* It will be picked up by ath_beaconq_config when
* it's necessary.
*/
- sc->sc_beacon_qi = *qinfo;
+ sc->beacon.beacon_qi = *qinfo;
return 0;
}
- ASSERT(sc->sc_txq[qnum].axq_qnum == qnum);
+ ASSERT(sc->tx.txq[qnum].axq_qnum == qnum);
ath9k_hw_get_txq_props(ah, qnum, &qi);
qi.tqi_aifs = qinfo->tqi_aifs;
@@ -2251,8 +2091,7 @@ int ath_txq_update(struct ath_softc *sc, int qnum,
if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) {
DPRINTF(sc, ATH_DBG_FATAL,
- "%s: unable to update hardware queue %u!\n",
- __func__, qnum);
+ "Unable to update hardware queue %u!\n", qnum);
error = -EIO;
} else {
ath9k_hw_resettxqueue(ah, qnum); /* push to h/w */
@@ -2264,7 +2103,7 @@ int ath_txq_update(struct ath_softc *sc, int qnum,
int ath_cabq_update(struct ath_softc *sc)
{
struct ath9k_tx_queue_info qi;
- int qnum = sc->sc_cabq->axq_qnum;
+ int qnum = sc->beacon.cabq->axq_qnum;
struct ath_beacon_config conf;
ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
@@ -2284,27 +2123,6 @@ int ath_cabq_update(struct ath_softc *sc)
return 0;
}
-int ath_tx_start(struct ath_softc *sc, struct sk_buff *skb)
-{
- struct ath_tx_control txctl;
- int error = 0;
-
- memset(&txctl, 0, sizeof(struct ath_tx_control));
- error = ath_tx_prepare(sc, skb, &txctl);
- if (error == 0)
- /*
- * Start DMA mapping.
- * ath_tx_start_dma() will be called either synchronously
- * or asynchrounsly once DMA is complete.
- */
- xmit_map_sg(sc, skb, &txctl);
- else
- ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE);
-
- /* failed packets will be dropped by the caller */
- return error;
-}
-
/* Deferred processing of transmit interrupt */
void ath_tx_tasklet(struct ath_softc *sc)
@@ -2319,7 +2137,7 @@ void ath_tx_tasklet(struct ath_softc *sc)
*/
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i)))
- ath_tx_processq(sc, &sc->sc_txq[i]);
+ ath_tx_processq(sc, &sc->tx.txq[i]);
}
}
@@ -2351,9 +2169,9 @@ void ath_tx_draintxq(struct ath_softc *sc,
list_del(&bf->list);
spin_unlock_bh(&txq->axq_lock);
- spin_lock_bh(&sc->sc_txbuflock);
- list_add_tail(&bf->list, &sc->sc_txbuf);
- spin_unlock_bh(&sc->sc_txbuflock);
+ spin_lock_bh(&sc->tx.txbuflock);
+ list_add_tail(&bf->list, &sc->tx.txbuf);
+ spin_unlock_bh(&sc->tx.txbuflock);
continue;
}
@@ -2378,8 +2196,7 @@ void ath_tx_draintxq(struct ath_softc *sc,
if (sc->sc_flags & SC_OP_TXAGGR) {
if (!retry_tx) {
spin_lock_bh(&txq->axq_lock);
- ath_txq_drain_pending_buffers(sc, txq,
- ATH9K_BH_STATUS_CHANGE);
+ ath_txq_drain_pending_buffers(sc, txq);
spin_unlock_bh(&txq->axq_lock);
}
}
@@ -2392,9 +2209,9 @@ void ath_draintxq(struct ath_softc *sc, bool retry_tx)
/* stop beacon queue. The beacon will be freed when
* we go to INIT state */
if (!(sc->sc_flags & SC_OP_INVALID)) {
- (void) ath9k_hw_stoptxdma(sc->sc_ah, sc->sc_bhalq);
- DPRINTF(sc, ATH_DBG_XMIT, "%s: beacon queue %x\n", __func__,
- ath9k_hw_gettxbuf(sc->sc_ah, sc->sc_bhalq));
+ (void) ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
+ DPRINTF(sc, ATH_DBG_XMIT, "beacon queue %x\n",
+ ath9k_hw_gettxbuf(sc->sc_ah, sc->beacon.beaconq));
}
ath_drain_txdataq(sc, retry_tx);
@@ -2402,72 +2219,47 @@ void ath_draintxq(struct ath_softc *sc, bool retry_tx)
u32 ath_txq_depth(struct ath_softc *sc, int qnum)
{
- return sc->sc_txq[qnum].axq_depth;
+ return sc->tx.txq[qnum].axq_depth;
}
u32 ath_txq_aggr_depth(struct ath_softc *sc, int qnum)
{
- return sc->sc_txq[qnum].axq_aggr_depth;
+ return sc->tx.txq[qnum].axq_aggr_depth;
}
-/* Check if an ADDBA is required. A valid node must be passed. */
-enum ATH_AGGR_CHECK ath_tx_aggr_check(struct ath_softc *sc,
- struct ath_node *an,
- u8 tidno)
+bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno)
{
struct ath_atx_tid *txtid;
- DECLARE_MAC_BUF(mac);
if (!(sc->sc_flags & SC_OP_TXAGGR))
- return AGGR_NOT_REQUIRED;
+ return false;
- /* ADDBA exchange must be completed before sending aggregates */
txtid = ATH_AN_2_TID(an, tidno);
- if (txtid->addba_exchangecomplete)
- return AGGR_EXCHANGE_DONE;
-
- if (txtid->cleanup_inprogress)
- return AGGR_CLEANUP_PROGRESS;
-
- if (txtid->addba_exchangeinprogress)
- return AGGR_EXCHANGE_PROGRESS;
-
- if (!txtid->addba_exchangecomplete) {
- if (!txtid->addba_exchangeinprogress &&
+ if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
+ if (!(txtid->state & AGGR_ADDBA_PROGRESS) &&
(txtid->addba_exchangeattempts < ADDBA_EXCHANGE_ATTEMPTS)) {
txtid->addba_exchangeattempts++;
- return AGGR_REQUIRED;
+ return true;
}
}
- return AGGR_NOT_REQUIRED;
+ return false;
}
/* Start TX aggregation */
-int ath_tx_aggr_start(struct ath_softc *sc,
- const u8 *addr,
- u16 tid,
- u16 *ssn)
+int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
+ u16 tid, u16 *ssn)
{
struct ath_atx_tid *txtid;
struct ath_node *an;
- spin_lock_bh(&sc->node_lock);
- an = ath_node_find(sc, (u8 *) addr);
- spin_unlock_bh(&sc->node_lock);
-
- if (!an) {
- DPRINTF(sc, ATH_DBG_AGGR,
- "%s: Node not found to initialize "
- "TX aggregation\n", __func__);
- return -1;
- }
+ an = (struct ath_node *)sta->drv_priv;
if (sc->sc_flags & SC_OP_TXAGGR) {
txtid = ATH_AN_2_TID(an, tid);
- txtid->addba_exchangeinprogress = 1;
+ txtid->state |= AGGR_ADDBA_PROGRESS;
ath_tx_pause_tid(sc, txtid);
}
@@ -2476,24 +2268,31 @@ int ath_tx_aggr_start(struct ath_softc *sc,
/* Stop tx aggregation */
-int ath_tx_aggr_stop(struct ath_softc *sc,
- const u8 *addr,
- u16 tid)
+int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
{
+ struct ath_node *an = (struct ath_node *)sta->drv_priv;
+
+ ath_tx_aggr_teardown(sc, an, tid);
+ return 0;
+}
+
+/* Resume tx aggregation */
+
+void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
+{
+ struct ath_atx_tid *txtid;
struct ath_node *an;
- spin_lock_bh(&sc->node_lock);
- an = ath_node_find(sc, (u8 *) addr);
- spin_unlock_bh(&sc->node_lock);
+ an = (struct ath_node *)sta->drv_priv;
- if (!an) {
- DPRINTF(sc, ATH_DBG_AGGR,
- "%s: TX aggr stop for non-existent node\n", __func__);
- return -1;
+ if (sc->sc_flags & SC_OP_TXAGGR) {
+ txtid = ATH_AN_2_TID(an, tid);
+ txtid->baw_size =
+ IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
+ txtid->state |= AGGR_ADDBA_COMPLETE;
+ txtid->state &= ~AGGR_ADDBA_PROGRESS;
+ ath_tx_resume_tid(sc, txtid);
}
-
- ath_tx_aggr_teardown(sc, an, tid);
- return 0;
}
/*
@@ -2503,21 +2302,18 @@ int ath_tx_aggr_stop(struct ath_softc *sc,
* - Discard all retry frames from the s/w queue.
*/
-void ath_tx_aggr_teardown(struct ath_softc *sc,
- struct ath_node *an, u8 tid)
+void ath_tx_aggr_teardown(struct ath_softc *sc, struct ath_node *an, u8 tid)
{
struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
- struct ath_txq *txq = &sc->sc_txq[txtid->ac->qnum];
+ struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum];
struct ath_buf *bf;
struct list_head bf_head;
INIT_LIST_HEAD(&bf_head);
- DPRINTF(sc, ATH_DBG_AGGR, "%s: teardown TX aggregation\n", __func__);
-
- if (txtid->cleanup_inprogress) /* cleanup is in progress */
+ if (txtid->state & AGGR_CLEANUP) /* cleanup is in progress */
return;
- if (!txtid->addba_exchangecomplete) {
+ if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
txtid->addba_exchangeattempts = 0;
return;
}
@@ -2547,9 +2343,9 @@ void ath_tx_aggr_teardown(struct ath_softc *sc,
if (txtid->baw_head != txtid->baw_tail) {
spin_unlock_bh(&txq->axq_lock);
- txtid->cleanup_inprogress = true;
+ txtid->state |= AGGR_CLEANUP;
} else {
- txtid->addba_exchangecomplete = 0;
+ txtid->state &= ~AGGR_ADDBA_COMPLETE;
txtid->addba_exchangeattempts = 0;
spin_unlock_bh(&txq->axq_lock);
ath_tx_flush_tid(sc, txtid);
@@ -2591,10 +2387,8 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
if (tid->paused) /* check next tid to keep h/w busy */
continue;
- if (!(tid->an->an_smmode == ATH_SM_PWRSAV_DYNAMIC) ||
- ((txq->axq_depth % 2) == 0)) {
+ if ((txq->axq_depth % 2) == 0)
ath_tx_sched_aggr(sc, txq, tid);
- }
/*
* add tid to round-robin queue if more frames
@@ -2625,72 +2419,67 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
{
- if (sc->sc_flags & SC_OP_TXAGGR) {
- struct ath_atx_tid *tid;
- struct ath_atx_ac *ac;
- int tidno, acno;
-
- sc->sc_ht_info.maxampdu = ATH_AMPDU_LIMIT_DEFAULT;
+ struct ath_atx_tid *tid;
+ struct ath_atx_ac *ac;
+ int tidno, acno;
- /*
- * Init per tid tx state
- */
- for (tidno = 0, tid = &an->an_aggr.tx.tid[tidno];
- tidno < WME_NUM_TID;
- tidno++, tid++) {
- tid->an = an;
- tid->tidno = tidno;
- tid->seq_start = tid->seq_next = 0;
- tid->baw_size = WME_MAX_BA;
- tid->baw_head = tid->baw_tail = 0;
- tid->sched = false;
- tid->paused = false;
- tid->cleanup_inprogress = false;
- INIT_LIST_HEAD(&tid->buf_q);
-
- acno = TID_TO_WME_AC(tidno);
- tid->ac = &an->an_aggr.tx.ac[acno];
-
- /* ADDBA state */
- tid->addba_exchangecomplete = 0;
- tid->addba_exchangeinprogress = 0;
- tid->addba_exchangeattempts = 0;
- }
+ /*
+ * Init per tid tx state
+ */
+ for (tidno = 0, tid = &an->tid[tidno];
+ tidno < WME_NUM_TID;
+ tidno++, tid++) {
+ tid->an = an;
+ tid->tidno = tidno;
+ tid->seq_start = tid->seq_next = 0;
+ tid->baw_size = WME_MAX_BA;
+ tid->baw_head = tid->baw_tail = 0;
+ tid->sched = false;
+ tid->paused = false;
+ tid->state &= ~AGGR_CLEANUP;
+ INIT_LIST_HEAD(&tid->buf_q);
+
+ acno = TID_TO_WME_AC(tidno);
+ tid->ac = &an->ac[acno];
+
+ /* ADDBA state */
+ tid->state &= ~AGGR_ADDBA_COMPLETE;
+ tid->state &= ~AGGR_ADDBA_PROGRESS;
+ tid->addba_exchangeattempts = 0;
+ }
- /*
- * Init per ac tx state
- */
- for (acno = 0, ac = &an->an_aggr.tx.ac[acno];
- acno < WME_NUM_AC; acno++, ac++) {
- ac->sched = false;
- INIT_LIST_HEAD(&ac->tid_q);
-
- switch (acno) {
- case WME_AC_BE:
- ac->qnum = ath_tx_get_qnum(sc,
- ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE);
- break;
- case WME_AC_BK:
- ac->qnum = ath_tx_get_qnum(sc,
- ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BK);
- break;
- case WME_AC_VI:
- ac->qnum = ath_tx_get_qnum(sc,
- ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VI);
- break;
- case WME_AC_VO:
- ac->qnum = ath_tx_get_qnum(sc,
- ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VO);
- break;
- }
+ /*
+ * Init per ac tx state
+ */
+ for (acno = 0, ac = &an->ac[acno];
+ acno < WME_NUM_AC; acno++, ac++) {
+ ac->sched = false;
+ INIT_LIST_HEAD(&ac->tid_q);
+
+ switch (acno) {
+ case WME_AC_BE:
+ ac->qnum = ath_tx_get_qnum(sc,
+ ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE);
+ break;
+ case WME_AC_BK:
+ ac->qnum = ath_tx_get_qnum(sc,
+ ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BK);
+ break;
+ case WME_AC_VI:
+ ac->qnum = ath_tx_get_qnum(sc,
+ ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VI);
+ break;
+ case WME_AC_VO:
+ ac->qnum = ath_tx_get_qnum(sc,
+ ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VO);
+ break;
}
}
}
/* Cleanupthe pending buffers for the node. */
-void ath_tx_node_cleanup(struct ath_softc *sc,
- struct ath_node *an, bool bh_flag)
+void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an)
{
int i;
struct ath_atx_ac *ac, *ac_tmp;
@@ -2698,12 +2487,9 @@ void ath_tx_node_cleanup(struct ath_softc *sc,
struct ath_txq *txq;
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
if (ATH_TXQ_SETUP(sc, i)) {
- txq = &sc->sc_txq[i];
+ txq = &sc->tx.txq[i];
- if (likely(bh_flag))
- spin_lock_bh(&txq->axq_lock);
- else
- spin_lock(&txq->axq_lock);
+ spin_lock(&txq->axq_lock);
list_for_each_entry_safe(ac,
ac_tmp, &txq->axq_acq, list) {
@@ -2718,36 +2504,14 @@ void ath_tx_node_cleanup(struct ath_softc *sc,
tid_tmp, &ac->tid_q, list) {
list_del(&tid->list);
tid->sched = false;
- ath_tid_drain(sc, txq, tid, bh_flag);
- tid->addba_exchangecomplete = 0;
+ ath_tid_drain(sc, txq, tid);
+ tid->state &= ~AGGR_ADDBA_COMPLETE;
tid->addba_exchangeattempts = 0;
- tid->cleanup_inprogress = false;
+ tid->state &= ~AGGR_CLEANUP;
}
}
- if (likely(bh_flag))
- spin_unlock_bh(&txq->axq_lock);
- else
- spin_unlock(&txq->axq_lock);
- }
- }
-}
-
-/* Cleanup per node transmit state */
-
-void ath_tx_node_free(struct ath_softc *sc, struct ath_node *an)
-{
- if (sc->sc_flags & SC_OP_TXAGGR) {
- struct ath_atx_tid *tid;
- int tidno, i;
-
- /* Init per tid rx state */
- for (tidno = 0, tid = &an->an_aggr.tx.tid[tidno];
- tidno < WME_NUM_TID;
- tidno++, tid++) {
-
- for (i = 0; i < ATH_TID_MAX_BUFS; i++)
- ASSERT(tid->tx_buf[i] == NULL);
+ spin_unlock(&txq->axq_lock);
}
}
}
@@ -2758,6 +2522,8 @@ void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb)
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ath_tx_control txctl;
+ memset(&txctl, 0, sizeof(struct ath_tx_control));
+
/*
* As a temporary workaround, assign seq# here; this will likely need
* to be cleaned up to work better with Beacon transmission and virtual
@@ -2766,9 +2532,9 @@ void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb)
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
- sc->seq_no += 0x10;
+ sc->tx.seq_no += 0x10;
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
- hdr->seq_ctrl |= cpu_to_le16(sc->seq_no);
+ hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
}
/* Add the padding after the header if this is not already done */
@@ -2776,8 +2542,7 @@ void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb)
if (hdrlen & 3) {
padsize = hdrlen % 4;
if (skb_headroom(skb) < padsize) {
- DPRINTF(sc, ATH_DBG_XMIT, "%s: TX CABQ padding "
- "failed\n", __func__);
+ DPRINTF(sc, ATH_DBG_XMIT, "TX CABQ padding failed\n");
dev_kfree_skb_any(skb);
return;
}
@@ -2785,23 +2550,16 @@ void ath_tx_cabq(struct ath_softc *sc, struct sk_buff *skb)
memmove(skb->data, skb->data + padsize, hdrlen);
}
- DPRINTF(sc, ATH_DBG_XMIT, "%s: transmitting CABQ packet, skb: %p\n",
- __func__,
- skb);
+ txctl.txq = sc->beacon.cabq;
- memset(&txctl, 0, sizeof(struct ath_tx_control));
- txctl.flags = ATH9K_TXDESC_CAB;
- if (ath_tx_prepare(sc, skb, &txctl) == 0) {
- /*
- * Start DMA mapping.
- * ath_tx_start_dma() will be called either synchronously
- * or asynchrounsly once DMA is complete.
- */
- xmit_map_sg(sc, skb, &txctl);
- } else {
- ath_node_put(sc, txctl.an, ATH9K_BH_STATUS_CHANGE);
- DPRINTF(sc, ATH_DBG_XMIT, "%s: TX CABQ failed\n", __func__);
- dev_kfree_skb_any(skb);
+ DPRINTF(sc, ATH_DBG_XMIT, "transmitting CABQ packet, skb: %p\n", skb);
+
+ if (ath_tx_start(sc, skb, &txctl) != 0) {
+ DPRINTF(sc, ATH_DBG_XMIT, "CABQ TX failed\n");
+ goto exit;
}
-}
+ return;
+exit:
+ dev_kfree_skb_any(skb);
+}
diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
index ecb02bdaab5b..350157fcd080 100644
--- a/drivers/net/wireless/atmel.c
+++ b/drivers/net/wireless/atmel.c
@@ -67,7 +67,7 @@
#include <linux/moduleparam.h>
#include <linux/firmware.h>
#include <linux/jiffies.h>
-#include <net/ieee80211.h>
+#include <linux/ieee80211.h>
#include "atmel.h"
#define DRIVER_MAJOR 0
@@ -569,7 +569,7 @@ static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data);
static void atmel_command_irq(struct atmel_private *priv);
static int atmel_validate_channel(struct atmel_private *priv, int channel);
static void atmel_management_frame(struct atmel_private *priv,
- struct ieee80211_hdr_4addr *header,
+ struct ieee80211_hdr *header,
u16 frame_len, u8 rssi);
static void atmel_management_timer(u_long a);
static void atmel_send_command(struct atmel_private *priv, int command,
@@ -577,7 +577,7 @@ static void atmel_send_command(struct atmel_private *priv, int command,
static int atmel_send_command_wait(struct atmel_private *priv, int command,
void *cmd, int cmd_size);
static void atmel_transmit_management_frame(struct atmel_private *priv,
- struct ieee80211_hdr_4addr *header,
+ struct ieee80211_hdr *header,
u8 *body, int body_len);
static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index);
@@ -785,7 +785,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
{
static const u8 SNAP_RFC1024[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
struct atmel_private *priv = netdev_priv(dev);
- struct ieee80211_hdr_4addr header;
+ struct ieee80211_hdr header;
unsigned long flags;
u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
@@ -823,7 +823,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
frame_ctl = IEEE80211_FTYPE_DATA;
header.duration_id = 0;
- header.seq_ctl = 0;
+ header.seq_ctrl = 0;
if (priv->wep_is_on)
frame_ctl |= IEEE80211_FCTL_PROTECTED;
if (priv->operating_mode == IW_MODE_ADHOC) {
@@ -840,7 +840,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
if (priv->use_wpa)
memcpy(&header.addr4, SNAP_RFC1024, 6);
- header.frame_ctl = cpu_to_le16(frame_ctl);
+ header.frame_control = cpu_to_le16(frame_ctl);
/* Copy the wireless header into the card */
atmel_copy_to_card(dev, buff, (unsigned char *)&header, DATA_FRAME_WS_HEADER_SIZE);
/* Copy the packet sans its 802.3 header addresses which have been replaced */
@@ -860,7 +860,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
}
static void atmel_transmit_management_frame(struct atmel_private *priv,
- struct ieee80211_hdr_4addr *header,
+ struct ieee80211_hdr *header,
u8 *body, int body_len)
{
u16 buff;
@@ -876,7 +876,7 @@ static void atmel_transmit_management_frame(struct atmel_private *priv,
}
static void fast_rx_path(struct atmel_private *priv,
- struct ieee80211_hdr_4addr *header,
+ struct ieee80211_hdr *header,
u16 msdu_size, u16 rx_packet_loc, u32 crc)
{
/* fast path: unfragmented packet copy directly into skbuf */
@@ -914,12 +914,11 @@ static void fast_rx_path(struct atmel_private *priv,
}
memcpy(skbp, header->addr1, 6); /* destination address */
- if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
+ if (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FROMDS)
memcpy(&skbp[6], header->addr3, 6);
else
memcpy(&skbp[6], header->addr2, 6); /* source address */
- priv->dev->last_rx = jiffies;
skb->protocol = eth_type_trans(skb, priv->dev);
skb->ip_summed = CHECKSUM_NONE;
netif_rx(skb);
@@ -950,7 +949,7 @@ static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size)
}
static void frag_rx_path(struct atmel_private *priv,
- struct ieee80211_hdr_4addr *header,
+ struct ieee80211_hdr *header,
u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no,
u8 frag_no, int more_frags)
{
@@ -958,7 +957,7 @@ static void frag_rx_path(struct atmel_private *priv,
u8 source[6];
struct sk_buff *skb;
- if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
+ if (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FROMDS)
memcpy(source, header->addr3, 6);
else
memcpy(source, header->addr2, 6);
@@ -1026,7 +1025,6 @@ static void frag_rx_path(struct atmel_private *priv,
memcpy(skb_put(skb, priv->frag_len + 12),
priv->rx_buf,
priv->frag_len + 12);
- priv->dev->last_rx = jiffies;
skb->protocol = eth_type_trans(skb, priv->dev);
skb->ip_summed = CHECKSUM_NONE;
netif_rx(skb);
@@ -1041,7 +1039,7 @@ static void frag_rx_path(struct atmel_private *priv,
static void rx_done_irq(struct atmel_private *priv)
{
int i;
- struct ieee80211_hdr_4addr header;
+ struct ieee80211_hdr header;
for (i = 0;
atmel_rmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head)) == RX_DESC_FLAG_VALID &&
@@ -1068,10 +1066,10 @@ static void rx_done_irq(struct atmel_private *priv)
goto next;
}
- /* Get header as far as end of seq_ctl */
+ /* Get header as far as end of seq_ctrl */
atmel_copy_to_host(priv->dev, (char *)&header, rx_packet_loc, 24);
- frame_ctl = le16_to_cpu(header.frame_ctl);
- seq_control = le16_to_cpu(header.seq_ctl);
+ frame_ctl = le16_to_cpu(header.frame_control);
+ seq_control = le16_to_cpu(header.seq_ctrl);
/* probe for CRC use here if needed once five packets have
arrived with the same crc status, we assume we know what's
@@ -1479,7 +1477,6 @@ struct net_device *init_atmel_card(unsigned short irq, unsigned long port,
struct net_device *dev;
struct atmel_private *priv;
int rc;
- DECLARE_MAC_BUF(mac);
/* Create the network device object. */
dev = alloc_etherdev(sizeof(*priv));
@@ -1591,8 +1588,8 @@ struct net_device *init_atmel_card(unsigned short irq, unsigned long port,
if (!ent)
printk(KERN_WARNING "atmel: unable to create /proc entry.\n");
- printk(KERN_INFO "%s: Atmel at76c50x. Version %d.%d. MAC %s\n",
- dev->name, DRIVER_MAJOR, DRIVER_MINOR, print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "%s: Atmel at76c50x. Version %d.%d. MAC %pM\n",
+ dev->name, DRIVER_MAJOR, DRIVER_MINOR, dev->dev_addr);
return dev;
@@ -1822,7 +1819,7 @@ static int atmel_set_encodeext(struct net_device *dev,
/* Determine and validate the key index */
idx = encoding->flags & IW_ENCODE_INDEX;
if (idx) {
- if (idx < 1 || idx > WEP_KEYS)
+ if (idx < 1 || idx > 4)
return -EINVAL;
idx--;
} else
@@ -1885,7 +1882,7 @@ static int atmel_get_encodeext(struct net_device *dev,
idx = encoding->flags & IW_ENCODE_INDEX;
if (idx) {
- if (idx < 1 || idx > WEP_KEYS)
+ if (idx < 1 || idx > 4)
return -EINVAL;
idx--;
} else
@@ -2800,7 +2797,7 @@ static void handle_beacon_probe(struct atmel_private *priv, u16 capability,
u8 channel)
{
int rejoin = 0;
- int new = capability & MFIE_TYPE_POWER_CONSTRAINT ?
+ int new = capability & WLAN_CAPABILITY_SHORT_PREAMBLE ?
SHORT_PREAMBLE : LONG_PREAMBLE;
if (priv->preamble != new) {
@@ -2829,19 +2826,19 @@ static void handle_beacon_probe(struct atmel_private *priv, u16 capability,
static void send_authentication_request(struct atmel_private *priv, u16 system,
u8 *challenge, int challenge_len)
{
- struct ieee80211_hdr_4addr header;
+ struct ieee80211_hdr header;
struct auth_body auth;
- header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
+ header.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH);
header.duration_id = cpu_to_le16(0x8000);
- header.seq_ctl = 0;
+ header.seq_ctrl = 0;
memcpy(header.addr1, priv->CurrentBSSID, 6);
memcpy(header.addr2, priv->dev->dev_addr, 6);
memcpy(header.addr3, priv->CurrentBSSID, 6);
if (priv->wep_is_on && priv->CurrentAuthentTransactionSeqNum != 1)
/* no WEP for authentication frames with TrSeqNo 1 */
- header.frame_ctl |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+ header.frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
auth.alg = cpu_to_le16(system);
@@ -2864,7 +2861,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
{
u8 *ssid_el_p;
int bodysize;
- struct ieee80211_hdr_4addr header;
+ struct ieee80211_hdr header;
struct ass_req_format {
__le16 capability;
__le16 listen_interval;
@@ -2877,10 +2874,10 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
u8 rates[4];
} body;
- header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ header.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
(is_reassoc ? IEEE80211_STYPE_REASSOC_REQ : IEEE80211_STYPE_ASSOC_REQ));
header.duration_id = cpu_to_le16(0x8000);
- header.seq_ctl = 0;
+ header.seq_ctrl = 0;
memcpy(header.addr1, priv->CurrentBSSID, 6);
memcpy(header.addr2, priv->dev->dev_addr, 6);
@@ -2890,7 +2887,7 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
if (priv->wep_is_on)
body.capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
if (priv->preamble == SHORT_PREAMBLE)
- body.capability |= cpu_to_le16(MFIE_TYPE_POWER_CONSTRAINT);
+ body.capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE);
body.listen_interval = cpu_to_le16(priv->listen_interval * priv->beacon_period);
@@ -2904,10 +2901,10 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
bodysize = 12 + priv->SSID_size;
}
- ssid_el_p[0] = MFIE_TYPE_SSID;
+ ssid_el_p[0] = WLAN_EID_SSID;
ssid_el_p[1] = priv->SSID_size;
memcpy(ssid_el_p + 2, priv->SSID, priv->SSID_size);
- ssid_el_p[2 + priv->SSID_size] = MFIE_TYPE_RATES;
+ ssid_el_p[2 + priv->SSID_size] = WLAN_EID_SUPP_RATES;
ssid_el_p[3 + priv->SSID_size] = 4; /* len of suported rates */
memcpy(ssid_el_p + 4 + priv->SSID_size, atmel_basic_rates, 4);
@@ -2915,9 +2912,9 @@ static void send_association_request(struct atmel_private *priv, int is_reassoc)
}
static int is_frame_from_current_bss(struct atmel_private *priv,
- struct ieee80211_hdr_4addr *header)
+ struct ieee80211_hdr *header)
{
- if (le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_FROMDS)
+ if (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FROMDS)
return memcmp(header->addr3, priv->CurrentBSSID, 6) == 0;
else
return memcmp(header->addr2, priv->CurrentBSSID, 6) == 0;
@@ -2965,7 +2962,7 @@ static int retrieve_bss(struct atmel_private *priv)
}
static void store_bss_info(struct atmel_private *priv,
- struct ieee80211_hdr_4addr *header, u16 capability,
+ struct ieee80211_hdr *header, u16 capability,
u16 beacon_period, u8 channel, u8 rssi, u8 ssid_len,
u8 *ssid, int is_beacon)
{
@@ -3004,7 +3001,7 @@ static void store_bss_info(struct atmel_private *priv,
else if (capability & WLAN_CAPABILITY_ESS)
priv->BSSinfo[index].BSStype =IW_MODE_INFRA;
- priv->BSSinfo[index].preamble = capability & MFIE_TYPE_POWER_CONSTRAINT ?
+ priv->BSSinfo[index].preamble = capability & WLAN_CAPABILITY_SHORT_PREAMBLE ?
SHORT_PREAMBLE : LONG_PREAMBLE;
}
@@ -3040,7 +3037,7 @@ static void authenticate(struct atmel_private *priv, u16 frame_len)
}
} else if (system == WLAN_AUTH_SHARED_KEY) {
if (trans_seq_no == 0x0002 &&
- auth->el_id == MFIE_TYPE_CHALLENGE) {
+ auth->el_id == WLAN_EID_CHALLENGE) {
send_authentication_request(priv, system, auth->chall_text, auth->chall_text_len);
return;
} else if (trans_seq_no == 0x0004) {
@@ -3183,7 +3180,7 @@ static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype)
}
}
-void atmel_join_bss(struct atmel_private *priv, int bss_index)
+static void atmel_join_bss(struct atmel_private *priv, int bss_index)
{
struct bss_info *bss = &priv->BSSinfo[bss_index];
@@ -3291,12 +3288,12 @@ static void atmel_smooth_qual(struct atmel_private *priv)
/* deals with incoming managment frames. */
static void atmel_management_frame(struct atmel_private *priv,
- struct ieee80211_hdr_4addr *header,
+ struct ieee80211_hdr *header,
u16 frame_len, u8 rssi)
{
u16 subtype;
- subtype = le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_STYPE;
+ subtype = le16_to_cpu(header->frame_control) & IEEE80211_FCTL_STYPE;
switch (subtype) {
case IEEE80211_STYPE_BEACON:
case IEEE80211_STYPE_PROBE_RESP:
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index 427b8203e3f9..a53c378e7484 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -718,7 +718,6 @@ struct b43_wldev {
bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */
bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */
- bool short_slot; /* TRUE, if short slot timing is enabled. */
bool radio_hw_enable; /* saved state of radio hardware enabled state */
bool suspend_in_progress; /* TRUE, if we are in a suspend/resume cycle */
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
index 06a01da80160..e04fc91f569e 100644
--- a/drivers/net/wireless/b43/debugfs.c
+++ b/drivers/net/wireless/b43/debugfs.c
@@ -731,6 +731,7 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev)
add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0);
add_dyn_dbg("debug_lo", B43_DBG_LO, 0);
add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0);
+ add_dyn_dbg("debug_keys", B43_DBG_KEYS, 0);
#undef add_dyn_dbg
}
diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h
index 22ffd02ba554..7886cbe2d1d1 100644
--- a/drivers/net/wireless/b43/debugfs.h
+++ b/drivers/net/wireless/b43/debugfs.h
@@ -12,6 +12,7 @@ enum b43_dyndbg { /* Dynamic debugging features */
B43_DBG_PWORK_STOP,
B43_DBG_LO,
B43_DBG_FIRMWARE,
+ B43_DBG_KEYS,
__B43_NR_DYNDBG,
};
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 098f886976f6..6d65a02b7052 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -1387,13 +1387,11 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
info = IEEE80211_SKB_CB(meta->skb);
- memset(&info->status, 0, sizeof(info->status));
-
/*
* Call back to inform the ieee80211 subsystem about
* the status of the transmission.
*/
- frame_succeed = b43_fill_txstatus_report(info, status);
+ frame_succeed = b43_fill_txstatus_report(dev, info, status);
#ifdef CONFIG_B43_DEBUG
if (frame_succeed)
ring->nr_succeed_tx_packets++;
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 14c44df584d0..7b31a327b24a 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -703,13 +703,11 @@ static void b43_set_slot_time(struct b43_wldev *dev, u16 slot_time)
static void b43_short_slot_timing_enable(struct b43_wldev *dev)
{
b43_set_slot_time(dev, 9);
- dev->short_slot = 1;
}
static void b43_short_slot_timing_disable(struct b43_wldev *dev)
{
b43_set_slot_time(dev, 20);
- dev->short_slot = 0;
}
/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
@@ -994,6 +992,52 @@ static void b43_clear_keys(struct b43_wldev *dev)
b43_key_clear(dev, i);
}
+static void b43_dump_keymemory(struct b43_wldev *dev)
+{
+ unsigned int i, index, offset;
+ DECLARE_MAC_BUF(macbuf);
+ u8 mac[ETH_ALEN];
+ u16 algo;
+ u32 rcmta0;
+ u16 rcmta1;
+ u64 hf;
+ struct b43_key *key;
+
+ if (!b43_debug(dev, B43_DBG_KEYS))
+ return;
+
+ hf = b43_hf_read(dev);
+ b43dbg(dev->wl, "Hardware key memory dump: USEDEFKEYS=%u\n",
+ !!(hf & B43_HF_USEDEFKEYS));
+ for (index = 0; index < dev->max_nr_keys; index++) {
+ key = &(dev->key[index]);
+ printk(KERN_DEBUG "Key slot %02u: %s",
+ index, (key->keyconf == NULL) ? " " : "*");
+ offset = dev->ktp + (index * B43_SEC_KEYSIZE);
+ for (i = 0; i < B43_SEC_KEYSIZE; i += 2) {
+ u16 tmp = b43_shm_read16(dev, B43_SHM_SHARED, offset + i);
+ printk("%02X%02X", (tmp & 0xFF), ((tmp >> 8) & 0xFF));
+ }
+
+ algo = b43_shm_read16(dev, B43_SHM_SHARED,
+ B43_SHM_SH_KEYIDXBLOCK + (index * 2));
+ printk(" Algo: %04X/%02X", algo, key->algorithm);
+
+ if (index >= 4) {
+ rcmta0 = b43_shm_read32(dev, B43_SHM_RCMTA,
+ ((index - 4) * 2) + 0);
+ rcmta1 = b43_shm_read16(dev, B43_SHM_RCMTA,
+ ((index - 4) * 2) + 1);
+ *((__le32 *)(&mac[0])) = cpu_to_le32(rcmta0);
+ *((__le16 *)(&mac[4])) = cpu_to_le16(rcmta1);
+ printk(" MAC: %s",
+ print_mac(macbuf, mac));
+ } else
+ printk(" DEFAULT KEY");
+ printk("\n");
+ }
+}
+
void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags)
{
u32 macctl;
@@ -1339,25 +1383,6 @@ u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev,
return antenna_nr;
}
-static int b43_antenna_from_ieee80211(struct b43_wldev *dev, u8 antenna)
-{
- antenna = b43_ieee80211_antenna_sanitize(dev, antenna);
- switch (antenna) {
- case 0: /* default/diversity */
- return B43_ANTENNA_DEFAULT;
- case 1: /* Antenna 0 */
- return B43_ANTENNA0;
- case 2: /* Antenna 1 */
- return B43_ANTENNA1;
- case 3: /* Antenna 2 */
- return B43_ANTENNA2;
- case 4: /* Antenna 3 */
- return B43_ANTENNA3;
- default:
- return B43_ANTENNA_DEFAULT;
- }
-}
-
/* Convert a b43 antenna number value to the PHY TX control value. */
static u16 b43_antenna_to_phyctl(int antenna)
{
@@ -1399,7 +1424,7 @@ static void b43_write_beacon_template(struct b43_wldev *dev,
len, ram_offset, shm_size_offset, rate);
/* Write the PHY TX control parameters. */
- antenna = b43_antenna_from_ieee80211(dev, info->antenna_sel_tx);
+ antenna = B43_ANTENNA_DEFAULT;
antenna = b43_antenna_to_phyctl(antenna);
ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL);
/* We can't send beacons with short preamble. Would get PHY errors. */
@@ -1693,25 +1718,6 @@ static void b43_update_templates(struct b43_wl *wl)
queue_work(wl->hw->workqueue, &wl->beacon_update_trigger);
}
-static void b43_set_ssid(struct b43_wldev *dev, const u8 * ssid, u8 ssid_len)
-{
- u32 tmp;
- u16 i, len;
-
- len = min((u16) ssid_len, (u16) 0x100);
- for (i = 0; i < len; i += sizeof(u32)) {
- tmp = (u32) (ssid[i + 0]);
- if (i + 1 < len)
- tmp |= (u32) (ssid[i + 1]) << 8;
- if (i + 2 < len)
- tmp |= (u32) (ssid[i + 2]) << 16;
- if (i + 3 < len)
- tmp |= (u32) (ssid[i + 3]) << 24;
- b43_shm_write32(dev, B43_SHM_SHARED, 0x380 + i, tmp);
- }
- b43_shm_write16(dev, B43_SHM_SHARED, 0x48, len);
-}
-
static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int)
{
b43_time_lock(dev);
@@ -3339,15 +3345,31 @@ init_failure:
return err;
}
-static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+/* Write the short and long frame retry limit values. */
+static void b43_set_retry_limits(struct b43_wldev *dev,
+ unsigned int short_retry,
+ unsigned int long_retry)
+{
+ /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing
+ * the chip-internal counter. */
+ short_retry = min(short_retry, (unsigned int)0xF);
+ long_retry = min(long_retry, (unsigned int)0xF);
+
+ b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_SRLIMIT,
+ short_retry);
+ b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_LRLIMIT,
+ long_retry);
+}
+
+static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev;
struct b43_phy *phy;
+ struct ieee80211_conf *conf = &hw->conf;
unsigned long flags;
int antenna;
int err = 0;
- u32 savedirqs;
mutex_lock(&wl->mutex);
@@ -3358,33 +3380,20 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
dev = wl->current_dev;
phy = &dev->phy;
- /* Disable IRQs while reconfiguring the device.
- * This makes it possible to drop the spinlock throughout
- * the reconfiguration process. */
- spin_lock_irqsave(&wl->irq_lock, flags);
- if (b43_status(dev) < B43_STAT_STARTED) {
- spin_unlock_irqrestore(&wl->irq_lock, flags);
- goto out_unlock_mutex;
- }
- savedirqs = b43_interrupt_disable(dev, B43_IRQ_ALL);
- spin_unlock_irqrestore(&wl->irq_lock, flags);
- b43_synchronize_irq(dev);
+ b43_mac_suspend(dev);
+
+ if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+ b43_set_retry_limits(dev, conf->short_frame_max_tx_count,
+ conf->long_frame_max_tx_count);
+ changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS;
+ if (!changed)
+ goto out_mac_enable;
/* Switch to the requested channel.
* The firmware takes care of races with the TX handler. */
if (conf->channel->hw_value != phy->channel)
b43_switch_channel(dev, conf->channel->hw_value);
- /* Enable/Disable ShortSlot timing. */
- if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)) !=
- dev->short_slot) {
- B43_WARN_ON(phy->type != B43_PHYTYPE_G);
- if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)
- b43_short_slot_timing_enable(dev);
- else
- b43_short_slot_timing_disable(dev);
- }
-
dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
/* Adjust the desired TX power level. */
@@ -3399,9 +3408,9 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
}
/* Antennas for RX and management frame TX. */
- antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_tx);
+ antenna = B43_ANTENNA_DEFAULT;
b43_mgmtframe_txantenna(dev, antenna);
- antenna = b43_antenna_from_ieee80211(dev, conf->antenna_sel_rx);
+ antenna = B43_ANTENNA_DEFAULT;
if (phy->ops->set_rx_antenna)
phy->ops->set_rx_antenna(dev, antenna);
@@ -3425,16 +3434,91 @@ static int b43_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
}
}
- spin_lock_irqsave(&wl->irq_lock, flags);
- b43_interrupt_enable(dev, savedirqs);
- mmiowb();
- spin_unlock_irqrestore(&wl->irq_lock, flags);
- out_unlock_mutex:
+out_mac_enable:
+ b43_mac_enable(dev);
+out_unlock_mutex:
mutex_unlock(&wl->mutex);
return err;
}
+static void b43_update_basic_rates(struct b43_wldev *dev, u64 brates)
+{
+ struct ieee80211_supported_band *sband =
+ dev->wl->hw->wiphy->bands[b43_current_band(dev->wl)];
+ struct ieee80211_rate *rate;
+ int i;
+ u16 basic, direct, offset, basic_offset, rateptr;
+
+ for (i = 0; i < sband->n_bitrates; i++) {
+ rate = &sband->bitrates[i];
+
+ if (b43_is_cck_rate(rate->hw_value)) {
+ direct = B43_SHM_SH_CCKDIRECT;
+ basic = B43_SHM_SH_CCKBASIC;
+ offset = b43_plcp_get_ratecode_cck(rate->hw_value);
+ offset &= 0xF;
+ } else {
+ direct = B43_SHM_SH_OFDMDIRECT;
+ basic = B43_SHM_SH_OFDMBASIC;
+ offset = b43_plcp_get_ratecode_ofdm(rate->hw_value);
+ offset &= 0xF;
+ }
+
+ rate = ieee80211_get_response_rate(sband, brates, rate->bitrate);
+
+ if (b43_is_cck_rate(rate->hw_value)) {
+ basic_offset = b43_plcp_get_ratecode_cck(rate->hw_value);
+ basic_offset &= 0xF;
+ } else {
+ basic_offset = b43_plcp_get_ratecode_ofdm(rate->hw_value);
+ basic_offset &= 0xF;
+ }
+
+ /*
+ * Get the pointer that we need to point to
+ * from the direct map
+ */
+ rateptr = b43_shm_read16(dev, B43_SHM_SHARED,
+ direct + 2 * basic_offset);
+ /* and write it to the basic map */
+ b43_shm_write16(dev, B43_SHM_SHARED, basic + 2 * offset,
+ rateptr);
+ }
+}
+
+static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *conf,
+ u32 changed)
+{
+ struct b43_wl *wl = hw_to_b43_wl(hw);
+ struct b43_wldev *dev;
+
+ mutex_lock(&wl->mutex);
+
+ dev = wl->current_dev;
+ if (!dev || b43_status(dev) < B43_STAT_STARTED)
+ goto out_unlock_mutex;
+ b43_mac_suspend(dev);
+
+ if (changed & BSS_CHANGED_BASIC_RATES)
+ b43_update_basic_rates(dev, conf->basic_rates);
+
+ if (changed & BSS_CHANGED_ERP_SLOT) {
+ if (conf->use_short_slot)
+ b43_short_slot_timing_enable(dev);
+ else
+ b43_short_slot_timing_disable(dev);
+ }
+
+ b43_mac_enable(dev);
+out_unlock_mutex:
+ mutex_unlock(&wl->mutex);
+
+ return;
+}
+
static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
const u8 *local_addr, const u8 *addr,
struct ieee80211_key_conf *key)
@@ -3445,7 +3529,6 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
u8 algorithm;
u8 index;
int err;
- DECLARE_MAC_BUF(mac);
if (modparam_nohwcrypt)
return -ENOSPC; /* User disabled HW-crypto */
@@ -3528,15 +3611,18 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
default:
B43_WARN_ON(1);
}
+
out_unlock:
- spin_unlock_irqrestore(&wl->irq_lock, flags);
- mutex_unlock(&wl->mutex);
if (!err) {
b43dbg(wl, "%s hardware based encryption for keyidx: %d, "
- "mac: %s\n",
+ "mac: %pM\n",
cmd == SET_KEY ? "Using" : "Disabling", key->keyidx,
- print_mac(mac, addr));
+ addr);
+ b43_dump_keymemory(dev);
}
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+ mutex_unlock(&wl->mutex);
+
return err;
}
@@ -3598,8 +3684,6 @@ static int b43_op_config_interface(struct ieee80211_hw *hw,
if (b43_is_mode(wl, NL80211_IFTYPE_AP) ||
b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) {
B43_WARN_ON(vif->type != wl->if_type);
- if (conf->changed & IEEE80211_IFCC_SSID)
- b43_set_ssid(dev, conf->ssid, conf->ssid_len);
if (conf->changed & IEEE80211_IFCC_BEACON)
b43_update_templates(wl);
} else if (b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) {
@@ -3878,22 +3962,6 @@ static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
#endif /* CONFIG_SSB_DRIVER_PCICORE */
}
-/* Write the short and long frame retry limit values. */
-static void b43_set_retry_limits(struct b43_wldev *dev,
- unsigned int short_retry,
- unsigned int long_retry)
-{
- /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing
- * the chip-internal counter. */
- short_retry = min(short_retry, (unsigned int)0xF);
- long_retry = min(long_retry, (unsigned int)0xF);
-
- b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_SRLIMIT,
- short_retry);
- b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_LRLIMIT,
- long_retry);
-}
-
static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle)
{
u16 pu_delay;
@@ -4214,26 +4282,6 @@ static void b43_op_stop(struct ieee80211_hw *hw)
cancel_work_sync(&(wl->txpower_adjust_work));
}
-static int b43_op_set_retry_limit(struct ieee80211_hw *hw,
- u32 short_retry_limit, u32 long_retry_limit)
-{
- struct b43_wl *wl = hw_to_b43_wl(hw);
- struct b43_wldev *dev;
- int err = 0;
-
- mutex_lock(&wl->mutex);
- dev = wl->current_dev;
- if (unlikely(!dev || (b43_status(dev) < B43_STAT_INITIALIZED))) {
- err = -ENODEV;
- goto out_unlock;
- }
- b43_set_retry_limits(dev, short_retry_limit, long_retry_limit);
-out_unlock:
- mutex_unlock(&wl->mutex);
-
- return err;
-}
-
static int b43_op_beacon_set_tim(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, bool set)
{
@@ -4263,6 +4311,7 @@ static const struct ieee80211_ops b43_hw_ops = {
.add_interface = b43_op_add_interface,
.remove_interface = b43_op_remove_interface,
.config = b43_op_config,
+ .bss_info_changed = b43_op_bss_info_changed,
.config_interface = b43_op_config_interface,
.configure_filter = b43_op_configure_filter,
.set_key = b43_op_set_key,
@@ -4270,7 +4319,6 @@ static const struct ieee80211_ops b43_hw_ops = {
.get_tx_stats = b43_op_get_tx_stats,
.start = b43_op_start,
.stop = b43_op_stop,
- .set_retry_limit = b43_op_set_retry_limit,
.set_tim = b43_op_beacon_set_tim,
.sta_notify = b43_op_sta_notify,
};
@@ -4588,7 +4636,7 @@ static int b43_wireless_init(struct ssb_device *dev)
BIT(NL80211_IFTYPE_ADHOC);
hw->queues = b43_modparam_qos ? 4 : 1;
- hw->max_altrates = 1;
+ hw->max_rates = 2;
SET_IEEE80211_DEV(hw, dev->dev);
if (is_valid_ether_addr(sprom->et1mac))
SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
diff --git a/drivers/net/wireless/b43/phy_a.c b/drivers/net/wireless/b43/phy_a.c
index 0f1a84c9de61..7fe9d1701624 100644
--- a/drivers/net/wireless/b43/phy_a.c
+++ b/drivers/net/wireless/b43/phy_a.c
@@ -77,7 +77,7 @@ static s8 b43_aphy_estimate_power_out(struct b43_wldev *dev, s8 tssi)
}
#endif
-void b43_radio_set_tx_iq(struct b43_wldev *dev)
+static void b43_radio_set_tx_iq(struct b43_wldev *dev)
{
static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 };
static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A };
@@ -147,7 +147,7 @@ static void aphy_channel_switch(struct b43_wldev *dev, unsigned int channel)
//FIXME b43_phy_xmitpower(dev);
}
-void b43_radio_init2060(struct b43_wldev *dev)
+static void b43_radio_init2060(struct b43_wldev *dev)
{
b43_radio_write16(dev, 0x0004, 0x00C0);
b43_radio_write16(dev, 0x0005, 0x0008);
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index af37abccccb3..026b61c03fb9 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -178,13 +178,27 @@ void b43_phy_unlock(struct b43_wldev *dev)
b43_power_saving_ctl_bits(dev, 0);
}
+static inline void assert_mac_suspended(struct b43_wldev *dev)
+{
+ if (!B43_DEBUG)
+ return;
+ if ((b43_status(dev) >= B43_STAT_INITIALIZED) &&
+ (dev->mac_suspended <= 0)) {
+ b43dbg(dev->wl, "PHY/RADIO register access with "
+ "enabled MAC.\n");
+ dump_stack();
+ }
+}
+
u16 b43_radio_read(struct b43_wldev *dev, u16 reg)
{
+ assert_mac_suspended(dev);
return dev->phy.ops->radio_read(dev, reg);
}
void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
{
+ assert_mac_suspended(dev);
dev->phy.ops->radio_write(dev, reg, value);
}
@@ -208,11 +222,13 @@ void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
u16 b43_phy_read(struct b43_wldev *dev, u16 reg)
{
+ assert_mac_suspended(dev);
return dev->phy.ops->phy_read(dev, reg);
}
void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value)
{
+ assert_mac_suspended(dev);
dev->phy.ops->phy_write(dev, reg, value);
}
@@ -280,8 +296,10 @@ void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state)
state = RFKILL_STATE_SOFT_BLOCKED;
}
+ b43_mac_suspend(dev);
phy->ops->software_rfkill(dev, state);
phy->radio_on = (state == RFKILL_STATE_UNBLOCKED);
+ b43_mac_enable(dev);
}
/**
diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c
index 232181f6333c..caac4a45f0bf 100644
--- a/drivers/net/wireless/b43/phy_g.c
+++ b/drivers/net/wireless/b43/phy_g.c
@@ -54,7 +54,7 @@ static const s8 b43_tssi2dbm_g_table[] = {
-20, -20, -20, -20,
};
-const u8 b43_radio_channel_codes_bg[] = {
+static const u8 b43_radio_channel_codes_bg[] = {
12, 17, 22, 27,
32, 37, 42, 47,
52, 57, 62, 67,
@@ -215,9 +215,9 @@ void b43_gphy_set_baseband_attenuation(struct b43_wldev *dev,
}
/* Adjust the transmission power output (G-PHY) */
-void b43_set_txpower_g(struct b43_wldev *dev,
- const struct b43_bbatt *bbatt,
- const struct b43_rfatt *rfatt, u8 tx_control)
+static void b43_set_txpower_g(struct b43_wldev *dev,
+ const struct b43_bbatt *bbatt,
+ const struct b43_rfatt *rfatt, u8 tx_control)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
@@ -383,14 +383,14 @@ static void b43_set_original_gains(struct b43_wldev *dev)
}
/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
-void b43_nrssi_hw_write(struct b43_wldev *dev, u16 offset, s16 val)
+static void b43_nrssi_hw_write(struct b43_wldev *dev, u16 offset, s16 val)
{
b43_phy_write(dev, B43_PHY_NRSSILT_CTRL, offset);
b43_phy_write(dev, B43_PHY_NRSSILT_DATA, (u16) val);
}
/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
-s16 b43_nrssi_hw_read(struct b43_wldev *dev, u16 offset)
+static s16 b43_nrssi_hw_read(struct b43_wldev *dev, u16 offset)
{
u16 val;
@@ -401,7 +401,7 @@ s16 b43_nrssi_hw_read(struct b43_wldev *dev, u16 offset)
}
/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
-void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val)
+static void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val)
{
u16 i;
s16 tmp;
@@ -415,7 +415,7 @@ void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val)
}
/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */
-void b43_nrssi_mem_update(struct b43_wldev *dev)
+static void b43_nrssi_mem_update(struct b43_wldev *dev)
{
struct b43_phy_g *gphy = dev->phy.g;
s16 i, delta;
@@ -589,7 +589,7 @@ static void b43_calc_nrssi_offset(struct b43_wldev *dev)
b43_phy_write(dev, 0x0811, backup[1]);
}
-void b43_calc_nrssi_slope(struct b43_wldev *dev)
+static void b43_calc_nrssi_slope(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
@@ -1354,7 +1354,7 @@ struct init2050_saved_values {
u16 phy_syncctl;
};
-u16 b43_radio_init2050(struct b43_wldev *dev)
+static u16 b43_radio_init2050(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
struct init2050_saved_values sav;
@@ -3047,6 +3047,8 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)
int rfatt, bbatt;
u8 tx_control;
+ b43_mac_suspend(dev);
+
spin_lock_irq(&dev->wl->irq_lock);
/* Calculate the new attenuation values. */
@@ -3103,6 +3105,8 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev)
gphy->tx_control);
b43_radio_unlock(dev);
b43_phy_unlock(dev);
+
+ b43_mac_enable(dev);
}
static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev,
@@ -3215,9 +3219,9 @@ static void b43_gphy_op_pwork_15sec(struct b43_wldev *dev)
struct b43_phy *phy = &dev->phy;
struct b43_phy_g *gphy = phy->g;
+ b43_mac_suspend(dev);
//TODO: update_aci_moving_average
if (gphy->aci_enable && gphy->aci_wlan_automatic) {
- b43_mac_suspend(dev);
if (!gphy->aci_enable && 1 /*TODO: not scanning? */ ) {
if (0 /*TODO: bunch of conditions */ ) {
phy->ops->interf_mitigation(dev,
@@ -3227,12 +3231,12 @@ static void b43_gphy_op_pwork_15sec(struct b43_wldev *dev)
if (/*(aci_average > 1000) &&*/ !b43_gphy_aci_scan(dev))
phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE);
}
- b43_mac_enable(dev);
} else if (gphy->interfmode == B43_INTERFMODE_NONWLAN &&
phy->rev == 1) {
//TODO: implement rev1 workaround
}
b43_lo_g_maintanance_work(dev);
+ b43_mac_enable(dev);
}
static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev)
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 401591267592..1036bef8c4cc 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -587,9 +587,8 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev,
spin_lock(&q->lock); /* IRQs are already disabled. */
info = IEEE80211_SKB_CB(pack->skb);
- memset(&info->status, 0, sizeof(info->status));
- b43_fill_txstatus_report(info, status);
+ b43_fill_txstatus_report(dev, info, status);
total_len = pack->skb->len + b43_txhdr_size(dev);
total_len = roundup(total_len, 4);
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 2fabcf8f0474..eae9b8052658 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -46,7 +46,6 @@ static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp)
case 0x6E:
return 3;
}
- B43_WARN_ON(1);
return -1;
}
@@ -73,7 +72,6 @@ static u8 b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy)
case 0xC:
return base + 7;
}
- B43_WARN_ON(1);
return -1;
}
@@ -185,7 +183,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
u8 *_txhdr,
const unsigned char *fragment_data,
unsigned int fragment_len,
- const struct ieee80211_tx_info *info,
+ struct ieee80211_tx_info *info,
u16 cookie)
{
struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr;
@@ -202,6 +200,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
u16 phy_ctl = 0;
u8 extra_ft = 0;
struct ieee80211_rate *txrate;
+ struct ieee80211_tx_rate *rates;
memset(txhdr, 0, sizeof(*txhdr));
@@ -291,7 +290,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
phy_ctl |= B43_TXH_PHY_ENC_OFDM;
else
phy_ctl |= B43_TXH_PHY_ENC_CCK;
- if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE)
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
phy_ctl |= B43_TXH_PHY_SHORTPRMBL;
switch (b43_ieee80211_antenna_sanitize(dev, info->antenna_sel_tx)) {
@@ -314,6 +313,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
B43_WARN_ON(1);
}
+ rates = info->control.rates;
/* MAC control */
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
mac_ctl |= B43_TXH_MAC_ACK;
@@ -324,12 +324,22 @@ int b43_generate_txhdr(struct b43_wldev *dev,
mac_ctl |= B43_TXH_MAC_STMSDU;
if (phy->type == B43_PHYTYPE_A)
mac_ctl |= B43_TXH_MAC_5GHZ;
- if (info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT)
+
+ /* Overwrite rates[0].count to make the retry calculation
+ * in the tx status easier. need the actual retry limit to
+ * detect whether the fallback rate was used.
+ */
+ if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
+ (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) {
+ rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count;
mac_ctl |= B43_TXH_MAC_LONGFRAME;
+ } else {
+ rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count;
+ }
/* Generate the RTS or CTS-to-self frame */
- if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) ||
- (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) {
+ if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
+ (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) {
unsigned int len;
struct ieee80211_hdr *hdr;
int rts_rate, rts_rate_fb;
@@ -344,7 +354,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
rts_rate_fb = b43_calc_fallback_rate(rts_rate);
rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb);
- if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
+ if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
struct ieee80211_cts *cts;
if (b43_is_old_txhdr_format(dev)) {
@@ -596,6 +606,8 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
phytype == B43_PHYTYPE_A);
else
status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
+ if (unlikely(status.rate_idx == -1))
+ goto drop;
status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT);
/*
@@ -687,10 +699,18 @@ void b43_handle_txstatus(struct b43_wldev *dev,
/* Fill out the mac80211 TXstatus report based on the b43-specific
* txstatus report data. This returns a boolean whether the frame was
* successfully transmitted. */
-bool b43_fill_txstatus_report(struct ieee80211_tx_info *report,
+bool b43_fill_txstatus_report(struct b43_wldev *dev,
+ struct ieee80211_tx_info *report,
const struct b43_txstatus *status)
{
bool frame_success = 1;
+ int retry_limit;
+
+ /* preserve the confiured retry limit before clearing the status
+ * The xmit function has overwritten the rc's value with the actual
+ * retry limit done by the hardware */
+ retry_limit = report->status.rates[0].count;
+ ieee80211_tx_info_clear_status(report);
if (status->acked) {
/* The frame was ACKed. */
@@ -700,14 +720,32 @@ bool b43_fill_txstatus_report(struct ieee80211_tx_info *report,
if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) {
/* ...but we expected an ACK. */
frame_success = 0;
- report->status.excessive_retries = 1;
}
}
if (status->frame_count == 0) {
/* The frame was not transmitted at all. */
- report->status.retry_count = 0;
- } else
- report->status.retry_count = status->frame_count - 1;
+ report->status.rates[0].count = 0;
+ } else if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) {
+ /*
+ * If the short retries (RTS, not data frame) have exceeded
+ * the limit, the hw will not have tried the selected rate,
+ * but will have used the fallback rate instead.
+ * Don't let the rate control count attempts for the selected
+ * rate in this case, otherwise the statistics will be off.
+ */
+ report->status.rates[0].count = 0;
+ report->status.rates[1].count = status->frame_count;
+ } else {
+ if (status->frame_count > retry_limit) {
+ report->status.rates[0].count = retry_limit;
+ report->status.rates[1].count = status->frame_count -
+ retry_limit;
+
+ } else {
+ report->status.rates[0].count = status->frame_count;
+ report->status.rates[1].idx = -1;
+ }
+ }
return frame_success;
}
diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h
index 0215faf47541..4fb2a190f7a7 100644
--- a/drivers/net/wireless/b43/xmit.h
+++ b/drivers/net/wireless/b43/xmit.h
@@ -178,7 +178,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
u8 * txhdr,
const unsigned char *fragment_data,
unsigned int fragment_len,
- const struct ieee80211_tx_info *txctl, u16 cookie);
+ struct ieee80211_tx_info *txctl, u16 cookie);
/* Transmit Status */
struct b43_txstatus {
@@ -294,7 +294,8 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr);
void b43_handle_txstatus(struct b43_wldev *dev,
const struct b43_txstatus *status);
-bool b43_fill_txstatus_report(struct ieee80211_tx_info *report,
+bool b43_fill_txstatus_report(struct b43_wldev *dev,
+ struct ieee80211_tx_info *report,
const struct b43_txstatus *status);
void b43_tx_suspend(struct b43_wldev *dev);
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
index c40078e1fff9..97b0e06dfe21 100644
--- a/drivers/net/wireless/b43legacy/b43legacy.h
+++ b/drivers/net/wireless/b43legacy/b43legacy.h
@@ -145,6 +145,10 @@
#define B43legacy_SHM_SH_PRMAXTIME 0x0074 /* Probe Response max time */
#define B43legacy_SHM_SH_PRPHYCTL 0x0188 /* Probe Resp PHY TX control */
/* SHM_SHARED rate tables */
+#define B43legacy_SHM_SH_OFDMDIRECT 0x0480 /* Pointer to OFDM direct map */
+#define B43legacy_SHM_SH_OFDMBASIC 0x04A0 /* Pointer to OFDM basic rate map */
+#define B43legacy_SHM_SH_CCKDIRECT 0x04C0 /* Pointer to CCK direct map */
+#define B43legacy_SHM_SH_CCKBASIC 0x04E0 /* Pointer to CCK basic rate map */
/* SHM_SHARED microcode soft registers */
#define B43legacy_SHM_SH_UCODEREV 0x0000 /* Microcode revision */
#define B43legacy_SHM_SH_UCODEPATCH 0x0002 /* Microcode patchlevel */
@@ -663,7 +667,6 @@ struct b43legacy_wldev {
bool bad_frames_preempt;/* Use "Bad Frames Preemption". */
bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM). */
bool short_preamble; /* TRUE if using short preamble. */
- bool short_slot; /* TRUE if using short slot timing. */
bool radio_hw_enable; /* State of radio hardware enable bit. */
/* PHY/Radio device. */
diff --git a/drivers/net/wireless/b43legacy/debugfs.c b/drivers/net/wireless/b43legacy/debugfs.c
index 03ce0821a60e..1f85ac569fec 100644
--- a/drivers/net/wireless/b43legacy/debugfs.c
+++ b/drivers/net/wireless/b43legacy/debugfs.c
@@ -211,7 +211,7 @@ static ssize_t b43legacy_debugfs_read(struct file *file, char __user *userbuf,
struct b43legacy_dfs_file *dfile;
ssize_t uninitialized_var(ret);
char *buf;
- const size_t bufsize = 1024 * 128;
+ const size_t bufsize = 1024 * 16; /* 16 KiB buffer */
const size_t buforder = get_order(bufsize);
int err = 0;
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c
index fb6819e40f38..3649fc367098 100644
--- a/drivers/net/wireless/b43legacy/dma.c
+++ b/drivers/net/wireless/b43legacy/dma.c
@@ -919,7 +919,7 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
if (!ring->txhdr_cache)
goto err_kfree_meta;
- dma_test = ssb_dma_map_single(dev->dev,
+ dma_test = ssb_dma_map_single(dev->dev,
ring->txhdr_cache,
sizeof(struct b43legacy_txhdr_fw3),
DMA_TO_DEVICE);
@@ -1411,6 +1411,7 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
struct b43legacy_dmaring *ring;
struct b43legacy_dmadesc_generic *desc;
struct b43legacy_dmadesc_meta *meta;
+ int retry_limit;
int slot;
ring = parse_cookie(dev, status->cookie, &slot);
@@ -1437,25 +1438,42 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
struct ieee80211_tx_info *info;
BUG_ON(!meta->skb);
info = IEEE80211_SKB_CB(meta->skb);
- /* Call back to inform the ieee80211 subsystem about the
- * status of the transmission.
- * Some fields of txstat are already filled in dma_tx().
- */
- memset(&info->status, 0, sizeof(info->status));
+ /* preserve the confiured retry limit before clearing the status
+ * The xmit function has overwritten the rc's value with the actual
+ * retry limit done by the hardware */
+ retry_limit = info->status.rates[0].count;
+ ieee80211_tx_info_clear_status(info);
- if (status->acked) {
+ if (status->acked)
info->flags |= IEEE80211_TX_STAT_ACK;
+
+ if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) {
+ /*
+ * If the short retries (RTS, not data frame) have exceeded
+ * the limit, the hw will not have tried the selected rate,
+ * but will have used the fallback rate instead.
+ * Don't let the rate control count attempts for the selected
+ * rate in this case, otherwise the statistics will be off.
+ */
+ info->status.rates[0].count = 0;
+ info->status.rates[1].count = status->frame_count;
} else {
- if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
- info->status.excessive_retries = 1;
+ if (status->frame_count > retry_limit) {
+ info->status.rates[0].count = retry_limit;
+ info->status.rates[1].count = status->frame_count -
+ retry_limit;
+
+ } else {
+ info->status.rates[0].count = status->frame_count;
+ info->status.rates[1].idx = -1;
+ }
}
- if (status->frame_count == 0) {
- /* The frame was not transmitted at all. */
- info->status.retry_count = 0;
- } else
- info->status.retry_count = status->frame_count
- - 1;
+
+ /* Call back to inform the ieee80211 subsystem about the
+ * status of the transmission.
+ * Some fields of txstat are already filled in dma_tx().
+ */
ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb);
/* skb is freed by ieee80211_tx_status_irqsafe() */
meta->skb = NULL;
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index c66d57560e7c..c1324e31d2f6 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -576,13 +576,11 @@ static void b43legacy_set_slot_time(struct b43legacy_wldev *dev,
static void b43legacy_short_slot_timing_enable(struct b43legacy_wldev *dev)
{
b43legacy_set_slot_time(dev, 9);
- dev->short_slot = 1;
}
static void b43legacy_short_slot_timing_disable(struct b43legacy_wldev *dev)
{
b43legacy_set_slot_time(dev, 20);
- dev->short_slot = 0;
}
/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
@@ -1160,29 +1158,6 @@ static void b43legacy_update_templates(struct b43legacy_wl *wl)
wl->beacon1_uploaded = 0;
}
-static void b43legacy_set_ssid(struct b43legacy_wldev *dev,
- const u8 *ssid, u8 ssid_len)
-{
- u32 tmp;
- u16 i;
- u16 len;
-
- len = min((u16)ssid_len, (u16)0x100);
- for (i = 0; i < len; i += sizeof(u32)) {
- tmp = (u32)(ssid[i + 0]);
- if (i + 1 < len)
- tmp |= (u32)(ssid[i + 1]) << 8;
- if (i + 2 < len)
- tmp |= (u32)(ssid[i + 2]) << 16;
- if (i + 3 < len)
- tmp |= (u32)(ssid[i + 3]) << 24;
- b43legacy_shm_write32(dev, B43legacy_SHM_SHARED,
- 0x380 + i, tmp);
- }
- b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
- 0x48, len);
-}
-
static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev,
u16 beacon_int)
{
@@ -2556,26 +2531,27 @@ init_failure:
return err;
}
-static int b43legacy_antenna_from_ieee80211(u8 antenna)
+/* Write the short and long frame retry limit values. */
+static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev,
+ unsigned int short_retry,
+ unsigned int long_retry)
{
- switch (antenna) {
- case 0: /* default/diversity */
- return B43legacy_ANTENNA_DEFAULT;
- case 1: /* Antenna 0 */
- return B43legacy_ANTENNA0;
- case 2: /* Antenna 1 */
- return B43legacy_ANTENNA1;
- default:
- return B43legacy_ANTENNA_DEFAULT;
- }
+ /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing
+ * the chip-internal counter. */
+ short_retry = min(short_retry, (unsigned int)0xF);
+ long_retry = min(long_retry, (unsigned int)0xF);
+
+ b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0006, short_retry);
+ b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry);
}
static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
- struct ieee80211_conf *conf)
+ u32 changed)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev;
struct b43legacy_phy *phy;
+ struct ieee80211_conf *conf = &hw->conf;
unsigned long flags;
unsigned int new_phymode = 0xFFFF;
int antenna_tx;
@@ -2583,13 +2559,21 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
int err = 0;
u32 savedirqs;
- antenna_tx = b43legacy_antenna_from_ieee80211(conf->antenna_sel_tx);
- antenna_rx = b43legacy_antenna_from_ieee80211(conf->antenna_sel_rx);
+ antenna_tx = B43legacy_ANTENNA_DEFAULT;
+ antenna_rx = B43legacy_ANTENNA_DEFAULT;
mutex_lock(&wl->mutex);
dev = wl->current_dev;
phy = &dev->phy;
+ if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+ b43legacy_set_retry_limits(dev,
+ conf->short_frame_max_tx_count,
+ conf->long_frame_max_tx_count);
+ changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS;
+ if (!changed)
+ goto out_unlock_mutex;
+
/* Switch the PHY mode (if necessary). */
switch (conf->channel->band) {
case IEEE80211_BAND_2GHZ:
@@ -2622,16 +2606,6 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
if (conf->channel->hw_value != phy->channel)
b43legacy_radio_selectchannel(dev, conf->channel->hw_value, 0);
- /* Enable/Disable ShortSlot timing. */
- if ((!!(conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME))
- != dev->short_slot) {
- B43legacy_WARN_ON(phy->type != B43legacy_PHYTYPE_G);
- if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME)
- b43legacy_short_slot_timing_enable(dev);
- else
- b43legacy_short_slot_timing_disable(dev);
- }
-
dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
/* Adjust the desired TX power level. */
@@ -2676,6 +2650,104 @@ out_unlock_mutex:
return err;
}
+static void b43legacy_update_basic_rates(struct b43legacy_wldev *dev, u64 brates)
+{
+ struct ieee80211_supported_band *sband =
+ dev->wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ];
+ struct ieee80211_rate *rate;
+ int i;
+ u16 basic, direct, offset, basic_offset, rateptr;
+
+ for (i = 0; i < sband->n_bitrates; i++) {
+ rate = &sband->bitrates[i];
+
+ if (b43legacy_is_cck_rate(rate->hw_value)) {
+ direct = B43legacy_SHM_SH_CCKDIRECT;
+ basic = B43legacy_SHM_SH_CCKBASIC;
+ offset = b43legacy_plcp_get_ratecode_cck(rate->hw_value);
+ offset &= 0xF;
+ } else {
+ direct = B43legacy_SHM_SH_OFDMDIRECT;
+ basic = B43legacy_SHM_SH_OFDMBASIC;
+ offset = b43legacy_plcp_get_ratecode_ofdm(rate->hw_value);
+ offset &= 0xF;
+ }
+
+ rate = ieee80211_get_response_rate(sband, brates, rate->bitrate);
+
+ if (b43legacy_is_cck_rate(rate->hw_value)) {
+ basic_offset = b43legacy_plcp_get_ratecode_cck(rate->hw_value);
+ basic_offset &= 0xF;
+ } else {
+ basic_offset = b43legacy_plcp_get_ratecode_ofdm(rate->hw_value);
+ basic_offset &= 0xF;
+ }
+
+ /*
+ * Get the pointer that we need to point to
+ * from the direct map
+ */
+ rateptr = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,
+ direct + 2 * basic_offset);
+ /* and write it to the basic map */
+ b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
+ basic + 2 * offset, rateptr);
+ }
+}
+
+static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *conf,
+ u32 changed)
+{
+ struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+ struct b43legacy_wldev *dev;
+ struct b43legacy_phy *phy;
+ unsigned long flags;
+ u32 savedirqs;
+
+ mutex_lock(&wl->mutex);
+
+ dev = wl->current_dev;
+ phy = &dev->phy;
+
+ /* Disable IRQs while reconfiguring the device.
+ * This makes it possible to drop the spinlock throughout
+ * the reconfiguration process. */
+ spin_lock_irqsave(&wl->irq_lock, flags);
+ if (b43legacy_status(dev) < B43legacy_STAT_STARTED) {
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+ goto out_unlock_mutex;
+ }
+ savedirqs = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL);
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+ b43legacy_synchronize_irq(dev);
+
+ b43legacy_mac_suspend(dev);
+
+ if (changed & BSS_CHANGED_BASIC_RATES)
+ b43legacy_update_basic_rates(dev, conf->basic_rates);
+
+ if (changed & BSS_CHANGED_ERP_SLOT) {
+ if (conf->use_short_slot)
+ b43legacy_short_slot_timing_enable(dev);
+ else
+ b43legacy_short_slot_timing_disable(dev);
+ }
+
+ b43legacy_mac_enable(dev);
+
+ spin_lock_irqsave(&wl->irq_lock, flags);
+ b43legacy_interrupt_enable(dev, savedirqs);
+ /* XXX: why? */
+ mmiowb();
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+ out_unlock_mutex:
+ mutex_unlock(&wl->mutex);
+
+ return;
+}
+
static void b43legacy_op_configure_filter(struct ieee80211_hw *hw,
unsigned int changed,
unsigned int *fflags,
@@ -2735,7 +2807,6 @@ static int b43legacy_op_config_interface(struct ieee80211_hw *hw,
if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) {
if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) {
B43legacy_WARN_ON(vif->type != NL80211_IFTYPE_AP);
- b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len);
if (conf->changed & IEEE80211_IFCC_BEACON)
b43legacy_update_templates(wl);
} else if (b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC)) {
@@ -3002,20 +3073,6 @@ static void b43legacy_imcfglo_timeouts_workaround(struct b43legacy_wldev *dev)
#endif /* CONFIG_SSB_DRIVER_PCICORE */
}
-/* Write the short and long frame retry limit values. */
-static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev,
- unsigned int short_retry,
- unsigned int long_retry)
-{
- /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing
- * the chip-internal counter. */
- short_retry = min(short_retry, (unsigned int)0xF);
- long_retry = min(long_retry, (unsigned int)0xF);
-
- b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0006, short_retry);
- b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry);
-}
-
static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev,
bool idle) {
u16 pu_delay = 1050;
@@ -3380,28 +3437,6 @@ static void b43legacy_op_stop(struct ieee80211_hw *hw)
mutex_unlock(&wl->mutex);
}
-static int b43legacy_op_set_retry_limit(struct ieee80211_hw *hw,
- u32 short_retry_limit,
- u32 long_retry_limit)
-{
- struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
- struct b43legacy_wldev *dev;
- int err = 0;
-
- mutex_lock(&wl->mutex);
- dev = wl->current_dev;
- if (unlikely(!dev ||
- (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED))) {
- err = -ENODEV;
- goto out_unlock;
- }
- b43legacy_set_retry_limits(dev, short_retry_limit, long_retry_limit);
-out_unlock:
- mutex_unlock(&wl->mutex);
-
- return err;
-}
-
static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
struct ieee80211_sta *sta, bool set)
{
@@ -3421,13 +3456,13 @@ static const struct ieee80211_ops b43legacy_hw_ops = {
.add_interface = b43legacy_op_add_interface,
.remove_interface = b43legacy_op_remove_interface,
.config = b43legacy_op_dev_config,
+ .bss_info_changed = b43legacy_op_bss_info_changed,
.config_interface = b43legacy_op_config_interface,
.configure_filter = b43legacy_op_configure_filter,
.get_stats = b43legacy_op_get_stats,
.get_tx_stats = b43legacy_op_get_tx_stats,
.start = b43legacy_op_start,
.stop = b43legacy_op_stop,
- .set_retry_limit = b43legacy_op_set_retry_limit,
.set_tim = b43legacy_op_beacon_set_tim,
};
@@ -3710,7 +3745,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
BIT(NL80211_IFTYPE_WDS) |
BIT(NL80211_IFTYPE_ADHOC);
hw->queues = 1; /* FIXME: hardware has more queues */
- hw->max_altrates = 1;
+ hw->max_rates = 2;
SET_IEEE80211_DEV(hw, dev->dev);
if (is_valid_ether_addr(sprom->et1mac))
SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c
index 4c9442b16f3f..11319ec2d64a 100644
--- a/drivers/net/wireless/b43legacy/phy.c
+++ b/drivers/net/wireless/b43legacy/phy.c
@@ -1296,12 +1296,10 @@ void b43legacy_lo_write(struct b43legacy_wldev *dev,
/* Sanity check. */
if (pair->low < -8 || pair->low > 8 ||
pair->high < -8 || pair->high > 8) {
- struct b43legacy_phy *phy = &dev->phy;
b43legacydbg(dev->wl,
"WARNING: Writing invalid LOpair "
- "(low: %d, high: %d, index: %lu)\n",
- pair->low, pair->high,
- (unsigned long)(pair - phy->_lo_pairs));
+ "(low: %d, high: %d)\n",
+ pair->low, pair->high);
dump_stack();
}
#endif
diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c
index a86c7647fa2d..746d5361bba0 100644
--- a/drivers/net/wireless/b43legacy/pio.c
+++ b/drivers/net/wireless/b43legacy/pio.c
@@ -491,6 +491,7 @@ void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev,
struct b43legacy_pioqueue *queue;
struct b43legacy_pio_txpacket *packet;
struct ieee80211_tx_info *info;
+ int retry_limit;
queue = parse_cookie(dev, status->cookie, &packet);
B43legacy_WARN_ON(!queue);
@@ -503,11 +504,37 @@ void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev,
sizeof(struct b43legacy_txhdr_fw3));
info = IEEE80211_SKB_CB(packet->skb);
- memset(&info->status, 0, sizeof(info->status));
+
+ /* preserve the confiured retry limit before clearing the status
+ * The xmit function has overwritten the rc's value with the actual
+ * retry limit done by the hardware */
+ retry_limit = info->status.rates[0].count;
+ ieee80211_tx_info_clear_status(info);
if (status->acked)
info->flags |= IEEE80211_TX_STAT_ACK;
- info->status.retry_count = status->frame_count - 1;
+
+ if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) {
+ /*
+ * If the short retries (RTS, not data frame) have exceeded
+ * the limit, the hw will not have tried the selected rate,
+ * but will have used the fallback rate instead.
+ * Don't let the rate control count attempts for the selected
+ * rate in this case, otherwise the statistics will be off.
+ */
+ info->status.rates[0].count = 0;
+ info->status.rates[1].count = status->frame_count;
+ } else {
+ if (status->frame_count > retry_limit) {
+ info->status.rates[0].count = retry_limit;
+ info->status.rates[1].count = status->frame_count -
+ retry_limit;
+
+ } else {
+ info->status.rates[0].count = status->frame_count;
+ info->status.rates[1].idx = -1;
+ }
+ }
ieee80211_tx_status_irqsafe(dev->wl->hw, packet->skb);
packet->skb = NULL;
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c
index 65e833781608..12fca99f7578 100644
--- a/drivers/net/wireless/b43legacy/xmit.c
+++ b/drivers/net/wireless/b43legacy/xmit.c
@@ -188,7 +188,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
struct b43legacy_txhdr_fw3 *txhdr,
const unsigned char *fragment_data,
unsigned int fragment_len,
- const struct ieee80211_tx_info *info,
+ struct ieee80211_tx_info *info,
u16 cookie)
{
const struct ieee80211_hdr *wlhdr;
@@ -201,6 +201,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
u32 mac_ctl = 0;
u16 phy_ctl = 0;
struct ieee80211_rate *tx_rate;
+ struct ieee80211_tx_rate *rates;
wlhdr = (const struct ieee80211_hdr *)fragment_data;
@@ -274,7 +275,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
/* PHY TX Control word */
if (rate_ofdm)
phy_ctl |= B43legacy_TX4_PHY_OFDM;
- if (dev->short_preamble)
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
phy_ctl |= B43legacy_TX4_PHY_SHORTPRMBL;
switch (info->antenna_sel_tx) {
case 0:
@@ -291,6 +292,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
}
/* MAC control */
+ rates = info->control.rates;
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
mac_ctl |= B43legacy_TX4_MAC_ACK;
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
@@ -299,12 +301,22 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
mac_ctl |= B43legacy_TX4_MAC_STMSDU;
if (rate_fb_ofdm)
mac_ctl |= B43legacy_TX4_MAC_FALLBACKOFDM;
- if (info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT)
+
+ /* Overwrite rates[0].count to make the retry calculation
+ * in the tx status easier. need the actual retry limit to
+ * detect whether the fallback rate was used.
+ */
+ if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
+ (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) {
+ rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count;
mac_ctl |= B43legacy_TX4_MAC_LONGFRAME;
+ } else {
+ rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count;
+ }
/* Generate the RTS or CTS-to-self frame */
- if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) ||
- (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) {
+ if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
+ (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) {
unsigned int len;
struct ieee80211_hdr *hdr;
int rts_rate;
@@ -319,7 +331,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
if (rts_rate_fb_ofdm)
mac_ctl |= B43legacy_TX4_MAC_CTSFALLBACKOFDM;
- if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
+ if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
ieee80211_ctstoself_get(dev->wl->hw,
info->control.vif,
fragment_data,
@@ -362,7 +374,7 @@ int b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
u8 *txhdr,
const unsigned char *fragment_data,
unsigned int fragment_len,
- const struct ieee80211_tx_info *info,
+ struct ieee80211_tx_info *info,
u16 cookie)
{
return generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr,
diff --git a/drivers/net/wireless/b43legacy/xmit.h b/drivers/net/wireless/b43legacy/xmit.h
index e56777e0feab..62e09d02788f 100644
--- a/drivers/net/wireless/b43legacy/xmit.h
+++ b/drivers/net/wireless/b43legacy/xmit.h
@@ -80,7 +80,7 @@ int b43legacy_generate_txhdr(struct b43legacy_wldev *dev,
u8 *txhdr,
const unsigned char *fragment_data,
unsigned int fragment_len,
- const struct ieee80211_tx_info *info,
+ struct ieee80211_tx_info *info,
u16 cookie);
diff --git a/drivers/net/wireless/hostap/Kconfig b/drivers/net/wireless/hostap/Kconfig
index 1fef33169fdd..932d207bce23 100644
--- a/drivers/net/wireless/hostap/Kconfig
+++ b/drivers/net/wireless/hostap/Kconfig
@@ -2,8 +2,17 @@ config HOSTAP
tristate "IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP)"
depends on WLAN_80211
select WIRELESS_EXT
- select IEEE80211
- select IEEE80211_CRYPT_WEP
+ select CRYPTO
+ select CRYPTO_ARC4
+ select CRYPTO_ECB
+ select CRYPTO_AES
+ select CRYPTO_MICHAEL_MIC
+ select CRYPTO_ECB
+ select CRC32
+ select LIB80211
+ select LIB80211_CRYPT_WEP
+ select LIB80211_CRYPT_TKIP
+ select LIB80211_CRYPT_CCMP
---help---
Shared driver code for IEEE 802.11b wireless cards based on
Intersil Prism2/2.5/3 chipset. This driver supports so called
diff --git a/drivers/net/wireless/hostap/hostap.h b/drivers/net/wireless/hostap/hostap.h
index 3a386a636cca..2453deaa3e00 100644
--- a/drivers/net/wireless/hostap/hostap.h
+++ b/drivers/net/wireless/hostap/hostap.h
@@ -63,7 +63,7 @@ void ap_control_flush_macs(struct mac_restrictions *mac_restrictions);
int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev, u8 *mac);
void ap_control_kickall(struct ap_data *ap);
void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
- struct ieee80211_crypt_data ***crypt);
+ struct lib80211_crypt_data ***crypt);
int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
struct iw_quality qual[], int buf_size,
int aplist);
diff --git a/drivers/net/wireless/hostap/hostap_80211.h b/drivers/net/wireless/hostap/hostap_80211.h
index 3694b1eba521..3a9474d9a907 100644
--- a/drivers/net/wireless/hostap/hostap_80211.h
+++ b/drivers/net/wireless/hostap/hostap_80211.h
@@ -2,7 +2,7 @@
#define HOSTAP_80211_H
#include <linux/types.h>
-#include <net/ieee80211_crypt.h>
+#include <net/ieee80211.h>
struct hostap_ieee80211_mgmt {
__le16 frame_control;
diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c
index f106bc1585a4..19b1bf0478bd 100644
--- a/drivers/net/wireless/hostap/hostap_80211_rx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_rx.c
@@ -1,5 +1,5 @@
#include <linux/etherdevice.h>
-#include <net/ieee80211_crypt.h>
+#include <net/lib80211.h>
#include "hostap_80211.h"
#include "hostap.h"
@@ -19,7 +19,6 @@ void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
{
struct ieee80211_hdr_4addr *hdr;
u16 fc;
- DECLARE_MAC_BUF(mac);
hdr = (struct ieee80211_hdr_4addr *) skb->data;
@@ -45,11 +44,11 @@ void hostap_dump_rx_80211(const char *name, struct sk_buff *skb,
printk(" dur=0x%04x seq=0x%04x\n", le16_to_cpu(hdr->duration_id),
le16_to_cpu(hdr->seq_ctl));
- printk(KERN_DEBUG " A1=%s", print_mac(mac, hdr->addr1));
- printk(" A2=%s", print_mac(mac, hdr->addr2));
- printk(" A3=%s", print_mac(mac, hdr->addr3));
+ printk(KERN_DEBUG " A1=%pM", hdr->addr1);
+ printk(" A2=%pM", hdr->addr2);
+ printk(" A3=%pM", hdr->addr3);
if (skb->len >= 30)
- printk(" A4=%s", print_mac(mac, hdr->addr4));
+ printk(" A4=%pM", hdr->addr4);
printk("\n");
}
@@ -68,7 +67,6 @@ int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb,
iface = netdev_priv(dev);
local = iface->local;
- dev->last_rx = jiffies;
if (dev->type == ARPHRD_IEEE80211_PRISM) {
if (local->monitor_type == PRISM2_MONITOR_PRISM) {
@@ -557,7 +555,6 @@ static int
hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
u16 fc, struct net_device **wds)
{
- DECLARE_MAC_BUF(mac);
/* FIX: is this really supposed to accept WDS frames only in Master
* mode? What about Repeater or Managed with WDS frames? */
if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) !=
@@ -573,10 +570,10 @@ hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
hdr->addr1[4] != 0xff || hdr->addr1[5] != 0xff)) {
/* RA (or BSSID) is not ours - drop */
PDEBUG(DEBUG_EXTRA2, "%s: received WDS frame with "
- "not own or broadcast %s=%s\n",
+ "not own or broadcast %s=%pM\n",
local->dev->name,
fc & IEEE80211_FCTL_FROMDS ? "RA" : "BSSID",
- print_mac(mac, hdr->addr1));
+ hdr->addr1);
return -1;
}
@@ -589,8 +586,8 @@ hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
/* require that WDS link has been registered with TA or the
* frame is from current AP when using 'AP client mode' */
PDEBUG(DEBUG_EXTRA, "%s: received WDS[4 addr] frame "
- "from unknown TA=%s\n",
- local->dev->name, print_mac(mac, hdr->addr2));
+ "from unknown TA=%pM\n",
+ local->dev->name, hdr->addr2);
if (local->ap && local->ap->autom_ap_wds)
hostap_wds_link_oper(local, hdr->addr2, WDS_ADD);
return -1;
@@ -652,7 +649,7 @@ static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb)
/* Called only as a tasklet (software IRQ) */
static int
hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
- struct ieee80211_crypt_data *crypt)
+ struct lib80211_crypt_data *crypt)
{
struct ieee80211_hdr_4addr *hdr;
int res, hdrlen;
@@ -667,10 +664,8 @@ hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
strcmp(crypt->ops->name, "TKIP") == 0) {
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
- "received packet from " MAC_FMT "\n",
- local->dev->name,
- hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
- hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]);
+ "received packet from %pM\n",
+ local->dev->name, hdr->addr2);
}
return -1;
}
@@ -679,12 +674,8 @@ hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
atomic_dec(&crypt->refcnt);
if (res < 0) {
- printk(KERN_DEBUG "%s: decryption failed (SA=" MAC_FMT
- ") res=%d\n",
- local->dev->name,
- hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
- hdr->addr2[3], hdr->addr2[4], hdr->addr2[5],
- res);
+ printk(KERN_DEBUG "%s: decryption failed (SA=%pM) res=%d\n",
+ local->dev->name, hdr->addr2, res);
local->comm_tallies.rx_discards_wep_undecryptable++;
return -1;
}
@@ -696,11 +687,10 @@ hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb,
/* Called only as a tasklet (software IRQ) */
static int
hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
- int keyidx, struct ieee80211_crypt_data *crypt)
+ int keyidx, struct lib80211_crypt_data *crypt)
{
struct ieee80211_hdr_4addr *hdr;
int res, hdrlen;
- DECLARE_MAC_BUF(mac);
if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
return 0;
@@ -713,8 +703,8 @@ hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb,
atomic_dec(&crypt->refcnt);
if (res < 0) {
printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
- " (SA=%s keyidx=%d)\n",
- local->dev->name, print_mac(mac, hdr->addr2), keyidx);
+ " (SA=%pM keyidx=%d)\n",
+ local->dev->name, hdr->addr2, keyidx);
return -1;
}
@@ -743,7 +733,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
int from_assoc_ap = 0;
u8 dst[ETH_ALEN];
u8 src[ETH_ALEN];
- struct ieee80211_crypt_data *crypt = NULL;
+ struct lib80211_crypt_data *crypt = NULL;
void *sta = NULL;
int keyidx = 0;
@@ -795,7 +785,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
int idx = 0;
if (skb->len >= hdrlen + 3)
idx = skb->data[hdrlen + 3] >> 6;
- crypt = local->crypt[idx];
+ crypt = local->crypt_info.crypt[idx];
sta = NULL;
/* Use station specific key to override default keys if the
@@ -822,10 +812,8 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
* frames silently instead of filling system log with
* these reports. */
printk(KERN_DEBUG "%s: WEP decryption failed (not set)"
- " (SA=" MAC_FMT ")\n",
- local->dev->name,
- hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
- hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]);
+ " (SA=%pM)\n",
+ local->dev->name, hdr->addr2);
#endif
local->comm_tallies.rx_discards_wep_undecryptable++;
goto rx_dropped;
@@ -839,9 +827,7 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
(keyidx = hostap_rx_frame_decrypt(local, skb, crypt)) < 0)
{
printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth "
- "from " MAC_FMT "\n", dev->name,
- hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
- hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]);
+ "from %pM\n", dev->name, hdr->addr2);
/* TODO: could inform hostapd about this so that it
* could send auth failure report */
goto rx_dropped;
@@ -896,8 +882,6 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
from_assoc_ap = 1;
}
- dev->last_rx = jiffies;
-
if ((local->iw_mode == IW_MODE_MASTER ||
local->iw_mode == IW_MODE_REPEAT) &&
!from_assoc_ap) {
@@ -1009,10 +993,8 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
"unencrypted EAPOL frame\n", local->dev->name);
} else {
printk(KERN_DEBUG "%s: encryption configured, but RX "
- "frame not encrypted (SA=" MAC_FMT ")\n",
- local->dev->name,
- hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
- hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]);
+ "frame not encrypted (SA=%pM)\n",
+ local->dev->name, hdr->addr2);
goto rx_dropped;
}
}
@@ -1021,10 +1003,8 @@ void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb,
!hostap_is_eapol_frame(local, skb)) {
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: dropped unencrypted RX data "
- "frame from " MAC_FMT " (drop_unencrypted=1)\n",
- dev->name,
- hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
- hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]);
+ "frame from %pM (drop_unencrypted=1)\n",
+ dev->name, hdr->addr2);
}
goto rx_dropped;
}
diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c
index 921c984416f8..078a010f39a0 100644
--- a/drivers/net/wireless/hostap/hostap_80211_tx.c
+++ b/drivers/net/wireless/hostap/hostap_80211_tx.c
@@ -17,7 +17,6 @@ void hostap_dump_tx_80211(const char *name, struct sk_buff *skb)
{
struct ieee80211_hdr_4addr *hdr;
u16 fc;
- DECLARE_MAC_BUF(mac);
hdr = (struct ieee80211_hdr_4addr *) skb->data;
@@ -41,11 +40,11 @@ void hostap_dump_tx_80211(const char *name, struct sk_buff *skb)
printk(" dur=0x%04x seq=0x%04x\n", le16_to_cpu(hdr->duration_id),
le16_to_cpu(hdr->seq_ctl));
- printk(KERN_DEBUG " A1=%s", print_mac(mac, hdr->addr1));
- printk(" A2=%s", print_mac(mac, hdr->addr2));
- printk(" A3=%s", print_mac(mac, hdr->addr3));
+ printk(KERN_DEBUG " A1=%pM", hdr->addr1);
+ printk(" A2=%pM", hdr->addr2);
+ printk(" A3=%pM", hdr->addr3);
if (skb->len >= 30)
- printk(" A4=%s", print_mac(mac, hdr->addr4));
+ printk(" A4=%pM", hdr->addr4);
printk("\n");
}
@@ -307,7 +306,7 @@ int hostap_mgmt_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Called only from software IRQ */
static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
- struct ieee80211_crypt_data *crypt)
+ struct lib80211_crypt_data *crypt)
{
struct hostap_interface *iface;
local_info_t *local;
@@ -328,10 +327,8 @@ static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb,
hdr = (struct ieee80211_hdr_4addr *) skb->data;
if (net_ratelimit()) {
printk(KERN_DEBUG "%s: TKIP countermeasures: dropped "
- "TX packet to " MAC_FMT "\n",
- local->dev->name,
- hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
- hdr->addr1[3], hdr->addr1[4], hdr->addr1[5]);
+ "TX packet to %pM\n",
+ local->dev->name, hdr->addr1);
}
kfree_skb(skb);
return NULL;
@@ -408,7 +405,7 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (local->host_encrypt) {
/* Set crypt to default algorithm and key; will be replaced in
* AP code if STA has own alg/key */
- tx.crypt = local->crypt[local->tx_keyidx];
+ tx.crypt = local->crypt_info.crypt[local->crypt_info.tx_keyidx];
tx.host_encrypt = 1;
} else {
tx.crypt = NULL;
@@ -490,7 +487,9 @@ int hostap_master_start_xmit(struct sk_buff *skb, struct net_device *dev)
if (tx.crypt && (!tx.crypt->ops || !tx.crypt->ops->encrypt_mpdu))
tx.crypt = NULL;
- else if ((tx.crypt || local->crypt[local->tx_keyidx]) && !no_encrypt) {
+ else if ((tx.crypt ||
+ local->crypt_info.crypt[local->crypt_info.tx_keyidx]) &&
+ !no_encrypt) {
/* Add ISWEP flag both for firmware and host based encryption
*/
fc |= IEEE80211_FCTL_PROTECTED;
diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c
index af3d4ef2a80b..0903db786d5f 100644
--- a/drivers/net/wireless/hostap/hostap_ap.c
+++ b/drivers/net/wireless/hostap/hostap_ap.c
@@ -94,7 +94,6 @@ static void ap_sta_hash_add(struct ap_data *ap, struct sta_info *sta)
static void ap_sta_hash_del(struct ap_data *ap, struct sta_info *sta)
{
struct sta_info *s;
- DECLARE_MAC_BUF(mac);
s = ap->sta_hash[STA_HASH(sta->addr)];
if (s == NULL) return;
@@ -109,20 +108,18 @@ static void ap_sta_hash_del(struct ap_data *ap, struct sta_info *sta)
if (s->hnext != NULL)
s->hnext = s->hnext->hnext;
else
- printk("AP: could not remove STA %s"
- " from hash table\n",
- print_mac(mac, sta->addr));
+ printk("AP: could not remove STA %pM from hash table\n",
+ sta->addr);
}
static void ap_free_sta(struct ap_data *ap, struct sta_info *sta)
{
- DECLARE_MAC_BUF(mac);
if (sta->ap && sta->local)
hostap_event_expired_sta(sta->local->dev, sta);
if (ap->proc != NULL) {
char name[20];
- sprintf(name, "%s", print_mac(mac, sta->addr));
+ sprintf(name, "%pM", sta->addr);
remove_proc_entry(name, ap->proc);
}
@@ -185,7 +182,6 @@ static void ap_handle_timer(unsigned long data)
struct ap_data *ap;
unsigned long next_time = 0;
int was_assoc;
- DECLARE_MAC_BUF(mac);
if (sta == NULL || sta->local == NULL || sta->local->ap == NULL) {
PDEBUG(DEBUG_AP, "ap_handle_timer() called with NULL data\n");
@@ -242,8 +238,8 @@ static void ap_handle_timer(unsigned long data)
if (sta->ap) {
if (ap->autom_ap_wds) {
PDEBUG(DEBUG_AP, "%s: removing automatic WDS "
- "connection to AP %s\n",
- local->dev->name, print_mac(mac, sta->addr));
+ "connection to AP %pM\n",
+ local->dev->name, sta->addr);
hostap_wds_link_oper(local, sta->addr, WDS_DEL);
}
} else if (sta->timeout_next == STA_NULLFUNC) {
@@ -259,11 +255,11 @@ static void ap_handle_timer(unsigned long data)
} else {
int deauth = sta->timeout_next == STA_DEAUTH;
__le16 resp;
- PDEBUG(DEBUG_AP, "%s: sending %s info to STA %s"
+ PDEBUG(DEBUG_AP, "%s: sending %s info to STA %pM"
"(last=%lu, jiffies=%lu)\n",
local->dev->name,
deauth ? "deauthentication" : "disassociation",
- print_mac(mac, sta->addr), sta->last_rx, jiffies);
+ sta->addr, sta->last_rx, jiffies);
resp = cpu_to_le16(deauth ? WLAN_REASON_PREV_AUTH_NOT_VALID :
WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY);
@@ -275,10 +271,10 @@ static void ap_handle_timer(unsigned long data)
if (sta->timeout_next == STA_DEAUTH) {
if (sta->flags & WLAN_STA_PERM) {
- PDEBUG(DEBUG_AP, "%s: STA %s"
+ PDEBUG(DEBUG_AP, "%s: STA %pM"
" would have been removed, "
"but it has 'perm' flag\n",
- local->dev->name, print_mac(mac, sta->addr));
+ local->dev->name, sta->addr);
} else
ap_free_sta(ap, sta);
return;
@@ -332,7 +328,6 @@ static int ap_control_proc_read(char *page, char **start, off_t off,
struct ap_data *ap = (struct ap_data *) data;
char *policy_txt;
struct mac_entry *entry;
- DECLARE_MAC_BUF(mac);
if (off != 0) {
*eof = 1;
@@ -363,7 +358,7 @@ static int ap_control_proc_read(char *page, char **start, off_t off,
break;
}
- p += sprintf(p, "%s\n", print_mac(mac, entry->addr));
+ p += sprintf(p, "%pM\n", entry->addr);
}
spin_unlock_bh(&ap->mac_restrictions.lock);
@@ -520,7 +515,6 @@ static int prism2_ap_proc_read(char *page, char **start, off_t off,
struct ap_data *ap = (struct ap_data *) data;
struct sta_info *sta;
int i;
- DECLARE_MAC_BUF(mac);
if (off > PROC_LIMIT) {
*eof = 1;
@@ -533,8 +527,8 @@ static int prism2_ap_proc_read(char *page, char **start, off_t off,
if (!sta->ap)
continue;
- p += sprintf(p, "%s %d %d %d %d '",
- print_mac(mac, sta->addr),
+ p += sprintf(p, "%pM %d %d %d %d '",
+ sta->addr,
sta->u.ap.channel, sta->last_rx_signal,
sta->last_rx_silence, sta->last_rx_rate);
for (i = 0; i < sta->u.ap.ssid_len; i++)
@@ -683,11 +677,9 @@ static void hostap_ap_tx_cb_auth(struct sk_buff *skb, int ok, void *data)
if (sta)
atomic_dec(&sta->users);
if (txt) {
- PDEBUG(DEBUG_AP, "%s: " MAC_FMT " auth_cb - alg=%d "
+ PDEBUG(DEBUG_AP, "%s: %pM auth_cb - alg=%d "
"trans#=%d status=%d - %s\n",
- dev->name,
- hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
- hdr->addr1[3], hdr->addr1[4], hdr->addr1[5],
+ dev->name, hdr->addr1,
auth_alg, auth_transaction, status, txt);
}
dev_kfree_skb(skb);
@@ -754,11 +746,8 @@ static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data)
if (sta)
atomic_dec(&sta->users);
if (txt) {
- PDEBUG(DEBUG_AP, "%s: " MAC_FMT " assoc_cb - %s\n",
- dev->name,
- hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
- hdr->addr1[3], hdr->addr1[4], hdr->addr1[5],
- txt);
+ PDEBUG(DEBUG_AP, "%s: %pM assoc_cb - %s\n",
+ dev->name, hdr->addr1, txt);
}
dev_kfree_skb(skb);
}
@@ -781,11 +770,9 @@ static void hostap_ap_tx_cb_poll(struct sk_buff *skb, int ok, void *data)
sta->flags &= ~WLAN_STA_PENDING_POLL;
spin_unlock(&ap->sta_table_lock);
} else {
- PDEBUG(DEBUG_AP, "%s: STA " MAC_FMT
- " did not ACK activity poll frame\n",
- ap->local->dev->name,
- hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
- hdr->addr1[3], hdr->addr1[4], hdr->addr1[5]);
+ PDEBUG(DEBUG_AP,
+ "%s: STA %pM did not ACK activity poll frame\n",
+ ap->local->dev->name, hdr->addr1);
}
fail:
@@ -1002,7 +989,6 @@ static int prism2_sta_proc_read(char *page, char **start, off_t off,
char *p = page;
struct sta_info *sta = (struct sta_info *) data;
int i;
- DECLARE_MAC_BUF(mac);
/* FIX: possible race condition.. the STA data could have just expired,
* but proc entry was still here so that the read could have started;
@@ -1013,11 +999,11 @@ static int prism2_sta_proc_read(char *page, char **start, off_t off,
return 0;
}
- p += sprintf(p, "%s=%s\nusers=%d\naid=%d\n"
+ p += sprintf(p, "%s=%pM\nusers=%d\naid=%d\n"
"flags=0x%04x%s%s%s%s%s%s%s\n"
"capability=0x%02x\nlisten_interval=%d\nsupported_rates=",
sta->ap ? "AP" : "STA",
- print_mac(mac, sta->addr), atomic_read(&sta->users), sta->aid,
+ sta->addr, atomic_read(&sta->users), sta->aid,
sta->flags,
sta->flags & WLAN_STA_AUTH ? " AUTH" : "",
sta->flags & WLAN_STA_ASSOC ? " ASSOC" : "",
@@ -1078,7 +1064,6 @@ static void handle_add_proc_queue(struct work_struct *work)
struct sta_info *sta;
char name[20];
struct add_sta_proc_data *entry, *prev;
- DECLARE_MAC_BUF(mac);
entry = ap->add_sta_proc_entries;
ap->add_sta_proc_entries = NULL;
@@ -1091,7 +1076,7 @@ static void handle_add_proc_queue(struct work_struct *work)
spin_unlock_bh(&ap->sta_table_lock);
if (sta) {
- sprintf(name, "%s", print_mac(mac, sta->addr));
+ sprintf(name, "%pM", sta->addr);
sta->proc = create_proc_read_entry(
name, 0, ap->proc,
prism2_sta_proc_read, sta);
@@ -1221,7 +1206,7 @@ static void prism2_check_tx_rates(struct sta_info *sta)
static void ap_crypt_init(struct ap_data *ap)
{
- ap->crypt = ieee80211_get_crypto_ops("WEP");
+ ap->crypt = lib80211_get_crypto_ops("WEP");
if (ap->crypt) {
if (ap->crypt->init) {
@@ -1239,7 +1224,7 @@ static void ap_crypt_init(struct ap_data *ap)
if (ap->crypt == NULL) {
printk(KERN_WARNING "AP could not initialize WEP: load module "
- "ieee80211_crypt_wep.ko\n");
+ "lib80211_crypt_wep.ko\n");
}
}
@@ -1308,7 +1293,7 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb,
__le16 *pos;
u16 resp = WLAN_STATUS_SUCCESS, fc;
struct sta_info *sta = NULL;
- struct ieee80211_crypt_data *crypt;
+ struct lib80211_crypt_data *crypt;
char *txt = "";
len = skb->len - IEEE80211_MGMT_HDR_LEN;
@@ -1318,9 +1303,7 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb,
if (len < 6) {
PDEBUG(DEBUG_AP, "%s: handle_authen - too short payload "
- "(len=%d) from " MAC_FMT "\n", dev->name, len,
- hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
- hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]);
+ "(len=%d) from %pM\n", dev->name, len, hdr->addr2);
return;
}
@@ -1336,7 +1319,7 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb,
int idx = 0;
if (skb->len >= hdrlen + 3)
idx = skb->data[hdrlen + 3] >> 6;
- crypt = local->crypt[idx];
+ crypt = local->crypt_info.crypt[idx];
}
pos = (__le16 *) (skb->data + IEEE80211_MGMT_HDR_LEN);
@@ -1385,10 +1368,8 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb,
if (time_after(jiffies, sta->u.ap.last_beacon +
(10 * sta->listen_interval * HZ) / 1024)) {
PDEBUG(DEBUG_AP, "%s: no beacons received for a while,"
- " assuming AP " MAC_FMT " is now STA\n",
- dev->name,
- sta->addr[0], sta->addr[1], sta->addr[2],
- sta->addr[3], sta->addr[4], sta->addr[5]);
+ " assuming AP %pM is now STA\n",
+ dev->name, sta->addr);
sta->ap = 0;
sta->flags = 0;
sta->u.sta.challenge = NULL;
@@ -1503,11 +1484,9 @@ static void handle_authen(local_info_t *local, struct sk_buff *skb,
}
if (resp) {
- PDEBUG(DEBUG_AP, "%s: " MAC_FMT " auth (alg=%d "
+ PDEBUG(DEBUG_AP, "%s: %pM auth (alg=%d "
"trans#=%d stat=%d len=%d fc=%04x) ==> %d (%s)\n",
- dev->name,
- hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
- hdr->addr2[3], hdr->addr2[4], hdr->addr2[5],
+ dev->name, hdr->addr2,
auth_alg, auth_transaction, status_code, len,
fc, resp, txt);
}
@@ -1533,10 +1512,8 @@ static void handle_assoc(local_info_t *local, struct sk_buff *skb,
if (len < (reassoc ? 10 : 4)) {
PDEBUG(DEBUG_AP, "%s: handle_assoc - too short payload "
- "(len=%d, reassoc=%d) from " MAC_FMT "\n",
- dev->name, len, reassoc,
- hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
- hdr->addr2[3], hdr->addr2[4], hdr->addr2[5]);
+ "(len=%d, reassoc=%d) from %pM\n",
+ dev->name, len, reassoc, hdr->addr2);
return;
}
@@ -1613,12 +1590,9 @@ static void handle_assoc(local_info_t *local, struct sk_buff *skb,
}
if (left > 0) {
- PDEBUG(DEBUG_AP, "%s: assoc from " MAC_FMT
+ PDEBUG(DEBUG_AP, "%s: assoc from %pM"
" with extra data (%d bytes) [",
- dev->name,
- hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
- hdr->addr2[3], hdr->addr2[4], hdr->addr2[5],
- left);
+ dev->name, hdr->addr2, left);
while (left > 0) {
PDEBUG2(DEBUG_AP, "<%02x>", *u);
u++; left--;
@@ -1717,14 +1691,12 @@ static void handle_assoc(local_info_t *local, struct sk_buff *skb,
}
#if 0
- PDEBUG(DEBUG_AP, "%s: " MAC_FMT" %sassoc (len=%d "
- "prev_ap=" MAC_FMT") => %d(%d) (%s)\n",
+ PDEBUG(DEBUG_AP, "%s: %pM %sassoc (len=%d "
+ "prev_ap=%pM) => %d(%d) (%s)\n",
dev->name,
- hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
- hdr->addr2[3], hdr->addr2[4], hdr->addr2[5],
+ hdr->addr2,
reassoc ? "re" : "", len,
- prev_ap[0], prev_ap[1], prev_ap[2],
- prev_ap[3], prev_ap[4], prev_ap[5],
+ prev_ap,
resp, send_deauth, txt);
#endif
}
@@ -1741,7 +1713,6 @@ static void handle_deauth(local_info_t *local, struct sk_buff *skb,
u16 reason_code;
__le16 *pos;
struct sta_info *sta = NULL;
- DECLARE_MAC_BUF(mac);
len = skb->len - IEEE80211_MGMT_HDR_LEN;
@@ -1753,10 +1724,8 @@ static void handle_deauth(local_info_t *local, struct sk_buff *skb,
pos = (__le16 *) body;
reason_code = le16_to_cpu(*pos);
- PDEBUG(DEBUG_AP, "%s: deauthentication: " MAC_FMT " len=%d, "
- "reason_code=%d\n", dev->name,
- hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
- hdr->addr2[3], hdr->addr2[4], hdr->addr2[5],
+ PDEBUG(DEBUG_AP, "%s: deauthentication: %pM len=%d, "
+ "reason_code=%d\n", dev->name, hdr->addr2,
len, reason_code);
spin_lock_bh(&local->ap->sta_table_lock);
@@ -1768,11 +1737,9 @@ static void handle_deauth(local_info_t *local, struct sk_buff *skb,
}
spin_unlock_bh(&local->ap->sta_table_lock);
if (sta == NULL) {
- printk("%s: deauthentication from " MAC_FMT ", "
+ printk("%s: deauthentication from %pM, "
"reason_code=%d, but STA not authenticated\n", dev->name,
- hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
- hdr->addr2[3], hdr->addr2[4], hdr->addr2[5],
- reason_code);
+ hdr->addr2, reason_code);
}
}
@@ -1799,10 +1766,8 @@ static void handle_disassoc(local_info_t *local, struct sk_buff *skb,
pos = (__le16 *) body;
reason_code = le16_to_cpu(*pos);
- PDEBUG(DEBUG_AP, "%s: disassociation: " MAC_FMT " len=%d, "
- "reason_code=%d\n", dev->name,
- hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
- hdr->addr2[3], hdr->addr2[4], hdr->addr2[5],
+ PDEBUG(DEBUG_AP, "%s: disassociation: %pM len=%d, "
+ "reason_code=%d\n", dev->name, hdr->addr2,
len, reason_code);
spin_lock_bh(&local->ap->sta_table_lock);
@@ -1814,12 +1779,9 @@ static void handle_disassoc(local_info_t *local, struct sk_buff *skb,
}
spin_unlock_bh(&local->ap->sta_table_lock);
if (sta == NULL) {
- printk("%s: disassociation from " MAC_FMT ", "
+ printk("%s: disassociation from %pM, "
"reason_code=%d, but STA not authenticated\n",
- dev->name,
- hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
- hdr->addr2[3], hdr->addr2[4], hdr->addr2[5],
- reason_code);
+ dev->name, hdr->addr2, reason_code);
}
}
@@ -1909,19 +1871,14 @@ static void handle_pspoll(local_info_t *local,
u16 aid;
struct sk_buff *skb;
- PDEBUG(DEBUG_PS2, "handle_pspoll: BSSID=" MAC_FMT
- ", TA=" MAC_FMT " PWRMGT=%d\n",
- hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
- hdr->addr1[3], hdr->addr1[4], hdr->addr1[5],
- hdr->addr2[0], hdr->addr2[1], hdr->addr2[2],
- hdr->addr2[3], hdr->addr2[4], hdr->addr2[5],
+ PDEBUG(DEBUG_PS2, "handle_pspoll: BSSID=%pM, TA=%pM PWRMGT=%d\n",
+ hdr->addr1, hdr->addr2,
!!(le16_to_cpu(hdr->frame_ctl) & IEEE80211_FCTL_PM));
if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) {
- PDEBUG(DEBUG_AP, "handle_pspoll - addr1(BSSID)=" MAC_FMT
- " not own MAC\n",
- hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
- hdr->addr1[3], hdr->addr1[4], hdr->addr1[5]);
+ PDEBUG(DEBUG_AP,
+ "handle_pspoll - addr1(BSSID)=%pM not own MAC\n",
+ hdr->addr1);
return;
}
@@ -2007,11 +1964,10 @@ static void handle_wds_oper_queue(struct work_struct *work)
while (entry) {
PDEBUG(DEBUG_AP, "%s: %s automatic WDS connection "
- "to AP " MAC_FMT "\n",
+ "to AP %pM\n",
local->dev->name,
entry->type == WDS_ADD ? "adding" : "removing",
- entry->addr[0], entry->addr[1], entry->addr[2],
- entry->addr[3], entry->addr[4], entry->addr[5]);
+ entry->addr);
if (entry->type == WDS_ADD)
prism2_wds_add(local, entry->addr, 0);
else if (entry->type == WDS_DEL)
@@ -2215,10 +2171,8 @@ static void handle_ap_item(local_info_t *local, struct sk_buff *skb,
}
if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) {
- PDEBUG(DEBUG_AP, "handle_ap_item - addr1(BSSID)="
- MAC_FMT " not own MAC\n",
- hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
- hdr->addr1[3], hdr->addr1[4], hdr->addr1[5]);
+ PDEBUG(DEBUG_AP, "handle_ap_item - addr1(BSSID)=%pM"
+ " not own MAC\n", hdr->addr1);
goto done;
}
@@ -2254,18 +2208,14 @@ static void handle_ap_item(local_info_t *local, struct sk_buff *skb,
}
if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) {
- PDEBUG(DEBUG_AP, "handle_ap_item - addr1(DA)=" MAC_FMT
- " not own MAC\n",
- hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
- hdr->addr1[3], hdr->addr1[4], hdr->addr1[5]);
+ PDEBUG(DEBUG_AP, "handle_ap_item - addr1(DA)=%pM"
+ " not own MAC\n", hdr->addr1);
goto done;
}
if (memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN)) {
- PDEBUG(DEBUG_AP, "handle_ap_item - addr3(BSSID)=" MAC_FMT
- " not own MAC\n",
- hdr->addr3[0], hdr->addr3[1], hdr->addr3[2],
- hdr->addr3[3], hdr->addr3[4], hdr->addr3[5]);
+ PDEBUG(DEBUG_AP, "handle_ap_item - addr3(BSSID)=%pM"
+ " not own MAC\n", hdr->addr3);
goto done;
}
@@ -2366,10 +2316,9 @@ static void schedule_packet_send(local_info_t *local, struct sta_info *sta)
memcpy(hdr->addr2, sta->addr, ETH_ALEN);
hdr->duration_id = cpu_to_le16(sta->aid | BIT(15) | BIT(14));
- PDEBUG(DEBUG_PS2, "%s: Scheduling buffered packet delivery for STA "
- MAC_FMT "\n", local->dev->name,
- sta->addr[0], sta->addr[1], sta->addr[2],
- sta->addr[3], sta->addr[4], sta->addr[5]);
+ PDEBUG(DEBUG_PS2,
+ "%s: Scheduling buffered packet delivery for STA %pM\n",
+ local->dev->name, sta->addr);
skb->dev = local->dev;
@@ -2723,12 +2672,8 @@ static int ap_update_sta_tx_rate(struct sta_info *sta, struct net_device *dev)
case 3: sta->tx_rate = 110; break;
default: sta->tx_rate = 0; break;
}
- PDEBUG(DEBUG_AP, "%s: STA " MAC_FMT
- " TX rate raised to %d\n",
- dev->name,
- sta->addr[0], sta->addr[1], sta->addr[2],
- sta->addr[3], sta->addr[4], sta->addr[5],
- sta->tx_rate);
+ PDEBUG(DEBUG_AP, "%s: STA %pM TX rate raised to %d\n",
+ dev->name, sta->addr, sta->tx_rate);
}
sta->tx_since_last_failure = 0;
}
@@ -2781,9 +2726,7 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
* print out any errors here. */
if (net_ratelimit()) {
printk(KERN_DEBUG "AP: drop packet to non-associated "
- "STA " MAC_FMT "\n",
- hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
- hdr->addr1[3], hdr->addr1[4], hdr->addr1[5]);
+ "STA %pM\n", hdr->addr1);
}
#endif
local->ap->tx_drop_nonassoc++;
@@ -2821,11 +2764,9 @@ ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx)
}
if (skb_queue_len(&sta->tx_buf) >= STA_MAX_TX_BUFFER) {
- PDEBUG(DEBUG_PS, "%s: No more space in STA (" MAC_FMT
- ")'s PS mode buffer\n",
- local->dev->name,
- sta->addr[0], sta->addr[1], sta->addr[2],
- sta->addr[3], sta->addr[4], sta->addr[5]);
+ PDEBUG(DEBUG_PS, "%s: No more space in STA (%pM)'s"
+ "PS mode buffer\n",
+ local->dev->name, sta->addr);
/* Make sure that TIM is set for the station (it might not be
* after AP wlan hw reset). */
/* FIX: should fix hw reset to restore bits based on STA
@@ -2897,12 +2838,9 @@ void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb)
sta = ap_get_sta(local->ap, hdr->addr1);
if (!sta) {
spin_unlock(&local->ap->sta_table_lock);
- PDEBUG(DEBUG_AP, "%s: Could not find STA " MAC_FMT
+ PDEBUG(DEBUG_AP, "%s: Could not find STA %pM"
" for this TX error (@%lu)\n",
- local->dev->name,
- hdr->addr1[0], hdr->addr1[1], hdr->addr1[2],
- hdr->addr1[3], hdr->addr1[4], hdr->addr1[5],
- jiffies);
+ local->dev->name, hdr->addr1, jiffies);
return;
}
@@ -2929,12 +2867,9 @@ void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb)
case 3: sta->tx_rate = 110; break;
default: sta->tx_rate = 0; break;
}
- PDEBUG(DEBUG_AP, "%s: STA " MAC_FMT
- " TX rate lowered to %d\n",
- local->dev->name,
- sta->addr[0], sta->addr[1], sta->addr[2],
- sta->addr[3], sta->addr[4], sta->addr[5],
- sta->tx_rate);
+ PDEBUG(DEBUG_AP,
+ "%s: STA %pM TX rate lowered to %d\n",
+ local->dev->name, sta->addr, sta->tx_rate);
}
sta->tx_consecutive_exc = 0;
}
@@ -2945,17 +2880,16 @@ void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb)
static void hostap_update_sta_ps2(local_info_t *local, struct sta_info *sta,
int pwrmgt, int type, int stype)
{
- DECLARE_MAC_BUF(mac);
if (pwrmgt && !(sta->flags & WLAN_STA_PS)) {
sta->flags |= WLAN_STA_PS;
- PDEBUG(DEBUG_PS2, "STA %s changed to use PS "
+ PDEBUG(DEBUG_PS2, "STA %pM changed to use PS "
"mode (type=0x%02X, stype=0x%02X)\n",
- print_mac(mac, sta->addr), type >> 2, stype >> 4);
+ sta->addr, type >> 2, stype >> 4);
} else if (!pwrmgt && (sta->flags & WLAN_STA_PS)) {
sta->flags &= ~WLAN_STA_PS;
- PDEBUG(DEBUG_PS2, "STA %s changed to not use "
+ PDEBUG(DEBUG_PS2, "STA %pM changed to not use "
"PS mode (type=0x%02X, stype=0x%02X)\n",
- print_mac(mac, sta->addr), type >> 2, stype >> 4);
+ sta->addr, type >> 2, stype >> 4);
if (type != IEEE80211_FTYPE_CTL ||
stype != IEEE80211_STYPE_PSPOLL)
schedule_packet_send(local, sta);
@@ -3029,13 +2963,9 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
} else {
printk(KERN_DEBUG "%s: dropped received packet"
- " from non-associated STA "
- MAC_FMT
+ " from non-associated STA %pM"
" (type=0x%02x, subtype=0x%02x)\n",
- dev->name,
- hdr->addr2[0], hdr->addr2[1],
- hdr->addr2[2], hdr->addr2[3],
- hdr->addr2[4], hdr->addr2[5],
+ dev->name, hdr->addr2,
type >> 2, stype >> 4);
hostap_rx(dev, skb, rx_stats);
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
@@ -3068,13 +2998,9 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
* after being unavailable for some time. Speed up
* re-association by informing the station about it not
* being associated. */
- printk(KERN_DEBUG "%s: rejected received nullfunc "
- "frame without ToDS from not associated STA "
- MAC_FMT "\n",
- dev->name,
- hdr->addr2[0], hdr->addr2[1],
- hdr->addr2[2], hdr->addr2[3],
- hdr->addr2[4], hdr->addr2[5]);
+ printk(KERN_DEBUG "%s: rejected received nullfunc frame"
+ " without ToDS from not associated STA %pM\n",
+ dev->name, hdr->addr2);
hostap_rx(dev, skb, rx_stats);
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
}
@@ -3090,13 +3016,10 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
* broadcast frame from an IBSS network. Drop it silently.
* If BSSID is own, report the dropping of this frame. */
if (memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) {
- printk(KERN_DEBUG "%s: dropped received packet from "
- MAC_FMT " with no ToDS flag "
+ printk(KERN_DEBUG "%s: dropped received packet from %pM"
+ " with no ToDS flag "
"(type=0x%02x, subtype=0x%02x)\n", dev->name,
- hdr->addr2[0], hdr->addr2[1],
- hdr->addr2[2], hdr->addr2[3],
- hdr->addr2[4], hdr->addr2[5],
- type >> 2, stype >> 4);
+ hdr->addr2, type >> 2, stype >> 4);
hostap_dump_rx_80211(dev->name, skb, rx_stats);
}
ret = AP_RX_DROP;
@@ -3142,7 +3065,7 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
/* Called only as a tasklet (software IRQ) */
int hostap_handle_sta_crypto(local_info_t *local,
struct ieee80211_hdr_4addr *hdr,
- struct ieee80211_crypt_data **crypt,
+ struct lib80211_crypt_data **crypt,
void **sta_ptr)
{
struct sta_info *sta;
@@ -3290,7 +3213,7 @@ void hostap_update_rates(local_info_t *local)
void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent,
- struct ieee80211_crypt_data ***crypt)
+ struct lib80211_crypt_data ***crypt)
{
struct sta_info *sta;
diff --git a/drivers/net/wireless/hostap/hostap_ap.h b/drivers/net/wireless/hostap/hostap_ap.h
index 2fa2452b6b07..d36e4b175336 100644
--- a/drivers/net/wireless/hostap/hostap_ap.h
+++ b/drivers/net/wireless/hostap/hostap_ap.h
@@ -74,7 +74,7 @@ struct sta_info {
u32 tx_since_last_failure;
u32 tx_consecutive_exc;
- struct ieee80211_crypt_data *crypt;
+ struct lib80211_crypt_data *crypt;
int ap; /* whether this station is an AP */
@@ -209,7 +209,7 @@ struct ap_data {
/* WEP operations for generating challenges to be used with shared key
* authentication */
- struct ieee80211_crypto_ops *crypt;
+ struct lib80211_crypto_ops *crypt;
void *crypt_priv;
#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */
};
@@ -229,7 +229,7 @@ typedef enum {
struct hostap_tx_data {
struct sk_buff *skb;
int host_encrypt;
- struct ieee80211_crypt_data *crypt;
+ struct lib80211_crypt_data *crypt;
void *sta_ptr;
};
ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx);
@@ -244,7 +244,7 @@ ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev,
struct hostap_80211_rx_status *rx_stats,
int wds);
int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr_4addr *hdr,
- struct ieee80211_crypt_data **crypt,
+ struct lib80211_crypt_data **crypt,
void **sta_ptr);
int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr);
int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr);
diff --git a/drivers/net/wireless/hostap/hostap_common.h b/drivers/net/wireless/hostap/hostap_common.h
index b470c743c2d1..90b64b092007 100644
--- a/drivers/net/wireless/hostap/hostap_common.h
+++ b/drivers/net/wireless/hostap/hostap_common.h
@@ -6,19 +6,6 @@
/* IEEE 802.11 defines */
-/* Information Element IDs */
-#define WLAN_EID_SSID 0
-#define WLAN_EID_SUPP_RATES 1
-#define WLAN_EID_FH_PARAMS 2
-#define WLAN_EID_DS_PARAMS 3
-#define WLAN_EID_CF_PARAMS 4
-#define WLAN_EID_TIM 5
-#define WLAN_EID_IBSS_PARAMS 6
-#define WLAN_EID_CHALLENGE 16
-#define WLAN_EID_RSN 48
-#define WLAN_EID_GENERIC 221
-
-
/* HFA384X Configuration RIDs */
#define HFA384X_RID_CNFPORTTYPE 0xFC00
#define HFA384X_RID_CNFOWNMACADDR 0xFC01
diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c
index 3153fe9d7ce0..0f27059bbe85 100644
--- a/drivers/net/wireless/hostap/hostap_hw.c
+++ b/drivers/net/wireless/hostap/hostap_hw.c
@@ -47,7 +47,7 @@
#include <linux/wireless.h>
#include <net/iw_handler.h>
#include <net/ieee80211.h>
-#include <net/ieee80211_crypt.h>
+#include <net/lib80211.h>
#include <asm/irq.h>
#include "hostap_80211.h"
@@ -2335,10 +2335,6 @@ static void prism2_txexc(local_info_t *local)
int show_dump, res;
char *payload = NULL;
struct hfa384x_tx_frame txdesc;
- DECLARE_MAC_BUF(mac);
- DECLARE_MAC_BUF(mac2);
- DECLARE_MAC_BUF(mac3);
- DECLARE_MAC_BUF(mac4);
show_dump = local->frame_dump & PRISM2_DUMP_TXEXC_HDR;
local->stats.tx_errors++;
@@ -2404,9 +2400,9 @@ static void prism2_txexc(local_info_t *local)
WLAN_FC_GET_STYPE(fc) >> 4,
fc & IEEE80211_FCTL_TODS ? " ToDS" : "",
fc & IEEE80211_FCTL_FROMDS ? " FromDS" : "");
- PDEBUG(DEBUG_EXTRA, " A1=%s A2=%s A3=%s A4=%s\n",
- print_mac(mac, txdesc.addr1), print_mac(mac2, txdesc.addr2),
- print_mac(mac3, txdesc.addr3), print_mac(mac4, txdesc.addr4));
+ PDEBUG(DEBUG_EXTRA, " A1=%pM A2=%pM A3=%pM A4=%pM\n",
+ txdesc.addr1, txdesc.addr2,
+ txdesc.addr3, txdesc.addr4);
}
@@ -2792,45 +2788,6 @@ static void prism2_check_sta_fw_version(local_info_t *local)
}
-static void prism2_crypt_deinit_entries(local_info_t *local, int force)
-{
- struct list_head *ptr, *n;
- struct ieee80211_crypt_data *entry;
-
- for (ptr = local->crypt_deinit_list.next, n = ptr->next;
- ptr != &local->crypt_deinit_list; ptr = n, n = ptr->next) {
- entry = list_entry(ptr, struct ieee80211_crypt_data, list);
-
- if (atomic_read(&entry->refcnt) != 0 && !force)
- continue;
-
- list_del(ptr);
-
- if (entry->ops)
- entry->ops->deinit(entry->priv);
- kfree(entry);
- }
-}
-
-
-static void prism2_crypt_deinit_handler(unsigned long data)
-{
- local_info_t *local = (local_info_t *) data;
- unsigned long flags;
-
- spin_lock_irqsave(&local->lock, flags);
- prism2_crypt_deinit_entries(local, 0);
- if (!list_empty(&local->crypt_deinit_list)) {
- printk(KERN_DEBUG "%s: entries remaining in delayed crypt "
- "deletion list\n", local->dev->name);
- local->crypt_deinit_timer.expires = jiffies + HZ;
- add_timer(&local->crypt_deinit_timer);
- }
- spin_unlock_irqrestore(&local->lock, flags);
-
-}
-
-
static void hostap_passive_scan(unsigned long data)
{
local_info_t *local = (local_info_t *) data;
@@ -3254,10 +3211,8 @@ while (0)
INIT_LIST_HEAD(&local->cmd_queue);
init_waitqueue_head(&local->hostscan_wq);
- INIT_LIST_HEAD(&local->crypt_deinit_list);
- init_timer(&local->crypt_deinit_timer);
- local->crypt_deinit_timer.data = (unsigned long) local;
- local->crypt_deinit_timer.function = prism2_crypt_deinit_handler;
+
+ lib80211_crypt_info_init(&local->crypt_info, dev->name, &local->lock);
init_timer(&local->passive_scan_timer);
local->passive_scan_timer.data = (unsigned long) local;
@@ -3358,9 +3313,7 @@ static void prism2_free_local_data(struct net_device *dev)
flush_scheduled_work();
- if (timer_pending(&local->crypt_deinit_timer))
- del_timer(&local->crypt_deinit_timer);
- prism2_crypt_deinit_entries(local, 1);
+ lib80211_crypt_info_free(&local->crypt_info);
if (timer_pending(&local->passive_scan_timer))
del_timer(&local->passive_scan_timer);
@@ -3377,16 +3330,6 @@ static void prism2_free_local_data(struct net_device *dev)
if (local->dev_enabled)
prism2_callback(local, PRISM2_CALLBACK_DISABLE);
- for (i = 0; i < WEP_KEYS; i++) {
- struct ieee80211_crypt_data *crypt = local->crypt[i];
- if (crypt) {
- if (crypt->ops)
- crypt->ops->deinit(crypt->priv);
- kfree(crypt);
- local->crypt[i] = NULL;
- }
- }
-
if (local->ap != NULL)
hostap_free_data(local->ap);
diff --git a/drivers/net/wireless/hostap/hostap_info.c b/drivers/net/wireless/hostap/hostap_info.c
index 7cd3fb79230e..99b4cf41edf2 100644
--- a/drivers/net/wireless/hostap/hostap_info.c
+++ b/drivers/net/wireless/hostap/hostap_info.c
@@ -166,7 +166,6 @@ static void prism2_host_roaming(local_info_t *local)
struct hfa384x_hostscan_result *selected, *entry;
int i;
unsigned long flags;
- DECLARE_MAC_BUF(mac);
if (local->last_join_time &&
time_before(jiffies, local->last_join_time + 10 * HZ)) {
@@ -199,9 +198,8 @@ static void prism2_host_roaming(local_info_t *local)
local->preferred_ap[2] || local->preferred_ap[3] ||
local->preferred_ap[4] || local->preferred_ap[5]) {
/* Try to find preferred AP */
- PDEBUG(DEBUG_EXTRA, "%s: Preferred AP BSSID "
- "%s\n",
- dev->name, print_mac(mac, local->preferred_ap));
+ PDEBUG(DEBUG_EXTRA, "%s: Preferred AP BSSID %pM\n",
+ dev->name, local->preferred_ap);
for (i = 0; i < local->last_scan_results_count; i++) {
entry = &local->last_scan_results[i];
if (memcmp(local->preferred_ap, entry->bssid, 6) == 0)
@@ -218,9 +216,9 @@ static void prism2_host_roaming(local_info_t *local)
req.channel = selected->chid;
spin_unlock_irqrestore(&local->lock, flags);
- PDEBUG(DEBUG_EXTRA, "%s: JoinRequest: BSSID=%s"
+ PDEBUG(DEBUG_EXTRA, "%s: JoinRequest: BSSID=%pM"
" channel=%d\n",
- dev->name, print_mac(mac, req.bssid), le16_to_cpu(req.channel));
+ dev->name, req.bssid, le16_to_cpu(req.channel));
if (local->func->set_rid(dev, HFA384X_RID_JOINREQUEST, &req,
sizeof(req))) {
printk(KERN_DEBUG "%s: JoinRequest failed\n", dev->name);
@@ -413,7 +411,6 @@ static void handle_info_queue_linkstatus(local_info_t *local)
int val = local->prev_link_status;
int connected;
union iwreq_data wrqu;
- DECLARE_MAC_BUF(mac);
connected =
val == HFA384X_LINKSTATUS_CONNECTED ||
@@ -425,10 +422,9 @@ static void handle_info_queue_linkstatus(local_info_t *local)
printk(KERN_DEBUG "%s: could not read CURRENTBSSID after "
"LinkStatus event\n", local->dev->name);
} else {
- PDEBUG(DEBUG_EXTRA, "%s: LinkStatus: BSSID="
- "%s\n",
+ PDEBUG(DEBUG_EXTRA, "%s: LinkStatus: BSSID=%pM\n",
local->dev->name,
- print_mac(mac, (unsigned char *) local->bssid));
+ (unsigned char *) local->bssid);
if (local->wds_type & HOSTAP_WDS_AP_CLIENT)
hostap_add_sta(local->ap, local->bssid);
}
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c
index 3f8b1d7036e5..c40fdf4c79de 100644
--- a/drivers/net/wireless/hostap/hostap_ioctl.c
+++ b/drivers/net/wireless/hostap/hostap_ioctl.c
@@ -2,7 +2,7 @@
#include <linux/types.h>
#include <linux/ethtool.h>
-#include <net/ieee80211_crypt.h>
+#include <net/lib80211.h>
#include "hostap_wlan.h"
#include "hostap.h"
@@ -116,32 +116,6 @@ static int prism2_get_name(struct net_device *dev,
}
-static void prism2_crypt_delayed_deinit(local_info_t *local,
- struct ieee80211_crypt_data **crypt)
-{
- struct ieee80211_crypt_data *tmp;
- unsigned long flags;
-
- tmp = *crypt;
- *crypt = NULL;
-
- if (tmp == NULL)
- return;
-
- /* must not run ops->deinit() while there may be pending encrypt or
- * decrypt operations. Use a list of delayed deinits to avoid needing
- * locking. */
-
- spin_lock_irqsave(&local->lock, flags);
- list_add(&tmp->list, &local->crypt_deinit_list);
- if (!timer_pending(&local->crypt_deinit_timer)) {
- local->crypt_deinit_timer.expires = jiffies + HZ;
- add_timer(&local->crypt_deinit_timer);
- }
- spin_unlock_irqrestore(&local->lock, flags);
-}
-
-
static int prism2_ioctl_siwencode(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *erq, char *keybuf)
@@ -149,47 +123,47 @@ static int prism2_ioctl_siwencode(struct net_device *dev,
struct hostap_interface *iface;
local_info_t *local;
int i;
- struct ieee80211_crypt_data **crypt;
+ struct lib80211_crypt_data **crypt;
iface = netdev_priv(dev);
local = iface->local;
i = erq->flags & IW_ENCODE_INDEX;
if (i < 1 || i > 4)
- i = local->tx_keyidx;
+ i = local->crypt_info.tx_keyidx;
else
i--;
if (i < 0 || i >= WEP_KEYS)
return -EINVAL;
- crypt = &local->crypt[i];
+ crypt = &local->crypt_info.crypt[i];
if (erq->flags & IW_ENCODE_DISABLED) {
if (*crypt)
- prism2_crypt_delayed_deinit(local, crypt);
+ lib80211_crypt_delayed_deinit(&local->crypt_info, crypt);
goto done;
}
if (*crypt != NULL && (*crypt)->ops != NULL &&
strcmp((*crypt)->ops->name, "WEP") != 0) {
/* changing to use WEP; deinit previously used algorithm */
- prism2_crypt_delayed_deinit(local, crypt);
+ lib80211_crypt_delayed_deinit(&local->crypt_info, crypt);
}
if (*crypt == NULL) {
- struct ieee80211_crypt_data *new_crypt;
+ struct lib80211_crypt_data *new_crypt;
/* take WEP into use */
- new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
+ new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
GFP_KERNEL);
if (new_crypt == NULL)
return -ENOMEM;
- new_crypt->ops = ieee80211_get_crypto_ops("WEP");
+ new_crypt->ops = lib80211_get_crypto_ops("WEP");
if (!new_crypt->ops) {
- request_module("ieee80211_crypt_wep");
- new_crypt->ops = ieee80211_get_crypto_ops("WEP");
+ request_module("lib80211_crypt_wep");
+ new_crypt->ops = lib80211_get_crypto_ops("WEP");
}
- if (new_crypt->ops)
+ if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
new_crypt->priv = new_crypt->ops->init(i);
if (!new_crypt->ops || !new_crypt->priv) {
kfree(new_crypt);
@@ -210,16 +184,16 @@ static int prism2_ioctl_siwencode(struct net_device *dev,
memset(keybuf + erq->length, 0, len - erq->length);
(*crypt)->ops->set_key(keybuf, len, NULL, (*crypt)->priv);
for (j = 0; j < WEP_KEYS; j++) {
- if (j != i && local->crypt[j]) {
+ if (j != i && local->crypt_info.crypt[j]) {
first = 0;
break;
}
}
if (first)
- local->tx_keyidx = i;
+ local->crypt_info.tx_keyidx = i;
} else {
/* No key data - just set the default TX key index */
- local->tx_keyidx = i;
+ local->crypt_info.tx_keyidx = i;
}
done:
@@ -252,20 +226,20 @@ static int prism2_ioctl_giwencode(struct net_device *dev,
local_info_t *local;
int i, len;
u16 val;
- struct ieee80211_crypt_data *crypt;
+ struct lib80211_crypt_data *crypt;
iface = netdev_priv(dev);
local = iface->local;
i = erq->flags & IW_ENCODE_INDEX;
if (i < 1 || i > 4)
- i = local->tx_keyidx;
+ i = local->crypt_info.tx_keyidx;
else
i--;
if (i < 0 || i >= WEP_KEYS)
return -EINVAL;
- crypt = local->crypt[i];
+ crypt = local->crypt_info.crypt[i];
erq->flags = i + 1;
if (crypt == NULL || crypt->ops == NULL) {
@@ -664,7 +638,6 @@ static int hostap_join_ap(struct net_device *dev)
unsigned long flags;
int i;
struct hfa384x_hostscan_result *entry;
- DECLARE_MAC_BUF(mac);
iface = netdev_priv(dev);
local = iface->local;
@@ -686,14 +659,13 @@ static int hostap_join_ap(struct net_device *dev)
if (local->func->set_rid(dev, HFA384X_RID_JOINREQUEST, &req,
sizeof(req))) {
- printk(KERN_DEBUG "%s: JoinRequest %s"
- " failed\n",
- dev->name, print_mac(mac, local->preferred_ap));
+ printk(KERN_DEBUG "%s: JoinRequest %pM failed\n",
+ dev->name, local->preferred_ap);
return -1;
}
- printk(KERN_DEBUG "%s: Trying to join BSSID %s\n",
- dev->name, print_mac(mac, local->preferred_ap));
+ printk(KERN_DEBUG "%s: Trying to join BSSID %pM\n",
+ dev->name, local->preferred_ap);
return 0;
}
@@ -3229,8 +3201,8 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
local_info_t *local = iface->local;
struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
int i, ret = 0;
- struct ieee80211_crypto_ops *ops;
- struct ieee80211_crypt_data **crypt;
+ struct lib80211_crypto_ops *ops;
+ struct lib80211_crypt_data **crypt;
void *sta_ptr;
u8 *addr;
const char *alg, *module;
@@ -3239,7 +3211,7 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
if (i > WEP_KEYS)
return -EINVAL;
if (i < 1 || i > WEP_KEYS)
- i = local->tx_keyidx;
+ i = local->crypt_info.tx_keyidx;
else
i--;
if (i < 0 || i >= WEP_KEYS)
@@ -3249,7 +3221,7 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff &&
addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) {
sta_ptr = NULL;
- crypt = &local->crypt[i];
+ crypt = &local->crypt_info.crypt[i];
} else {
if (i != 0)
return -EINVAL;
@@ -3262,7 +3234,7 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
* is emulated by using default key idx 0.
*/
i = 0;
- crypt = &local->crypt[i];
+ crypt = &local->crypt_info.crypt[i];
} else
return -EINVAL;
}
@@ -3271,22 +3243,22 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
if ((erq->flags & IW_ENCODE_DISABLED) ||
ext->alg == IW_ENCODE_ALG_NONE) {
if (*crypt)
- prism2_crypt_delayed_deinit(local, crypt);
+ lib80211_crypt_delayed_deinit(&local->crypt_info, crypt);
goto done;
}
switch (ext->alg) {
case IW_ENCODE_ALG_WEP:
alg = "WEP";
- module = "ieee80211_crypt_wep";
+ module = "lib80211_crypt_wep";
break;
case IW_ENCODE_ALG_TKIP:
alg = "TKIP";
- module = "ieee80211_crypt_tkip";
+ module = "lib80211_crypt_tkip";
break;
case IW_ENCODE_ALG_CCMP:
alg = "CCMP";
- module = "ieee80211_crypt_ccmp";
+ module = "lib80211_crypt_ccmp";
break;
default:
printk(KERN_DEBUG "%s: unsupported algorithm %d\n",
@@ -3295,10 +3267,10 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
goto done;
}
- ops = ieee80211_get_crypto_ops(alg);
+ ops = lib80211_get_crypto_ops(alg);
if (ops == NULL) {
request_module(module);
- ops = ieee80211_get_crypto_ops(alg);
+ ops = lib80211_get_crypto_ops(alg);
}
if (ops == NULL) {
printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n",
@@ -3317,18 +3289,19 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
}
if (*crypt == NULL || (*crypt)->ops != ops) {
- struct ieee80211_crypt_data *new_crypt;
+ struct lib80211_crypt_data *new_crypt;
- prism2_crypt_delayed_deinit(local, crypt);
+ lib80211_crypt_delayed_deinit(&local->crypt_info, crypt);
- new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
+ new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
GFP_KERNEL);
if (new_crypt == NULL) {
ret = -ENOMEM;
goto done;
}
new_crypt->ops = ops;
- new_crypt->priv = new_crypt->ops->init(i);
+ if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+ new_crypt->priv = new_crypt->ops->init(i);
if (new_crypt->priv == NULL) {
kfree(new_crypt);
ret = -EINVAL;
@@ -3356,20 +3329,20 @@ static int prism2_ioctl_siwencodeext(struct net_device *dev,
if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
if (!sta_ptr)
- local->tx_keyidx = i;
+ local->crypt_info.tx_keyidx = i;
}
if (sta_ptr == NULL && ext->key_len > 0) {
int first = 1, j;
for (j = 0; j < WEP_KEYS; j++) {
- if (j != i && local->crypt[j]) {
+ if (j != i && local->crypt_info.crypt[j]) {
first = 0;
break;
}
}
if (first)
- local->tx_keyidx = i;
+ local->crypt_info.tx_keyidx = i;
}
done:
@@ -3401,7 +3374,7 @@ static int prism2_ioctl_giwencodeext(struct net_device *dev,
{
struct hostap_interface *iface = netdev_priv(dev);
local_info_t *local = iface->local;
- struct ieee80211_crypt_data **crypt;
+ struct lib80211_crypt_data **crypt;
void *sta_ptr;
int max_key_len, i;
struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
@@ -3413,7 +3386,7 @@ static int prism2_ioctl_giwencodeext(struct net_device *dev,
i = erq->flags & IW_ENCODE_INDEX;
if (i < 1 || i > WEP_KEYS)
- i = local->tx_keyidx;
+ i = local->crypt_info.tx_keyidx;
else
i--;
@@ -3421,7 +3394,7 @@ static int prism2_ioctl_giwencodeext(struct net_device *dev,
if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff &&
addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) {
sta_ptr = NULL;
- crypt = &local->crypt[i];
+ crypt = &local->crypt_info.crypt[i];
} else {
i = 0;
sta_ptr = ap_crypt_get_ptrs(local->ap, addr, 0, &crypt);
@@ -3470,8 +3443,8 @@ static int prism2_ioctl_set_encryption(local_info_t *local,
int param_len)
{
int ret = 0;
- struct ieee80211_crypto_ops *ops;
- struct ieee80211_crypt_data **crypt;
+ struct lib80211_crypto_ops *ops;
+ struct lib80211_crypt_data **crypt;
void *sta_ptr;
param->u.crypt.err = 0;
@@ -3488,7 +3461,7 @@ static int prism2_ioctl_set_encryption(local_info_t *local,
if (param->u.crypt.idx >= WEP_KEYS)
return -EINVAL;
sta_ptr = NULL;
- crypt = &local->crypt[param->u.crypt.idx];
+ crypt = &local->crypt_info.crypt[param->u.crypt.idx];
} else {
if (param->u.crypt.idx)
return -EINVAL;
@@ -3505,20 +3478,20 @@ static int prism2_ioctl_set_encryption(local_info_t *local,
if (strcmp(param->u.crypt.alg, "none") == 0) {
if (crypt)
- prism2_crypt_delayed_deinit(local, crypt);
+ lib80211_crypt_delayed_deinit(&local->crypt_info, crypt);
goto done;
}
- ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
+ ops = lib80211_get_crypto_ops(param->u.crypt.alg);
if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
- request_module("ieee80211_crypt_wep");
- ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
+ request_module("lib80211_crypt_wep");
+ ops = lib80211_get_crypto_ops(param->u.crypt.alg);
} else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
- request_module("ieee80211_crypt_tkip");
- ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
+ request_module("lib80211_crypt_tkip");
+ ops = lib80211_get_crypto_ops(param->u.crypt.alg);
} else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
- request_module("ieee80211_crypt_ccmp");
- ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
+ request_module("lib80211_crypt_ccmp");
+ ops = lib80211_get_crypto_ops(param->u.crypt.alg);
}
if (ops == NULL) {
printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n",
@@ -3533,11 +3506,11 @@ static int prism2_ioctl_set_encryption(local_info_t *local,
local->host_decrypt = local->host_encrypt = 1;
if (*crypt == NULL || (*crypt)->ops != ops) {
- struct ieee80211_crypt_data *new_crypt;
+ struct lib80211_crypt_data *new_crypt;
- prism2_crypt_delayed_deinit(local, crypt);
+ lib80211_crypt_delayed_deinit(&local->crypt_info, crypt);
- new_crypt = kzalloc(sizeof(struct ieee80211_crypt_data),
+ new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
GFP_KERNEL);
if (new_crypt == NULL) {
ret = -ENOMEM;
@@ -3570,7 +3543,7 @@ static int prism2_ioctl_set_encryption(local_info_t *local,
if (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) {
if (!sta_ptr)
- local->tx_keyidx = param->u.crypt.idx;
+ local->crypt_info.tx_keyidx = param->u.crypt.idx;
else if (param->u.crypt.idx) {
printk(KERN_DEBUG "%s: TX key idx setting failed\n",
local->dev->name);
@@ -3606,7 +3579,7 @@ static int prism2_ioctl_get_encryption(local_info_t *local,
struct prism2_hostapd_param *param,
int param_len)
{
- struct ieee80211_crypt_data **crypt;
+ struct lib80211_crypt_data **crypt;
void *sta_ptr;
int max_key_len;
@@ -3622,8 +3595,8 @@ static int prism2_ioctl_get_encryption(local_info_t *local,
param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
sta_ptr = NULL;
if (param->u.crypt.idx >= WEP_KEYS)
- param->u.crypt.idx = local->tx_keyidx;
- crypt = &local->crypt[param->u.crypt.idx];
+ param->u.crypt.idx = local->crypt_info.tx_keyidx;
+ crypt = &local->crypt_info.crypt[param->u.crypt.idx];
} else {
param->u.crypt.idx = 0;
sta_ptr = ap_crypt_get_ptrs(local->ap, param->sta_addr, 0,
@@ -3701,10 +3674,8 @@ static int prism2_ioctl_set_assoc_ap_addr(local_info_t *local,
struct prism2_hostapd_param *param,
int param_len)
{
- DECLARE_MAC_BUF(mac);
- printk(KERN_DEBUG "%ssta: associated as client with AP "
- "%s\n",
- local->dev->name, print_mac(mac, param->sta_addr));
+ printk(KERN_DEBUG "%ssta: associated as client with AP %pM\n",
+ local->dev->name, param->sta_addr);
memcpy(local->assoc_ap_addr, param->sta_addr, ETH_ALEN);
return 0;
}
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 756ab56c1f40..02a312ca8607 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -27,7 +27,7 @@
#include <net/net_namespace.h>
#include <net/iw_handler.h>
#include <net/ieee80211.h>
-#include <net/ieee80211_crypt.h>
+#include <net/lib80211.h>
#include <asm/uaccess.h>
#include "hostap_wlan.h"
@@ -343,10 +343,11 @@ int hostap_set_encryption(local_info_t *local)
char keybuf[WEP_KEY_LEN + 1];
enum { NONE, WEP, OTHER } encrypt_type;
- idx = local->tx_keyidx;
- if (local->crypt[idx] == NULL || local->crypt[idx]->ops == NULL)
+ idx = local->crypt_info.tx_keyidx;
+ if (local->crypt_info.crypt[idx] == NULL ||
+ local->crypt_info.crypt[idx]->ops == NULL)
encrypt_type = NONE;
- else if (strcmp(local->crypt[idx]->ops->name, "WEP") == 0)
+ else if (strcmp(local->crypt_info.crypt[idx]->ops->name, "WEP") == 0)
encrypt_type = WEP;
else
encrypt_type = OTHER;
@@ -394,17 +395,17 @@ int hostap_set_encryption(local_info_t *local)
/* 104-bit support seems to require that all the keys are set to the
* same keylen */
keylen = 6; /* first 5 octets */
- len = local->crypt[idx]->ops->get_key(keybuf, sizeof(keybuf),
- NULL, local->crypt[idx]->priv);
+ len = local->crypt_info.crypt[idx]->ops->get_key(keybuf, sizeof(keybuf), NULL,
+ local->crypt_info.crypt[idx]->priv);
if (idx >= 0 && idx < WEP_KEYS && len > 5)
keylen = WEP_KEY_LEN + 1; /* first 13 octets */
for (i = 0; i < WEP_KEYS; i++) {
memset(keybuf, 0, sizeof(keybuf));
- if (local->crypt[i]) {
- (void) local->crypt[i]->ops->get_key(
+ if (local->crypt_info.crypt[i]) {
+ (void) local->crypt_info.crypt[i]->ops->get_key(
keybuf, sizeof(keybuf),
- NULL, local->crypt[i]->priv);
+ NULL, local->crypt_info.crypt[i]->priv);
}
if (local->func->set_rid(local->dev,
HFA384X_RID_CNFDEFAULTKEY0 + i,
@@ -530,10 +531,6 @@ int hostap_set_auth_algs(local_info_t *local)
void hostap_dump_rx_header(const char *name, const struct hfa384x_rx_frame *rx)
{
u16 status, fc;
- DECLARE_MAC_BUF(mac);
- DECLARE_MAC_BUF(mac2);
- DECLARE_MAC_BUF(mac3);
- DECLARE_MAC_BUF(mac4);
status = __le16_to_cpu(rx->status);
@@ -552,12 +549,11 @@ void hostap_dump_rx_header(const char *name, const struct hfa384x_rx_frame *rx)
fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "",
fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : "");
- printk(KERN_DEBUG " A1=%s A2=%s A3=%s A4=%s\n",
- print_mac(mac, rx->addr1), print_mac(mac2, rx->addr2),
- print_mac(mac3, rx->addr3), print_mac(mac4, rx->addr4));
+ printk(KERN_DEBUG " A1=%pM A2=%pM A3=%pM A4=%pM\n",
+ rx->addr1, rx->addr2, rx->addr3, rx->addr4);
- printk(KERN_DEBUG " dst=%s src=%s len=%d\n",
- print_mac(mac, rx->dst_addr), print_mac(mac2, rx->src_addr),
+ printk(KERN_DEBUG " dst=%pM src=%pM len=%d\n",
+ rx->dst_addr, rx->src_addr,
__be16_to_cpu(rx->len));
}
@@ -565,10 +561,6 @@ void hostap_dump_rx_header(const char *name, const struct hfa384x_rx_frame *rx)
void hostap_dump_tx_header(const char *name, const struct hfa384x_tx_frame *tx)
{
u16 fc;
- DECLARE_MAC_BUF(mac);
- DECLARE_MAC_BUF(mac2);
- DECLARE_MAC_BUF(mac3);
- DECLARE_MAC_BUF(mac4);
printk(KERN_DEBUG "%s: TX status=0x%04x retry_count=%d tx_rate=%d "
"tx_control=0x%04x; jiffies=%ld\n",
@@ -584,12 +576,11 @@ void hostap_dump_tx_header(const char *name, const struct hfa384x_tx_frame *tx)
fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "",
fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : "");
- printk(KERN_DEBUG " A1=%s A2=%s A3=%s A4=%s\n",
- print_mac(mac, tx->addr1), print_mac(mac2, tx->addr2),
- print_mac(mac3, tx->addr3), print_mac(mac4, tx->addr4));
+ printk(KERN_DEBUG " A1=%pM A2=%pM A3=%pM A4=%pM\n",
+ tx->addr1, tx->addr2, tx->addr3, tx->addr4);
- printk(KERN_DEBUG " dst=%s src=%s len=%d\n",
- print_mac(mac, tx->dst_addr), print_mac(mac2, tx->src_addr),
+ printk(KERN_DEBUG " dst=%pM src=%pM len=%d\n",
+ tx->dst_addr, tx->src_addr,
__be16_to_cpu(tx->len));
}
diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c
index 3a874fc621d3..8fdd41f4b4f2 100644
--- a/drivers/net/wireless/hostap/hostap_pci.c
+++ b/drivers/net/wireless/hostap/hostap_pci.c
@@ -312,7 +312,7 @@ static int prism2_pci_probe(struct pci_dev *pdev,
goto err_out_disable;
}
- mem = ioremap(phymem, pci_resource_len(pdev, 0));
+ mem = pci_ioremap_bar(pdev, 0);
if (mem == NULL) {
printk(KERN_ERR "prism2: Cannot remap PCI memory region\n") ;
goto fail;
diff --git a/drivers/net/wireless/hostap/hostap_proc.c b/drivers/net/wireless/hostap/hostap_proc.c
index b03536008ad9..005ff25a405f 100644
--- a/drivers/net/wireless/hostap/hostap_proc.c
+++ b/drivers/net/wireless/hostap/hostap_proc.c
@@ -2,7 +2,7 @@
#include <linux/types.h>
#include <linux/proc_fs.h>
-#include <net/ieee80211_crypt.h>
+#include <net/lib80211.h>
#include "hostap_wlan.h"
#include "hostap.h"
@@ -36,9 +36,10 @@ static int prism2_debug_proc_read(char *page, char **start, off_t off,
p += sprintf(p, "dev_enabled=%d\n", local->dev_enabled);
p += sprintf(p, "sw_tick_stuck=%d\n", local->sw_tick_stuck);
for (i = 0; i < WEP_KEYS; i++) {
- if (local->crypt[i] && local->crypt[i]->ops) {
- p += sprintf(p, "crypt[%d]=%s\n",
- i, local->crypt[i]->ops->name);
+ if (local->crypt_info.crypt[i] &&
+ local->crypt_info.crypt[i]->ops) {
+ p += sprintf(p, "crypt[%d]=%s\n", i,
+ local->crypt_info.crypt[i]->ops->name);
}
}
p += sprintf(p, "pri_only=%d\n", local->pri_only);
@@ -106,7 +107,6 @@ static int prism2_wds_proc_read(char *page, char **start, off_t off,
local_info_t *local = (local_info_t *) data;
struct list_head *ptr;
struct hostap_interface *iface;
- DECLARE_MAC_BUF(mac);
if (off > PROC_LIMIT) {
*eof = 1;
@@ -118,9 +118,9 @@ static int prism2_wds_proc_read(char *page, char **start, off_t off,
iface = list_entry(ptr, struct hostap_interface, list);
if (iface->type != HOSTAP_INTERFACE_WDS)
continue;
- p += sprintf(p, "%s\t%s\n",
+ p += sprintf(p, "%s\t%pM\n",
iface->dev->name,
- print_mac(mac, iface->u.wds.remote_addr));
+ iface->u.wds.remote_addr);
if ((p - page) > PROC_LIMIT) {
printk(KERN_DEBUG "%s: wds proc did not fit\n",
local->dev->name);
@@ -148,7 +148,6 @@ static int prism2_bss_list_proc_read(char *page, char **start, off_t off,
struct list_head *ptr;
struct hostap_bss_info *bss;
int i;
- DECLARE_MAC_BUF(mac);
if (off > PROC_LIMIT) {
*eof = 1;
@@ -160,8 +159,8 @@ static int prism2_bss_list_proc_read(char *page, char **start, off_t off,
spin_lock_bh(&local->lock);
list_for_each(ptr, &local->bss_list) {
bss = list_entry(ptr, struct hostap_bss_info, list);
- p += sprintf(p, "%s\t%lu\t%u\t0x%x\t",
- print_mac(mac, bss->bssid), bss->last_update,
+ p += sprintf(p, "%pM\t%lu\t%u\t0x%x\t",
+ bss->bssid, bss->last_update,
bss->count, bss->capab_info);
for (i = 0; i < bss->ssid_len; i++) {
p += sprintf(p, "%c",
@@ -208,12 +207,13 @@ static int prism2_crypt_proc_read(char *page, char **start, off_t off,
return 0;
}
- p += sprintf(p, "tx_keyidx=%d\n", local->tx_keyidx);
+ p += sprintf(p, "tx_keyidx=%d\n", local->crypt_info.tx_keyidx);
for (i = 0; i < WEP_KEYS; i++) {
- if (local->crypt[i] && local->crypt[i]->ops &&
- local->crypt[i]->ops->print_stats) {
- p = local->crypt[i]->ops->print_stats(
- p, local->crypt[i]->priv);
+ if (local->crypt_info.crypt[i] &&
+ local->crypt_info.crypt[i]->ops &&
+ local->crypt_info.crypt[i]->ops->print_stats) {
+ p = local->crypt_info.crypt[i]->ops->print_stats(
+ p, local->crypt_info.crypt[i]->priv);
}
}
@@ -314,7 +314,6 @@ static int prism2_scan_results_proc_read(char *page, char **start, off_t off,
int entry, i, len, total = 0;
struct hfa384x_hostscan_result *scanres;
u8 *pos;
- DECLARE_MAC_BUF(mac);
p += sprintf(p, "CHID ANL SL BcnInt Capab Rate BSSID ATIM SupRates "
"SSID\n");
@@ -332,14 +331,14 @@ static int prism2_scan_results_proc_read(char *page, char **start, off_t off,
if ((p - page) > (PAGE_SIZE - 200))
break;
- p += sprintf(p, "%d %d %d %d 0x%02x %d %s %d ",
+ p += sprintf(p, "%d %d %d %d 0x%02x %d %pM %d ",
le16_to_cpu(scanres->chid),
(s16) le16_to_cpu(scanres->anl),
(s16) le16_to_cpu(scanres->sl),
le16_to_cpu(scanres->beacon_interval),
le16_to_cpu(scanres->capability),
le16_to_cpu(scanres->rate),
- print_mac(mac, scanres->bssid),
+ scanres->bssid,
le16_to_cpu(scanres->atim));
pos = scanres->sup_rates;
diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h
index a68f97c39359..4d8d51a353cd 100644
--- a/drivers/net/wireless/hostap/hostap_wlan.h
+++ b/drivers/net/wireless/hostap/hostap_wlan.h
@@ -6,6 +6,7 @@
#include <linux/mutex.h>
#include <net/iw_handler.h>
#include <net/ieee80211_radiotap.h>
+#include <net/lib80211.h>
#include "hostap_config.h"
#include "hostap_common.h"
@@ -763,10 +764,7 @@ struct local_info {
#define WEP_KEYS 4
#define WEP_KEY_LEN 13
- struct ieee80211_crypt_data *crypt[WEP_KEYS];
- int tx_keyidx; /* default TX key index (crypt[tx_keyidx]) */
- struct timer_list crypt_deinit_timer;
- struct list_head crypt_deinit_list;
+ struct lib80211_crypt_info crypt_info;
int open_wep; /* allow unencrypted frames */
int host_encrypt;
@@ -822,7 +820,7 @@ struct local_info {
int last_scan_results_count;
enum { PRISM2_SCAN, PRISM2_HOSTSCAN } last_scan_type;
struct work_struct info_queue;
- long pending_info; /* bit field of pending info_queue items */
+ unsigned long pending_info; /* bit field of pending info_queue items */
#define PRISM2_INFO_PENDING_LINKSTATUS 0
#define PRISM2_INFO_PENDING_SCANRESULTS 1
int prev_link_status; /* previous received LinkStatus info */
diff --git a/drivers/net/wireless/ipw2x00/Kconfig b/drivers/net/wireless/ipw2x00/Kconfig
new file mode 100644
index 000000000000..3d5cc4463d4d
--- /dev/null
+++ b/drivers/net/wireless/ipw2x00/Kconfig
@@ -0,0 +1,191 @@
+#
+# Intel Centrino wireless drivers
+#
+
+config IPW2100
+ tristate "Intel PRO/Wireless 2100 Network Connection"
+ depends on PCI && WLAN_80211
+ select WIRELESS_EXT
+ select FW_LOADER
+ select LIB80211
+ select LIBIPW
+ ---help---
+ A driver for the Intel PRO/Wireless 2100 Network
+ Connection 802.11b wireless network adapter.
+
+ See <file:Documentation/networking/README.ipw2100> for information on
+ the capabilities currently enabled in this driver and for tips
+ for debugging issues and problems.
+
+ In order to use this driver, you will need a firmware image for it.
+ You can obtain the firmware from
+ <http://ipw2100.sf.net/>. Once you have the firmware image, you
+ will need to place it in /lib/firmware.
+
+ You will also very likely need the Wireless Tools in order to
+ configure your card:
+
+ <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
+
+ It is recommended that you compile this driver as a module (M)
+ rather than built-in (Y). This driver requires firmware at device
+ initialization time, and when built-in this typically happens
+ before the filesystem is accessible (hence firmware will be
+ unavailable and initialization will fail). If you do choose to build
+ this driver into your kernel image, you can avoid this problem by
+ including the firmware and a firmware loader in an initramfs.
+
+config IPW2100_MONITOR
+ bool "Enable promiscuous mode"
+ depends on IPW2100
+ ---help---
+ Enables promiscuous/monitor mode support for the ipw2100 driver.
+ With this feature compiled into the driver, you can switch to
+ promiscuous mode via the Wireless Tool's Monitor mode. While in this
+ mode, no packets can be sent.
+
+config IPW2100_DEBUG
+ bool "Enable full debugging output in IPW2100 module."
+ depends on IPW2100
+ ---help---
+ This option will enable debug tracing output for the IPW2100.
+
+ This will result in the kernel module being ~60k larger. You can
+ control which debug output is sent to the kernel log by setting the
+ value in
+
+ /sys/bus/pci/drivers/ipw2100/debug_level
+
+ This entry will only exist if this option is enabled.
+
+ If you are not trying to debug or develop the IPW2100 driver, you
+ most likely want to say N here.
+
+config IPW2200
+ tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection"
+ depends on PCI && WLAN_80211
+ select WIRELESS_EXT
+ select FW_LOADER
+ select LIB80211
+ select LIBIPW
+ ---help---
+ A driver for the Intel PRO/Wireless 2200BG and 2915ABG Network
+ Connection adapters.
+
+ See <file:Documentation/networking/README.ipw2200> for
+ information on the capabilities currently enabled in this
+ driver and for tips for debugging issues and problems.
+
+ In order to use this driver, you will need a firmware image for it.
+ You can obtain the firmware from
+ <http://ipw2200.sf.net/>. See the above referenced README.ipw2200
+ for information on where to install the firmware images.
+
+ You will also very likely need the Wireless Tools in order to
+ configure your card:
+
+ <http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html>.
+
+ It is recommended that you compile this driver as a module (M)
+ rather than built-in (Y). This driver requires firmware at device
+ initialization time, and when built-in this typically happens
+ before the filesystem is accessible (hence firmware will be
+ unavailable and initialization will fail). If you do choose to build
+ this driver into your kernel image, you can avoid this problem by
+ including the firmware and a firmware loader in an initramfs.
+
+config IPW2200_MONITOR
+ bool "Enable promiscuous mode"
+ depends on IPW2200
+ ---help---
+ Enables promiscuous/monitor mode support for the ipw2200 driver.
+ With this feature compiled into the driver, you can switch to
+ promiscuous mode via the Wireless Tool's Monitor mode. While in this
+ mode, no packets can be sent.
+
+config IPW2200_RADIOTAP
+ bool "Enable radiotap format 802.11 raw packet support"
+ depends on IPW2200_MONITOR
+
+config IPW2200_PROMISCUOUS
+ bool "Enable creation of a RF radiotap promiscuous interface"
+ depends on IPW2200_MONITOR
+ select IPW2200_RADIOTAP
+ ---help---
+ Enables the creation of a second interface prefixed 'rtap'.
+ This second interface will provide every received in radiotap
+ format.
+
+ This is useful for performing wireless network analysis while
+ maintaining an active association.
+
+ Example usage:
+
+ % modprobe ipw2200 rtap_iface=1
+ % ifconfig rtap0 up
+ % tethereal -i rtap0
+
+ If you do not specify 'rtap_iface=1' as a module parameter then
+ the rtap interface will not be created and you will need to turn
+ it on via sysfs:
+
+ % echo 1 > /sys/bus/pci/drivers/ipw2200/*/rtap_iface
+
+config IPW2200_QOS
+ bool "Enable QoS support"
+ depends on IPW2200 && EXPERIMENTAL
+
+config IPW2200_DEBUG
+ bool "Enable full debugging output in IPW2200 module."
+ depends on IPW2200
+ ---help---
+ This option will enable low level debug tracing output for IPW2200.
+
+ Note, normal debug code is already compiled in. This low level
+ debug option enables debug on hot paths (e.g Tx, Rx, ISR) and
+ will result in the kernel module being ~70 larger. Most users
+ will typically not need this high verbosity debug information.
+
+ If you are not sure, say N here.
+
+config LIBIPW
+ tristate
+ select WIRELESS_EXT
+ select CRYPTO
+ select CRYPTO_ARC4
+ select CRYPTO_ECB
+ select CRYPTO_AES
+ select CRYPTO_MICHAEL_MIC
+ select CRYPTO_ECB
+ select CRC32
+ select LIB80211
+ select LIB80211_CRYPT_WEP
+ select LIB80211_CRYPT_TKIP
+ select LIB80211_CRYPT_CCMP
+ ---help---
+ This option enables the hardware independent IEEE 802.11
+ networking stack. This component is deprecated in favor of the
+ mac80211 component.
+
+config LIBIPW_DEBUG
+ bool "Full debugging output for the LIBIPW component"
+ depends on LIBIPW
+ ---help---
+ This option will enable debug tracing output for the
+ libipw component.
+
+ This will result in the kernel module being ~70k larger. You
+ can control which debug output is sent to the kernel log by
+ setting the value in
+
+ /proc/net/ieee80211/debug_level
+
+ For example:
+
+ % echo 0x00000FFO > /proc/net/ieee80211/debug_level
+
+ For a list of values you can assign to debug_level, you
+ can look at the bit mask values in <net/ieee80211.h>
+
+ If you are not trying to debug or develop the libipw
+ component, you most likely want to say N here.
diff --git a/drivers/net/wireless/ipw2x00/Makefile b/drivers/net/wireless/ipw2x00/Makefile
new file mode 100644
index 000000000000..aecd2cff462b
--- /dev/null
+++ b/drivers/net/wireless/ipw2x00/Makefile
@@ -0,0 +1,14 @@
+#
+# Makefile for the Intel Centrino wireless drivers
+#
+
+obj-$(CONFIG_IPW2100) += ipw2100.o
+obj-$(CONFIG_IPW2200) += ipw2200.o
+
+obj-$(CONFIG_LIBIPW) += libipw.o
+libipw-objs := \
+ libipw_module.o \
+ libipw_tx.o \
+ libipw_rx.o \
+ libipw_wx.o \
+ libipw_geo.o
diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index bca74811bc7f..1667065b86a7 100644
--- a/drivers/net/wireless/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -163,6 +163,8 @@ that only one external action is invoked at a time.
#include <linux/ctype.h>
#include <linux/pm_qos_params.h>
+#include <net/lib80211.h>
+
#include "ipw2100.h"
#define IPW2100_VERSION "git-1.2.2"
@@ -185,7 +187,7 @@ MODULE_LICENSE("GPL");
static int debug = 0;
static int mode = 0;
static int channel = 0;
-static int associate = 1;
+static int associate = 0;
static int disable = 0;
#ifdef CONFIG_PM
static struct ipw2100_fw ipw2100_firmware;
@@ -201,7 +203,7 @@ module_param(disable, int, 0444);
MODULE_PARM_DESC(debug, "debug level");
MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS,2=Monitor)");
MODULE_PARM_DESC(channel, "channel");
-MODULE_PARM_DESC(associate, "auto associate when scanning (default on)");
+MODULE_PARM_DESC(associate, "auto associate when scanning (default off)");
MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
static u32 ipw2100_debug_level = IPW_DL_NONE;
@@ -1914,7 +1916,7 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status)
u32 chan;
char *txratename;
u8 bssid[ETH_ALEN];
- DECLARE_MAC_BUF(mac);
+ DECLARE_SSID_BUF(ssid);
/*
* TBD: BSSID is usually 00:00:00:00:00:00 here and not
@@ -1975,10 +1977,9 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status)
break;
}
- IPW_DEBUG_INFO("%s: Associated with '%s' at %s, channel %d (BSSID="
- "%s)\n",
- priv->net_dev->name, escape_essid(essid, essid_len),
- txratename, chan, print_mac(mac, bssid));
+ IPW_DEBUG_INFO("%s: Associated with '%s' at %s, channel %d (BSSID=%pM)\n",
+ priv->net_dev->name, print_ssid(ssid, essid, essid_len),
+ txratename, chan, bssid);
/* now we copy read ssid into dev */
if (!(priv->config & CFG_STATIC_ESSID)) {
@@ -2004,8 +2005,9 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid,
.host_command_length = ssid_len
};
int err;
+ DECLARE_SSID_BUF(ssid);
- IPW_DEBUG_HC("SSID: '%s'\n", escape_essid(essid, ssid_len));
+ IPW_DEBUG_HC("SSID: '%s'\n", print_ssid(ssid, essid, ssid_len));
if (ssid_len)
memcpy(cmd.host_command_parameters, essid, ssid_len);
@@ -2046,12 +2048,12 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid,
static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status)
{
- DECLARE_MAC_BUF(mac);
+ DECLARE_SSID_BUF(ssid);
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC,
- "disassociated: '%s' %s \n",
- escape_essid(priv->essid, priv->essid_len),
- print_mac(mac, priv->bssid));
+ "disassociated: '%s' %pM \n",
+ print_ssid(ssid, priv->essid, priv->essid_len),
+ priv->bssid);
priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING);
@@ -4008,7 +4010,7 @@ static ssize_t show_internals(struct device *d, struct device_attribute *attr,
else
len += sprintf(buf + len, "not connected\n");
- DUMP_VAR(ieee->crypt[priv->ieee->tx_keyidx], "p");
+ DUMP_VAR(ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx], "p");
DUMP_VAR(status, "08lx");
DUMP_VAR(config, "08lx");
DUMP_VAR(capability, "08lx");
@@ -4058,7 +4060,6 @@ static ssize_t show_bssinfo(struct device *d, struct device_attribute *attr,
char *out = buf;
int length;
int ret;
- DECLARE_MAC_BUF(mac);
if (priv->status & STATUS_RF_KILL_MASK)
return 0;
@@ -4086,7 +4087,7 @@ static ssize_t show_bssinfo(struct device *d, struct device_attribute *attr,
__LINE__);
out += sprintf(out, "ESSID: %s\n", essid);
- out += sprintf(out, "BSSID: %s\n", print_mac(mac, bssid));
+ out += sprintf(out, "BSSID: %pM\n", bssid);
out += sprintf(out, "Channel: %d\n", chan);
return out - buf;
@@ -4662,7 +4663,6 @@ static int ipw2100_read_mac_address(struct ipw2100_priv *priv)
{
u32 length = ETH_ALEN;
u8 addr[ETH_ALEN];
- DECLARE_MAC_BUF(mac);
int err;
@@ -4673,8 +4673,7 @@ static int ipw2100_read_mac_address(struct ipw2100_priv *priv)
}
memcpy(priv->net_dev->dev_addr, addr, ETH_ALEN);
- IPW_DEBUG_INFO("card MAC is %s\n",
- print_mac(mac, priv->net_dev->dev_addr));
+ IPW_DEBUG_INFO("card MAC is %pM\n", priv->net_dev->dev_addr);
return 0;
}
@@ -5053,10 +5052,8 @@ static int ipw2100_set_mandatory_bssid(struct ipw2100_priv *priv, u8 * bssid,
int err;
#ifdef CONFIG_IPW2100_DEBUG
- DECLARE_MAC_BUF(mac);
if (bssid != NULL)
- IPW_DEBUG_HC("MANDATORY_BSSID: %s\n",
- print_mac(mac, bssid));
+ IPW_DEBUG_HC("MANDATORY_BSSID: %pM\n", bssid);
else
IPW_DEBUG_HC("MANDATORY_BSSID: <clear>\n");
#endif
@@ -5271,21 +5268,21 @@ static int ipw2100_set_ibss_beacon_interval(struct ipw2100_priv *priv,
return 0;
}
-void ipw2100_queues_initialize(struct ipw2100_priv *priv)
+static void ipw2100_queues_initialize(struct ipw2100_priv *priv)
{
ipw2100_tx_initialize(priv);
ipw2100_rx_initialize(priv);
ipw2100_msg_initialize(priv);
}
-void ipw2100_queues_free(struct ipw2100_priv *priv)
+static void ipw2100_queues_free(struct ipw2100_priv *priv)
{
ipw2100_tx_free(priv);
ipw2100_rx_free(priv);
ipw2100_msg_free(priv);
}
-int ipw2100_queues_allocate(struct ipw2100_priv *priv)
+static int ipw2100_queues_allocate(struct ipw2100_priv *priv)
{
if (ipw2100_tx_allocate(priv) ||
ipw2100_rx_allocate(priv) || ipw2100_msg_allocate(priv))
@@ -5517,7 +5514,7 @@ static int ipw2100_configure_security(struct ipw2100_priv *priv, int batch_mode)
}
}
- ipw2100_set_key_index(priv, priv->ieee->tx_keyidx, 1);
+ ipw2100_set_key_index(priv, priv->ieee->crypt_info.tx_keyidx, 1);
}
/* Always enable privacy so the Host can filter WEP packets if
@@ -6905,7 +6902,6 @@ static int ipw2100_wx_set_wap(struct net_device *dev,
static const unsigned char off[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
- DECLARE_MAC_BUF(mac);
// sanity checks
if (wrqu->ap_addr.sa_family != ARPHRD_ETHER)
@@ -6931,8 +6927,7 @@ static int ipw2100_wx_set_wap(struct net_device *dev,
err = ipw2100_set_mandatory_bssid(priv, wrqu->ap_addr.sa_data, 0);
- IPW_DEBUG_WX("SET BSSID -> %s\n",
- print_mac(mac, wrqu->ap_addr.sa_data));
+ IPW_DEBUG_WX("SET BSSID -> %pM\n", wrqu->ap_addr.sa_data);
done:
mutex_unlock(&priv->action_mutex);
@@ -6948,7 +6943,6 @@ static int ipw2100_wx_get_wap(struct net_device *dev,
*/
struct ipw2100_priv *priv = ieee80211_priv(dev);
- DECLARE_MAC_BUF(mac);
/* If we are associated, trying to associate, or have a statically
* configured BSSID then return that; otherwise return ANY */
@@ -6958,8 +6952,7 @@ static int ipw2100_wx_get_wap(struct net_device *dev,
} else
memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
- IPW_DEBUG_WX("Getting WAP BSSID: %s\n",
- print_mac(mac, wrqu->ap_addr.sa_data));
+ IPW_DEBUG_WX("Getting WAP BSSID: %pM\n", wrqu->ap_addr.sa_data);
return 0;
}
@@ -6971,6 +6964,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
char *essid = ""; /* ANY */
int length = 0;
int err = 0;
+ DECLARE_SSID_BUF(ssid);
mutex_lock(&priv->action_mutex);
if (!(priv->status & STATUS_INITIALIZED)) {
@@ -7000,8 +6994,8 @@ static int ipw2100_wx_set_essid(struct net_device *dev,
goto done;
}
- IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n", escape_essid(essid, length),
- length);
+ IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n",
+ print_ssid(ssid, essid, length), length);
priv->essid_len = length;
memcpy(priv->essid, essid, priv->essid_len);
@@ -7022,12 +7016,13 @@ static int ipw2100_wx_get_essid(struct net_device *dev,
*/
struct ipw2100_priv *priv = ieee80211_priv(dev);
+ DECLARE_SSID_BUF(ssid);
/* If we are associated, trying to associate, or have a statically
* configured ESSID then return that; otherwise return ANY */
if (priv->config & CFG_STATIC_ESSID || priv->status & STATUS_ASSOCIATED) {
IPW_DEBUG_WX("Getting essid: '%s'\n",
- escape_essid(priv->essid, priv->essid_len));
+ print_ssid(ssid, priv->essid, priv->essid_len));
memcpy(extra, priv->essid, priv->essid_len);
wrqu->essid.length = priv->essid_len;
wrqu->essid.flags = 1; /* active */
@@ -7625,7 +7620,7 @@ static int ipw2100_wx_set_auth(struct net_device *dev,
struct ipw2100_priv *priv = ieee80211_priv(dev);
struct ieee80211_device *ieee = priv->ieee;
struct iw_param *param = &wrqu->param;
- struct ieee80211_crypt_data *crypt;
+ struct lib80211_crypt_data *crypt;
unsigned long flags;
int ret = 0;
@@ -7640,7 +7635,7 @@ static int ipw2100_wx_set_auth(struct net_device *dev,
break;
case IW_AUTH_TKIP_COUNTERMEASURES:
- crypt = priv->ieee->crypt[priv->ieee->tx_keyidx];
+ crypt = priv->ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx];
if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags)
break;
@@ -7717,7 +7712,7 @@ static int ipw2100_wx_get_auth(struct net_device *dev,
{
struct ipw2100_priv *priv = ieee80211_priv(dev);
struct ieee80211_device *ieee = priv->ieee;
- struct ieee80211_crypt_data *crypt;
+ struct lib80211_crypt_data *crypt;
struct iw_param *param = &wrqu->param;
int ret = 0;
@@ -7733,7 +7728,7 @@ static int ipw2100_wx_get_auth(struct net_device *dev,
break;
case IW_AUTH_TKIP_COUNTERMEASURES:
- crypt = priv->ieee->crypt[priv->ieee->tx_keyidx];
+ crypt = priv->ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx];
if (!crypt || !crypt->ops->get_flags) {
IPW_DEBUG_WARNING("Can't get TKIP countermeasures: "
"crypt not set!\n");
diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2x00/ipw2100.h
index bbf1ddcafba8..bbf1ddcafba8 100644
--- a/drivers/net/wireless/ipw2100.h
+++ b/drivers/net/wireless/ipw2x00/ipw2100.h
diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index 7a9f901d4ff6..625f2cf99fa9 100644
--- a/drivers/net/wireless/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -87,7 +87,7 @@ static int channel = 0;
static int mode = 0;
static u32 ipw_debug_level;
-static int associate = 1;
+static int associate;
static int auto_create = 1;
static int led = 0;
static int disable = 0;
@@ -2265,8 +2265,8 @@ static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac)
return -1;
}
- IPW_DEBUG_INFO("%s: Setting MAC to %s\n",
- priv->net_dev->name, print_mac(mac, mac));
+ IPW_DEBUG_INFO("%s: Setting MAC to %pM\n",
+ priv->net_dev->name, mac);
return ipw_send_cmd_pdu(priv, IPW_CMD_ADAPTER_ADDRESS, ETH_ALEN, mac);
}
@@ -3812,7 +3812,6 @@ static u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid)
{
struct ipw_station_entry entry;
int i;
- DECLARE_MAC_BUF(mac);
for (i = 0; i < priv->num_stations; i++) {
if (!memcmp(priv->stations[i], bssid, ETH_ALEN)) {
@@ -3829,7 +3828,7 @@ static u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid)
if (i == MAX_STATIONS)
return IPW_INVALID_STATION;
- IPW_DEBUG_SCAN("Adding AdHoc station: %s\n", print_mac(mac, bssid));
+ IPW_DEBUG_SCAN("Adding AdHoc station: %pM\n", bssid);
entry.reserved = 0;
entry.support_mode = 0;
@@ -3856,7 +3855,6 @@ static u8 ipw_find_station(struct ipw_priv *priv, u8 * bssid)
static void ipw_send_disassociate(struct ipw_priv *priv, int quiet)
{
int err;
- DECLARE_MAC_BUF(mac);
if (priv->status & STATUS_ASSOCIATING) {
IPW_DEBUG_ASSOC("Disassociating while associating.\n");
@@ -3869,9 +3867,9 @@ static void ipw_send_disassociate(struct ipw_priv *priv, int quiet)
return;
}
- IPW_DEBUG_ASSOC("Disassocation attempt from %s "
+ IPW_DEBUG_ASSOC("Disassocation attempt from %pM "
"on channel %d.\n",
- print_mac(mac, priv->assoc_request.bssid),
+ priv->assoc_request.bssid,
priv->assoc_request.channel);
priv->status &= ~(STATUS_ASSOCIATING | STATUS_ASSOCIATED);
@@ -4347,7 +4345,8 @@ static void ipw_handle_missed_beacon(struct ipw_priv *priv,
return;
}
- if (priv->status & STATUS_SCANNING) {
+ if (priv->status & STATUS_SCANNING &&
+ missed_count > IPW_MB_SCAN_CANCEL_THRESHOLD) {
/* Stop scan to keep fw from getting
* stuck (only if we aren't roaming --
* otherwise we'll never scan more than 2 or 3
@@ -4398,7 +4397,7 @@ static void handle_scan_event(struct ipw_priv *priv)
static void ipw_rx_notification(struct ipw_priv *priv,
struct ipw_rx_notification *notif)
{
- DECLARE_MAC_BUF(mac);
+ DECLARE_SSID_BUF(ssid);
u16 size = le16_to_cpu(notif->size);
notif->size = le16_to_cpu(notif->size);
@@ -4412,11 +4411,10 @@ static void ipw_rx_notification(struct ipw_priv *priv,
case CMAS_ASSOCIATED:{
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
IPW_DL_ASSOC,
- "associated: '%s' %s"
- " \n",
- escape_essid(priv->essid,
- priv->essid_len),
- print_mac(mac, priv->bssid));
+ "associated: '%s' %pM \n",
+ print_ssid(ssid, priv->essid,
+ priv->essid_len),
+ priv->bssid);
switch (priv->ieee->iw_mode) {
case IW_MODE_INFRA:
@@ -4450,7 +4448,7 @@ static void ipw_rx_notification(struct ipw_priv *priv,
#ifdef CONFIG_IPW2200_QOS
#define IPW_GET_PACKET_STYPE(x) WLAN_FC_GET_STYPE( \
- le16_to_cpu(((struct ieee80211_hdr *)(x))->frame_ctl))
+ le16_to_cpu(((struct ieee80211_hdr *)(x))->frame_control))
if ((priv->status & STATUS_AUTH) &&
(IPW_GET_PACKET_STYPE(&notif->u.raw)
== IEEE80211_STYPE_ASSOC_RESP)) {
@@ -4493,13 +4491,14 @@ static void ipw_rx_notification(struct ipw_priv *priv,
IPW_DL_STATE |
IPW_DL_ASSOC,
"deauthenticated: '%s' "
- "%s"
+ "%pM"
": (0x%04X) - %s \n",
- escape_essid(priv->
- essid,
- priv->
- essid_len),
- print_mac(mac, priv->bssid),
+ print_ssid(ssid,
+ priv->
+ essid,
+ priv->
+ essid_len),
+ priv->bssid,
le16_to_cpu(auth->status),
ipw_get_status_code
(le16_to_cpu
@@ -4516,11 +4515,10 @@ static void ipw_rx_notification(struct ipw_priv *priv,
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
IPW_DL_ASSOC,
- "authenticated: '%s' %s"
- "\n",
- escape_essid(priv->essid,
- priv->essid_len),
- print_mac(mac, priv->bssid));
+ "authenticated: '%s' %pM\n",
+ print_ssid(ssid, priv->essid,
+ priv->essid_len),
+ priv->bssid);
break;
}
@@ -4545,11 +4543,10 @@ static void ipw_rx_notification(struct ipw_priv *priv,
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
IPW_DL_ASSOC,
- "disassociated: '%s' %s"
- " \n",
- escape_essid(priv->essid,
- priv->essid_len),
- print_mac(mac, priv->bssid));
+ "disassociated: '%s' %pM \n",
+ print_ssid(ssid, priv->essid,
+ priv->essid_len),
+ priv->bssid);
priv->status &=
~(STATUS_DISASSOCIATING |
@@ -4584,10 +4581,10 @@ static void ipw_rx_notification(struct ipw_priv *priv,
switch (auth->state) {
case CMAS_AUTHENTICATED:
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE,
- "authenticated: '%s' %s \n",
- escape_essid(priv->essid,
- priv->essid_len),
- print_mac(mac, priv->bssid));
+ "authenticated: '%s' %pM \n",
+ print_ssid(ssid, priv->essid,
+ priv->essid_len),
+ priv->bssid);
priv->status |= STATUS_AUTH;
break;
@@ -4603,10 +4600,10 @@ static void ipw_rx_notification(struct ipw_priv *priv,
}
IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE |
IPW_DL_ASSOC,
- "deauthenticated: '%s' %s\n",
- escape_essid(priv->essid,
- priv->essid_len),
- print_mac(mac, priv->bssid));
+ "deauthenticated: '%s' %pM\n",
+ print_ssid(ssid, priv->essid,
+ priv->essid_len),
+ priv->bssid);
priv->status &= ~(STATUS_ASSOCIATING |
STATUS_AUTH |
@@ -5430,27 +5427,17 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
int roaming)
{
struct ipw_supported_rates rates;
- DECLARE_MAC_BUF(mac);
- DECLARE_MAC_BUF(mac2);
+ DECLARE_SSID_BUF(ssid);
/* Verify that this network's capability is compatible with the
* current mode (AdHoc or Infrastructure) */
if ((priv->ieee->iw_mode == IW_MODE_ADHOC &&
!(network->capability & WLAN_CAPABILITY_IBSS))) {
- IPW_DEBUG_MERGE("Network '%s (%s)' excluded due to "
+ IPW_DEBUG_MERGE("Network '%s (%pM)' excluded due to "
"capability mismatch.\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid));
- return 0;
- }
-
- /* If we do not have an ESSID for this AP, we can not associate with
- * it */
- if (network->flags & NETWORK_EMPTY_ESSID) {
- IPW_DEBUG_MERGE("Network '%s (%s)' excluded "
- "because of hidden ESSID.\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid));
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid);
return 0;
}
@@ -5460,11 +5447,11 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
if ((network->ssid_len != match->network->ssid_len) ||
memcmp(network->ssid, match->network->ssid,
network->ssid_len)) {
- IPW_DEBUG_MERGE("Network '%s (%s)' excluded "
+ IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
"because of non-network ESSID.\n",
- escape_essid(network->ssid,
- network->ssid_len),
- print_mac(mac, network->bssid));
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid);
return 0;
}
} else {
@@ -5477,13 +5464,14 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
strncpy(escaped,
- escape_essid(network->ssid, network->ssid_len),
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
sizeof(escaped));
- IPW_DEBUG_MERGE("Network '%s (%s)' excluded "
+ IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
"because of ESSID mismatch: '%s'.\n",
- escaped, print_mac(mac, network->bssid),
- escape_essid(priv->essid,
- priv->essid_len));
+ escaped, network->bssid,
+ print_ssid(ssid, priv->essid,
+ priv->essid_len));
return 0;
}
}
@@ -5494,24 +5482,25 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
if (network->time_stamp[0] < match->network->time_stamp[0]) {
IPW_DEBUG_MERGE("Network '%s excluded because newer than "
"current network.\n",
- escape_essid(match->network->ssid,
- match->network->ssid_len));
+ print_ssid(ssid, match->network->ssid,
+ match->network->ssid_len));
return 0;
} else if (network->time_stamp[1] < match->network->time_stamp[1]) {
IPW_DEBUG_MERGE("Network '%s excluded because newer than "
"current network.\n",
- escape_essid(match->network->ssid,
- match->network->ssid_len));
+ print_ssid(ssid, match->network->ssid,
+ match->network->ssid_len));
return 0;
}
/* Now go through and see if the requested network is valid... */
if (priv->ieee->scan_age != 0 &&
time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) {
- IPW_DEBUG_MERGE("Network '%s (%s)' excluded "
+ IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
"because of age: %ums.\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid),
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid,
jiffies_to_msecs(jiffies -
network->last_scanned));
return 0;
@@ -5519,10 +5508,11 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
if ((priv->config & CFG_STATIC_CHANNEL) &&
(network->channel != priv->channel)) {
- IPW_DEBUG_MERGE("Network '%s (%s)' excluded "
+ IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
"because of channel mismatch: %d != %d.\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid),
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid,
network->channel, priv->channel);
return 0;
}
@@ -5530,10 +5520,11 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
/* Verify privacy compatability */
if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) !=
((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) {
- IPW_DEBUG_MERGE("Network '%s (%s)' excluded "
+ IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
"because of privacy mismatch: %s != %s.\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid),
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid,
priv->
capability & CAP_PRIVACY_ON ? "on" : "off",
network->
@@ -5543,41 +5534,44 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
}
if (!memcmp(network->bssid, priv->bssid, ETH_ALEN)) {
- IPW_DEBUG_MERGE("Network '%s (%s)' excluded "
- "because of the same BSSID match: %s"
- ".\n", escape_essid(network->ssid,
- network->ssid_len),
- print_mac(mac, network->bssid),
- print_mac(mac2, priv->bssid));
+ IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
+ "because of the same BSSID match: %pM"
+ ".\n", print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid,
+ priv->bssid);
return 0;
}
/* Filter out any incompatible freq / mode combinations */
if (!ieee80211_is_valid_mode(priv->ieee, network->mode)) {
- IPW_DEBUG_MERGE("Network '%s (%s)' excluded "
+ IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
"because of invalid frequency/mode "
"combination.\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid));
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid);
return 0;
}
/* Ensure that the rates supported by the driver are compatible with
* this AP, including verification of basic rates (mandatory) */
if (!ipw_compatible_rates(priv, network, &rates)) {
- IPW_DEBUG_MERGE("Network '%s (%s)' excluded "
+ IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
"because configured rate mask excludes "
"AP mandatory rate.\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid));
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid);
return 0;
}
if (rates.num_rates == 0) {
- IPW_DEBUG_MERGE("Network '%s (%s)' excluded "
+ IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
"because of no compatible rates.\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid));
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid);
return 0;
}
@@ -5588,15 +5582,16 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv,
/* Set up 'new' AP to this network */
ipw_copy_rates(&match->rates, &rates);
match->network = network;
- IPW_DEBUG_MERGE("Network '%s (%s)' is a viable match.\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid));
+ IPW_DEBUG_MERGE("Network '%s (%pM)' is a viable match.\n",
+ print_ssid(ssid, network->ssid, network->ssid_len),
+ network->bssid);
return 1;
}
static void ipw_merge_adhoc_network(struct work_struct *work)
{
+ DECLARE_SSID_BUF(ssid);
struct ipw_priv *priv =
container_of(work, struct ipw_priv, merge_networks);
struct ieee80211_network *network = NULL;
@@ -5627,8 +5622,8 @@ static void ipw_merge_adhoc_network(struct work_struct *work)
mutex_lock(&priv->mutex);
if ((priv->ieee->iw_mode == IW_MODE_ADHOC)) {
IPW_DEBUG_MERGE("remove network %s\n",
- escape_essid(priv->essid,
- priv->essid_len));
+ print_ssid(ssid, priv->essid,
+ priv->essid_len));
ipw_remove_current_network(priv);
}
@@ -5644,7 +5639,7 @@ static int ipw_best_network(struct ipw_priv *priv,
struct ieee80211_network *network, int roaming)
{
struct ipw_supported_rates rates;
- DECLARE_MAC_BUF(mac);
+ DECLARE_SSID_BUF(ssid);
/* Verify that this network's capability is compatible with the
* current mode (AdHoc or Infrastructure) */
@@ -5652,20 +5647,11 @@ static int ipw_best_network(struct ipw_priv *priv,
!(network->capability & WLAN_CAPABILITY_ESS)) ||
(priv->ieee->iw_mode == IW_MODE_ADHOC &&
!(network->capability & WLAN_CAPABILITY_IBSS))) {
- IPW_DEBUG_ASSOC("Network '%s (%s)' excluded due to "
+ IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded due to "
"capability mismatch.\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid));
- return 0;
- }
-
- /* If we do not have an ESSID for this AP, we can not associate with
- * it */
- if (network->flags & NETWORK_EMPTY_ESSID) {
- IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
- "because of hidden ESSID.\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid));
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid);
return 0;
}
@@ -5675,11 +5661,11 @@ static int ipw_best_network(struct ipw_priv *priv,
if ((network->ssid_len != match->network->ssid_len) ||
memcmp(network->ssid, match->network->ssid,
network->ssid_len)) {
- IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
+ IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
"because of non-network ESSID.\n",
- escape_essid(network->ssid,
- network->ssid_len),
- print_mac(mac, network->bssid));
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid);
return 0;
}
} else {
@@ -5691,13 +5677,14 @@ static int ipw_best_network(struct ipw_priv *priv,
min(network->ssid_len, priv->essid_len)))) {
char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
strncpy(escaped,
- escape_essid(network->ssid, network->ssid_len),
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
sizeof(escaped));
- IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
+ IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
"because of ESSID mismatch: '%s'.\n",
- escaped, print_mac(mac, network->bssid),
- escape_essid(priv->essid,
- priv->essid_len));
+ escaped, network->bssid,
+ print_ssid(ssid, priv->essid,
+ priv->essid_len));
return 0;
}
}
@@ -5707,14 +5694,14 @@ static int ipw_best_network(struct ipw_priv *priv,
if (match->network && match->network->stats.rssi > network->stats.rssi) {
char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
strncpy(escaped,
- escape_essid(network->ssid, network->ssid_len),
+ print_ssid(ssid, network->ssid, network->ssid_len),
sizeof(escaped));
- IPW_DEBUG_ASSOC("Network '%s (%s)' excluded because "
- "'%s (%s)' has a stronger signal.\n",
- escaped, print_mac(mac, network->bssid),
- escape_essid(match->network->ssid,
- match->network->ssid_len),
- print_mac(mac, match->network->bssid));
+ IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded because "
+ "'%s (%pM)' has a stronger signal.\n",
+ escaped, network->bssid,
+ print_ssid(ssid, match->network->ssid,
+ match->network->ssid_len),
+ match->network->bssid);
return 0;
}
@@ -5722,11 +5709,12 @@ static int ipw_best_network(struct ipw_priv *priv,
* last 3 seconds, do not try and associate again... */
if (network->last_associate &&
time_after(network->last_associate + (HZ * 3UL), jiffies)) {
- IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
+ IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
"because of storming (%ums since last "
"assoc attempt).\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid),
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid,
jiffies_to_msecs(jiffies -
network->last_associate));
return 0;
@@ -5735,10 +5723,11 @@ static int ipw_best_network(struct ipw_priv *priv,
/* Now go through and see if the requested network is valid... */
if (priv->ieee->scan_age != 0 &&
time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) {
- IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
+ IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
"because of age: %ums.\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid),
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid,
jiffies_to_msecs(jiffies -
network->last_scanned));
return 0;
@@ -5746,10 +5735,11 @@ static int ipw_best_network(struct ipw_priv *priv,
if ((priv->config & CFG_STATIC_CHANNEL) &&
(network->channel != priv->channel)) {
- IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
+ IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
"because of channel mismatch: %d != %d.\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid),
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid,
network->channel, priv->channel);
return 0;
}
@@ -5757,10 +5747,11 @@ static int ipw_best_network(struct ipw_priv *priv,
/* Verify privacy compatability */
if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) !=
((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) {
- IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
+ IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
"because of privacy mismatch: %s != %s.\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid),
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid,
priv->capability & CAP_PRIVACY_ON ? "on" :
"off",
network->capability &
@@ -5770,48 +5761,53 @@ static int ipw_best_network(struct ipw_priv *priv,
if ((priv->config & CFG_STATIC_BSSID) &&
memcmp(network->bssid, priv->bssid, ETH_ALEN)) {
- IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
- "because of BSSID mismatch: %s.\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid), print_mac(mac, priv->bssid));
+ IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
+ "because of BSSID mismatch: %pM.\n",
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid, priv->bssid);
return 0;
}
/* Filter out any incompatible freq / mode combinations */
if (!ieee80211_is_valid_mode(priv->ieee, network->mode)) {
- IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
+ IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
"because of invalid frequency/mode "
"combination.\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid));
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid);
return 0;
}
/* Filter out invalid channel in current GEO */
if (!ieee80211_is_valid_channel(priv->ieee, network->channel)) {
- IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
+ IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
"because of invalid channel in current GEO\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid));
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid);
return 0;
}
/* Ensure that the rates supported by the driver are compatible with
* this AP, including verification of basic rates (mandatory) */
if (!ipw_compatible_rates(priv, network, &rates)) {
- IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
+ IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
"because configured rate mask excludes "
"AP mandatory rate.\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid));
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid);
return 0;
}
if (rates.num_rates == 0) {
- IPW_DEBUG_ASSOC("Network '%s (%s)' excluded "
+ IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
"because of no compatible rates.\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid));
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid);
return 0;
}
@@ -5823,9 +5819,9 @@ static int ipw_best_network(struct ipw_priv *priv,
ipw_copy_rates(&match->rates, &rates);
match->network = network;
- IPW_DEBUG_ASSOC("Network '%s (%s)' is a viable match.\n",
- escape_essid(network->ssid, network->ssid_len),
- print_mac(mac, network->bssid));
+ IPW_DEBUG_ASSOC("Network '%s (%pM)' is a viable match.\n",
+ print_ssid(ssid, network->ssid, network->ssid_len),
+ network->bssid);
return 1;
}
@@ -6067,7 +6063,7 @@ static void ipw_bg_adhoc_check(struct work_struct *work)
static void ipw_debug_config(struct ipw_priv *priv)
{
- DECLARE_MAC_BUF(mac);
+ DECLARE_SSID_BUF(ssid);
IPW_DEBUG_INFO("Scan completed, no valid APs matched "
"[CFG 0x%08X]\n", priv->config);
if (priv->config & CFG_STATIC_CHANNEL)
@@ -6076,12 +6072,11 @@ static void ipw_debug_config(struct ipw_priv *priv)
IPW_DEBUG_INFO("Channel unlocked.\n");
if (priv->config & CFG_STATIC_ESSID)
IPW_DEBUG_INFO("ESSID locked to '%s'\n",
- escape_essid(priv->essid, priv->essid_len));
+ print_ssid(ssid, priv->essid, priv->essid_len));
else
IPW_DEBUG_INFO("ESSID unlocked.\n");
if (priv->config & CFG_STATIC_BSSID)
- IPW_DEBUG_INFO("BSSID locked to %s\n",
- print_mac(mac, priv->bssid));
+ IPW_DEBUG_INFO("BSSID locked to %pM\n", priv->bssid);
else
IPW_DEBUG_INFO("BSSID unlocked.\n");
if (priv->capability & CAP_PRIVACY_ON)
@@ -6277,6 +6272,20 @@ static void ipw_add_scan_channels(struct ipw_priv *priv,
}
}
+static int ipw_passive_dwell_time(struct ipw_priv *priv)
+{
+ /* staying on passive channels longer than the DTIM interval during a
+ * scan, while associated, causes the firmware to cancel the scan
+ * without notification. Hence, don't stay on passive channels longer
+ * than the beacon interval.
+ */
+ if (priv->status & STATUS_ASSOCIATED
+ && priv->assoc_network->beacon_interval > 10)
+ return priv->assoc_network->beacon_interval - 10;
+ else
+ return 120;
+}
+
static int ipw_request_scan_helper(struct ipw_priv *priv, int type, int direct)
{
struct ipw_scan_request_ext scan;
@@ -6320,16 +6329,16 @@ static int ipw_request_scan_helper(struct ipw_priv *priv, int type, int direct)
scan.full_scan_index = cpu_to_le32(ieee80211_get_scans(priv->ieee));
if (type == IW_SCAN_TYPE_PASSIVE) {
- IPW_DEBUG_WX("use passive scanning\n");
- scan_type = IPW_SCAN_PASSIVE_FULL_DWELL_SCAN;
+ IPW_DEBUG_WX("use passive scanning\n");
+ scan_type = IPW_SCAN_PASSIVE_FULL_DWELL_SCAN;
scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] =
- cpu_to_le16(120);
+ cpu_to_le16(ipw_passive_dwell_time(priv));
ipw_add_scan_channels(priv, &scan, scan_type);
goto send_request;
}
/* Use active scan by default. */
- if (priv->config & CFG_SPEED_SCAN)
+ if (priv->config & CFG_SPEED_SCAN)
scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] =
cpu_to_le16(30);
else
@@ -6339,7 +6348,8 @@ static int ipw_request_scan_helper(struct ipw_priv *priv, int type, int direct)
scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] =
cpu_to_le16(20);
- scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = cpu_to_le16(120);
+ scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] =
+ cpu_to_le16(ipw_passive_dwell_time(priv));
scan.dwell_time[IPW_SCAN_ACTIVE_DIRECT_SCAN] = cpu_to_le16(20);
#ifdef CONFIG_IPW2200_MONITOR
@@ -6607,7 +6617,7 @@ static int ipw_wx_set_auth(struct net_device *dev,
struct ipw_priv *priv = ieee80211_priv(dev);
struct ieee80211_device *ieee = priv->ieee;
struct iw_param *param = &wrqu->param;
- struct ieee80211_crypt_data *crypt;
+ struct lib80211_crypt_data *crypt;
unsigned long flags;
int ret = 0;
@@ -6629,7 +6639,7 @@ static int ipw_wx_set_auth(struct net_device *dev,
break;
case IW_AUTH_TKIP_COUNTERMEASURES:
- crypt = priv->ieee->crypt[priv->ieee->tx_keyidx];
+ crypt = priv->ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx];
if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags)
break;
@@ -6706,7 +6716,7 @@ static int ipw_wx_get_auth(struct net_device *dev,
{
struct ipw_priv *priv = ieee80211_priv(dev);
struct ieee80211_device *ieee = priv->ieee;
- struct ieee80211_crypt_data *crypt;
+ struct lib80211_crypt_data *crypt;
struct iw_param *param = &wrqu->param;
int ret = 0;
@@ -6722,7 +6732,7 @@ static int ipw_wx_get_auth(struct net_device *dev,
break;
case IW_AUTH_TKIP_COUNTERMEASURES:
- crypt = priv->ieee->crypt[priv->ieee->tx_keyidx];
+ crypt = priv->ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx];
if (!crypt || !crypt->ops->get_flags)
break;
@@ -6893,8 +6903,7 @@ static int ipw_qos_handle_probe_response(struct ipw_priv *priv,
if ((priv->status & STATUS_ASSOCIATED) &&
(priv->ieee->iw_mode == IW_MODE_ADHOC) && (active_network == 0)) {
if (memcmp(network->bssid, priv->bssid, ETH_ALEN))
- if ((network->capability & WLAN_CAPABILITY_IBSS) &&
- !(network->flags & NETWORK_EMPTY_ESSID))
+ if (network->capability & WLAN_CAPABILITY_IBSS)
if ((network->ssid_len ==
priv->assoc_network->ssid_len) &&
!memcmp(network->ssid,
@@ -7296,7 +7305,7 @@ static int ipw_associate_network(struct ipw_priv *priv,
struct ipw_supported_rates *rates, int roaming)
{
int err;
- DECLARE_MAC_BUF(mac);
+ DECLARE_SSID_BUF(ssid);
if (priv->config & CFG_FIXED_RATE)
ipw_set_fixed_rate(priv, network->mode);
@@ -7365,7 +7374,7 @@ static int ipw_associate_network(struct ipw_priv *priv,
IPW_DEBUG_ASSOC("%sssocation attempt: '%s', channel %d, "
"802.11%c [%d], %s[:%s], enc=%s%s%s%c%c\n",
roaming ? "Rea" : "A",
- escape_essid(priv->essid, priv->essid_len),
+ print_ssid(ssid, priv->essid, priv->essid_len),
network->channel,
ipw_modes[priv->assoc_request.ieee_mode],
rates->num_rates,
@@ -7464,9 +7473,9 @@ static int ipw_associate_network(struct ipw_priv *priv,
return err;
}
- IPW_DEBUG(IPW_DL_STATE, "associating: '%s' %s \n",
- escape_essid(priv->essid, priv->essid_len),
- print_mac(mac, priv->bssid));
+ IPW_DEBUG(IPW_DL_STATE, "associating: '%s' %pM \n",
+ print_ssid(ssid, priv->essid, priv->essid_len),
+ priv->bssid);
return 0;
}
@@ -7556,6 +7565,7 @@ static int ipw_associate(void *data)
struct ipw_supported_rates *rates;
struct list_head *element;
unsigned long flags;
+ DECLARE_SSID_BUF(ssid);
if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
IPW_DEBUG_ASSOC("Not attempting association (monitor mode)\n");
@@ -7582,8 +7592,7 @@ static int ipw_associate(void *data)
}
if (!(priv->config & CFG_ASSOCIATE) &&
- !(priv->config & (CFG_STATIC_ESSID |
- CFG_STATIC_CHANNEL | CFG_STATIC_BSSID))) {
+ !(priv->config & (CFG_STATIC_ESSID | CFG_STATIC_BSSID))) {
IPW_DEBUG_ASSOC("Not attempting association (associate=0)\n");
return 0;
}
@@ -7605,7 +7614,6 @@ static int ipw_associate(void *data)
if (list_empty(&priv->ieee->network_free_list)) {
struct ieee80211_network *oldest = NULL;
struct ieee80211_network *target;
- DECLARE_MAC_BUF(mac);
list_for_each_entry(target, &priv->ieee->network_list, list) {
if ((oldest == NULL) ||
@@ -7616,11 +7624,11 @@ static int ipw_associate(void *data)
/* If there are no more slots, expire the oldest */
list_del(&oldest->list);
target = oldest;
- IPW_DEBUG_ASSOC("Expired '%s' (%s) from "
+ IPW_DEBUG_ASSOC("Expired '%s' (%pM) from "
"network list.\n",
- escape_essid(target->ssid,
- target->ssid_len),
- print_mac(mac, target->bssid));
+ print_ssid(ssid, target->ssid,
+ target->ssid_len),
+ target->bssid);
list_add_tail(&target->list,
&priv->ieee->network_free_list);
}
@@ -7673,12 +7681,12 @@ static void ipw_rebuild_decrypted_skb(struct ipw_priv *priv,
u16 fc;
hdr = (struct ieee80211_hdr *)skb->data;
- fc = le16_to_cpu(hdr->frame_ctl);
+ fc = le16_to_cpu(hdr->frame_control);
if (!(fc & IEEE80211_FCTL_PROTECTED))
return;
fc &= ~IEEE80211_FCTL_PROTECTED;
- hdr->frame_ctl = cpu_to_le16(fc);
+ hdr->frame_control = cpu_to_le16(fc);
switch (priv->ieee->sec.level) {
case SEC_LEVEL_3:
/* Remove CCMP HDR */
@@ -7806,15 +7814,6 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv,
memmove(rxb->skb->data + sizeof(struct ipw_rt_hdr),
rxb->skb->data + IPW_RX_FRAME_SIZE, len);
- /* Zero the radiotap static buffer ... We only need to zero the bytes NOT
- * part of our real header, saves a little time.
- *
- * No longer necessary since we fill in all our data. Purge before merging
- * patch officially.
- * memset(rxb->skb->data + sizeof(struct ipw_rt_hdr), 0,
- * IEEE80211_RADIOTAP_HDRLEN - sizeof(struct ipw_rt_hdr));
- */
-
ipw_rt = (struct ipw_rt_hdr *)rxb->skb->data;
ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
@@ -7990,17 +7989,17 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv,
}
hdr = (void *)rxb->skb->data + IPW_RX_FRAME_SIZE;
- if (ieee80211_is_management(le16_to_cpu(hdr->frame_ctl))) {
+ if (ieee80211_is_management(le16_to_cpu(hdr->frame_control))) {
if (filter & IPW_PROM_NO_MGMT)
return;
if (filter & IPW_PROM_MGMT_HEADER_ONLY)
hdr_only = 1;
- } else if (ieee80211_is_control(le16_to_cpu(hdr->frame_ctl))) {
+ } else if (ieee80211_is_control(le16_to_cpu(hdr->frame_control))) {
if (filter & IPW_PROM_NO_CTL)
return;
if (filter & IPW_PROM_CTL_HEADER_ONLY)
hdr_only = 1;
- } else if (ieee80211_is_data(le16_to_cpu(hdr->frame_ctl))) {
+ } else if (ieee80211_is_data(le16_to_cpu(hdr->frame_control))) {
if (filter & IPW_PROM_NO_DATA)
return;
if (filter & IPW_PROM_DATA_HEADER_ONLY)
@@ -8018,19 +8017,10 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv,
ipw_rt = (void *)skb->data;
if (hdr_only)
- len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
+ len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
memcpy(ipw_rt->payload, hdr, len);
- /* Zero the radiotap static buffer ... We only need to zero the bytes
- * NOT part of our real header, saves a little time.
- *
- * No longer necessary since we fill in all our data. Purge before
- * merging patch officially.
- * memset(rxb->skb->data + sizeof(struct ipw_rt_hdr), 0,
- * IEEE80211_RADIOTAP_HDRLEN - sizeof(struct ipw_rt_hdr));
- */
-
ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION;
ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */
ipw_rt->rt_hdr.it_len = cpu_to_le16(sizeof(*ipw_rt)); /* total header+data */
@@ -8238,7 +8228,7 @@ static int is_duplicate_packet(struct ipw_priv *priv,
/* Comment this line now since we observed the card receives
* duplicate packets but the FCTL_RETRY bit is not set in the
* IBSS mode with fragmentation enabled.
- BUG_ON(!(le16_to_cpu(header->frame_ctl) & IEEE80211_FCTL_RETRY)); */
+ BUG_ON(!(le16_to_cpu(header->frame_control) & IEEE80211_FCTL_RETRY)); */
return 1;
}
@@ -8302,9 +8292,6 @@ static void ipw_rx(struct ipw_priv *priv)
u32 r, w, i;
u8 network_packet;
u8 fill_rx = 0;
- DECLARE_MAC_BUF(mac);
- DECLARE_MAC_BUF(mac2);
- DECLARE_MAC_BUF(mac3);
r = ipw_read32(priv, IPW_RX_READ_INDEX);
w = ipw_read32(priv, IPW_RX_WRITE_INDEX);
@@ -8434,18 +8421,12 @@ static void ipw_rx(struct ipw_priv *priv)
header)))
{
IPW_DEBUG_DROP("Dropping: "
- "%s, "
- "%s, "
- "%s\n",
- print_mac(mac,
- header->
- addr1),
- print_mac(mac2,
- header->
- addr2),
- print_mac(mac3,
- header->
- addr3));
+ "%pM, "
+ "%pM, "
+ "%pM\n",
+ header->addr1,
+ header->addr2,
+ header->addr3);
break;
}
@@ -8984,7 +8965,6 @@ static int ipw_wx_set_wap(struct net_device *dev,
union iwreq_data *wrqu, char *extra)
{
struct ipw_priv *priv = ieee80211_priv(dev);
- DECLARE_MAC_BUF(mac);
static const unsigned char any[] = {
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
@@ -9015,8 +8995,8 @@ static int ipw_wx_set_wap(struct net_device *dev,
return 0;
}
- IPW_DEBUG_WX("Setting mandatory BSSID to %s\n",
- print_mac(mac, wrqu->ap_addr.sa_data));
+ IPW_DEBUG_WX("Setting mandatory BSSID to %pM\n",
+ wrqu->ap_addr.sa_data);
memcpy(priv->bssid, wrqu->ap_addr.sa_data, ETH_ALEN);
@@ -9034,7 +9014,6 @@ static int ipw_wx_get_wap(struct net_device *dev,
union iwreq_data *wrqu, char *extra)
{
struct ipw_priv *priv = ieee80211_priv(dev);
- DECLARE_MAC_BUF(mac);
/* If we are associated, trying to associate, or have a statically
* configured BSSID then return that; otherwise return ANY */
@@ -9046,8 +9025,8 @@ static int ipw_wx_get_wap(struct net_device *dev,
} else
memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN);
- IPW_DEBUG_WX("Getting WAP BSSID: %s\n",
- print_mac(mac, wrqu->ap_addr.sa_data));
+ IPW_DEBUG_WX("Getting WAP BSSID: %pM\n",
+ wrqu->ap_addr.sa_data);
mutex_unlock(&priv->mutex);
return 0;
}
@@ -9058,6 +9037,7 @@ static int ipw_wx_set_essid(struct net_device *dev,
{
struct ipw_priv *priv = ieee80211_priv(dev);
int length;
+ DECLARE_SSID_BUF(ssid);
mutex_lock(&priv->mutex);
@@ -9082,8 +9062,8 @@ static int ipw_wx_set_essid(struct net_device *dev,
return 0;
}
- IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n", escape_essid(extra, length),
- length);
+ IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n",
+ print_ssid(ssid, extra, length), length);
priv->essid_len = length;
memcpy(priv->essid, extra, priv->essid_len);
@@ -9102,6 +9082,7 @@ static int ipw_wx_get_essid(struct net_device *dev,
union iwreq_data *wrqu, char *extra)
{
struct ipw_priv *priv = ieee80211_priv(dev);
+ DECLARE_SSID_BUF(ssid);
/* If we are associated, trying to associate, or have a statically
* configured ESSID then return that; otherwise return ANY */
@@ -9109,7 +9090,7 @@ static int ipw_wx_get_essid(struct net_device *dev,
if (priv->config & CFG_STATIC_ESSID ||
priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) {
IPW_DEBUG_WX("Getting essid: '%s'\n",
- escape_essid(priv->essid, priv->essid_len));
+ print_ssid(ssid, priv->essid, priv->essid_len));
memcpy(extra, priv->essid, priv->essid_len);
wrqu->essid.length = priv->essid_len;
wrqu->essid.flags = 1; /* active */
@@ -10203,10 +10184,8 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
id = ipw_add_station(priv, hdr->addr1);
if (id == IPW_INVALID_STATION) {
IPW_WARNING("Attempt to send data to "
- "invalid cell: " MAC_FMT "\n",
- hdr->addr1[0], hdr->addr1[1],
- hdr->addr1[2], hdr->addr1[3],
- hdr->addr1[4], hdr->addr1[5]);
+ "invalid cell: %pM\n",
+ hdr->addr1);
goto drop;
}
}
@@ -10274,8 +10253,8 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb,
case SEC_LEVEL_1:
tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |=
cpu_to_le16(IEEE80211_FCTL_PROTECTED);
- tfd->u.data.key_index = priv->ieee->tx_keyidx;
- if (priv->ieee->sec.key_sizes[priv->ieee->tx_keyidx] <=
+ tfd->u.data.key_index = priv->ieee->crypt_info.tx_keyidx;
+ if (priv->ieee->sec.key_sizes[priv->ieee->crypt_info.tx_keyidx] <=
40)
tfd->u.data.key_index |= DCT_WEP_KEY_64Bit;
else
@@ -10403,17 +10382,17 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv,
/* Filtering of fragment chains is done agains the first fragment */
hdr = (void *)txb->fragments[0]->data;
- if (ieee80211_is_management(le16_to_cpu(hdr->frame_ctl))) {
+ if (ieee80211_is_management(le16_to_cpu(hdr->frame_control))) {
if (filter & IPW_PROM_NO_MGMT)
return;
if (filter & IPW_PROM_MGMT_HEADER_ONLY)
hdr_only = 1;
- } else if (ieee80211_is_control(le16_to_cpu(hdr->frame_ctl))) {
+ } else if (ieee80211_is_control(le16_to_cpu(hdr->frame_control))) {
if (filter & IPW_PROM_NO_CTL)
return;
if (filter & IPW_PROM_CTL_HEADER_ONLY)
hdr_only = 1;
- } else if (ieee80211_is_data(le16_to_cpu(hdr->frame_ctl))) {
+ } else if (ieee80211_is_data(le16_to_cpu(hdr->frame_control))) {
if (filter & IPW_PROM_NO_DATA)
return;
if (filter & IPW_PROM_DATA_HEADER_ONLY)
@@ -10428,13 +10407,13 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv,
if (hdr_only) {
hdr = (void *)src->data;
- len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
+ len = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_control));
} else
len = src->len;
- dst = alloc_skb(
- len + IEEE80211_RADIOTAP_HDRLEN, GFP_ATOMIC);
- if (!dst) continue;
+ dst = alloc_skb(len + sizeof(*rt_hdr), GFP_ATOMIC);
+ if (!dst)
+ continue;
rt_hdr = (void *)skb_put(dst, sizeof(*rt_hdr));
@@ -10509,15 +10488,14 @@ static int ipw_net_set_mac_address(struct net_device *dev, void *p)
{
struct ipw_priv *priv = ieee80211_priv(dev);
struct sockaddr *addr = p;
- DECLARE_MAC_BUF(mac);
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
mutex_lock(&priv->mutex);
priv->config |= CFG_CUSTOM_MAC;
memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN);
- printk(KERN_INFO "%s: Setting MAC to %s\n",
- priv->net_dev->name, print_mac(mac, priv->mac_addr));
+ printk(KERN_INFO "%s: Setting MAC to %pM\n",
+ priv->net_dev->name, priv->mac_addr);
queue_work(priv->workqueue, &priv->adapter_restart);
mutex_unlock(&priv->mutex);
return 0;
@@ -11652,7 +11630,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
length = pci_resource_len(pdev, 0);
priv->hw_len = length;
- base = ioremap_nocache(pci_resource_start(pdev, 0), length);
+ base = pci_ioremap_bar(pdev, 0);
if (!base) {
err = -ENODEV;
goto out_pci_release_regions;
@@ -11944,7 +11922,7 @@ module_param(disable, int, 0444);
MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
module_param(associate, int, 0444);
-MODULE_PARM_DESC(associate, "auto associate when scanning (default on)");
+MODULE_PARM_DESC(associate, "auto associate when scanning (default off)");
module_param(auto_create, int, 0444);
MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)");
diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2x00/ipw2200.h
index 0bad1ec3e7e0..277b274d4be5 100644
--- a/drivers/net/wireless/ipw2200.h
+++ b/drivers/net/wireless/ipw2x00/ipw2200.h
@@ -48,6 +48,7 @@
#include <linux/jiffies.h>
#include <asm/io.h>
+#include <net/lib80211.h>
#include <net/ieee80211.h>
#include <net/ieee80211_radiotap.h>
@@ -244,6 +245,7 @@ enum connection_manager_assoc_states {
#define HOST_NOTIFICATION_S36_MEASUREMENT_REFUSED 31
#define HOST_NOTIFICATION_STATUS_BEACON_MISSING 1
+#define IPW_MB_SCAN_CANCEL_THRESHOLD 3
#define IPW_MB_ROAMING_THRESHOLD_MIN 1
#define IPW_MB_ROAMING_THRESHOLD_DEFAULT 8
#define IPW_MB_ROAMING_THRESHOLD_MAX 30
diff --git a/drivers/net/wireless/ipw2x00/libipw_geo.c b/drivers/net/wireless/ipw2x00/libipw_geo.c
new file mode 100644
index 000000000000..960ad13f5e9f
--- /dev/null
+++ b/drivers/net/wireless/ipw2x00/libipw_geo.c
@@ -0,0 +1,195 @@
+/******************************************************************************
+
+ Copyright(c) 2005 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ 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., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************/
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/in6.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/wireless.h>
+#include <linux/etherdevice.h>
+#include <asm/uaccess.h>
+
+#include <net/ieee80211.h>
+
+int ieee80211_is_valid_channel(struct ieee80211_device *ieee, u8 channel)
+{
+ int i;
+
+ /* Driver needs to initialize the geography map before using
+ * these helper functions */
+ if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
+ return 0;
+
+ if (ieee->freq_band & IEEE80211_24GHZ_BAND)
+ for (i = 0; i < ieee->geo.bg_channels; i++)
+ /* NOTE: If G mode is currently supported but
+ * this is a B only channel, we don't see it
+ * as valid. */
+ if ((ieee->geo.bg[i].channel == channel) &&
+ !(ieee->geo.bg[i].flags & IEEE80211_CH_INVALID) &&
+ (!(ieee->mode & IEEE_G) ||
+ !(ieee->geo.bg[i].flags & IEEE80211_CH_B_ONLY)))
+ return IEEE80211_24GHZ_BAND;
+
+ if (ieee->freq_band & IEEE80211_52GHZ_BAND)
+ for (i = 0; i < ieee->geo.a_channels; i++)
+ if ((ieee->geo.a[i].channel == channel) &&
+ !(ieee->geo.a[i].flags & IEEE80211_CH_INVALID))
+ return IEEE80211_52GHZ_BAND;
+
+ return 0;
+}
+
+int ieee80211_channel_to_index(struct ieee80211_device *ieee, u8 channel)
+{
+ int i;
+
+ /* Driver needs to initialize the geography map before using
+ * these helper functions */
+ if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
+ return -1;
+
+ if (ieee->freq_band & IEEE80211_24GHZ_BAND)
+ for (i = 0; i < ieee->geo.bg_channels; i++)
+ if (ieee->geo.bg[i].channel == channel)
+ return i;
+
+ if (ieee->freq_band & IEEE80211_52GHZ_BAND)
+ for (i = 0; i < ieee->geo.a_channels; i++)
+ if (ieee->geo.a[i].channel == channel)
+ return i;
+
+ return -1;
+}
+
+u32 ieee80211_channel_to_freq(struct ieee80211_device * ieee, u8 channel)
+{
+ const struct ieee80211_channel * ch;
+
+ /* Driver needs to initialize the geography map before using
+ * these helper functions */
+ if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
+ return 0;
+
+ ch = ieee80211_get_channel(ieee, channel);
+ if (!ch->channel)
+ return 0;
+ return ch->freq;
+}
+
+u8 ieee80211_freq_to_channel(struct ieee80211_device * ieee, u32 freq)
+{
+ int i;
+
+ /* Driver needs to initialize the geography map before using
+ * these helper functions */
+ if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0)
+ return 0;
+
+ freq /= 100000;
+
+ if (ieee->freq_band & IEEE80211_24GHZ_BAND)
+ for (i = 0; i < ieee->geo.bg_channels; i++)
+ if (ieee->geo.bg[i].freq == freq)
+ return ieee->geo.bg[i].channel;
+
+ if (ieee->freq_band & IEEE80211_52GHZ_BAND)
+ for (i = 0; i < ieee->geo.a_channels; i++)
+ if (ieee->geo.a[i].freq == freq)
+ return ieee->geo.a[i].channel;
+
+ return 0;
+}
+
+int ieee80211_set_geo(struct ieee80211_device *ieee,
+ const struct ieee80211_geo *geo)
+{
+ memcpy(ieee->geo.name, geo->name, 3);
+ ieee->geo.name[3] = '\0';
+ ieee->geo.bg_channels = geo->bg_channels;
+ ieee->geo.a_channels = geo->a_channels;
+ memcpy(ieee->geo.bg, geo->bg, geo->bg_channels *
+ sizeof(struct ieee80211_channel));
+ memcpy(ieee->geo.a, geo->a, ieee->geo.a_channels *
+ sizeof(struct ieee80211_channel));
+ return 0;
+}
+
+const struct ieee80211_geo *ieee80211_get_geo(struct ieee80211_device *ieee)
+{
+ return &ieee->geo;
+}
+
+u8 ieee80211_get_channel_flags(struct ieee80211_device * ieee, u8 channel)
+{
+ int index = ieee80211_channel_to_index(ieee, channel);
+
+ if (index == -1)
+ return IEEE80211_CH_INVALID;
+
+ if (channel <= IEEE80211_24GHZ_CHANNELS)
+ return ieee->geo.bg[index].flags;
+
+ return ieee->geo.a[index].flags;
+}
+
+static const struct ieee80211_channel bad_channel = {
+ .channel = 0,
+ .flags = IEEE80211_CH_INVALID,
+ .max_power = 0,
+};
+
+const struct ieee80211_channel *ieee80211_get_channel(struct ieee80211_device
+ *ieee, u8 channel)
+{
+ int index = ieee80211_channel_to_index(ieee, channel);
+
+ if (index == -1)
+ return &bad_channel;
+
+ if (channel <= IEEE80211_24GHZ_CHANNELS)
+ return &ieee->geo.bg[index];
+
+ return &ieee->geo.a[index];
+}
+
+EXPORT_SYMBOL(ieee80211_get_channel);
+EXPORT_SYMBOL(ieee80211_get_channel_flags);
+EXPORT_SYMBOL(ieee80211_is_valid_channel);
+EXPORT_SYMBOL(ieee80211_freq_to_channel);
+EXPORT_SYMBOL(ieee80211_channel_to_freq);
+EXPORT_SYMBOL(ieee80211_channel_to_index);
+EXPORT_SYMBOL(ieee80211_set_geo);
+EXPORT_SYMBOL(ieee80211_get_geo);
diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c
new file mode 100644
index 000000000000..a2f5616d5b09
--- /dev/null
+++ b/drivers/net/wireless/ipw2x00/libipw_module.c
@@ -0,0 +1,293 @@
+/*******************************************************************************
+
+ Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
+
+ Portions of this file are based on the WEP enablement code provided by the
+ Host AP project hostap-drivers v0.1.3
+ Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ <j@w1.fi>
+ Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ 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., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+*******************************************************************************/
+
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/in6.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/wireless.h>
+#include <linux/etherdevice.h>
+#include <asm/uaccess.h>
+#include <net/net_namespace.h>
+#include <net/arp.h>
+
+#include <net/ieee80211.h>
+
+#define DRV_DESCRIPTION "802.11 data/management/control stack"
+#define DRV_NAME "ieee80211"
+#define DRV_VERSION IEEE80211_VERSION
+#define DRV_COPYRIGHT "Copyright (C) 2004-2005 Intel Corporation <jketreno@linux.intel.com>"
+
+MODULE_VERSION(DRV_VERSION);
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_AUTHOR(DRV_COPYRIGHT);
+MODULE_LICENSE("GPL");
+
+static int ieee80211_networks_allocate(struct ieee80211_device *ieee)
+{
+ if (ieee->networks)
+ return 0;
+
+ ieee->networks =
+ kzalloc(MAX_NETWORK_COUNT * sizeof(struct ieee80211_network),
+ GFP_KERNEL);
+ if (!ieee->networks) {
+ printk(KERN_WARNING "%s: Out of memory allocating beacons\n",
+ ieee->dev->name);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+void ieee80211_network_reset(struct ieee80211_network *network)
+{
+ if (!network)
+ return;
+
+ if (network->ibss_dfs) {
+ kfree(network->ibss_dfs);
+ network->ibss_dfs = NULL;
+ }
+}
+
+static inline void ieee80211_networks_free(struct ieee80211_device *ieee)
+{
+ int i;
+
+ if (!ieee->networks)
+ return;
+
+ for (i = 0; i < MAX_NETWORK_COUNT; i++)
+ if (ieee->networks[i].ibss_dfs)
+ kfree(ieee->networks[i].ibss_dfs);
+
+ kfree(ieee->networks);
+ ieee->networks = NULL;
+}
+
+static void ieee80211_networks_initialize(struct ieee80211_device *ieee)
+{
+ int i;
+
+ INIT_LIST_HEAD(&ieee->network_free_list);
+ INIT_LIST_HEAD(&ieee->network_list);
+ for (i = 0; i < MAX_NETWORK_COUNT; i++)
+ list_add_tail(&ieee->networks[i].list,
+ &ieee->network_free_list);
+}
+
+static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
+{
+ if ((new_mtu < 68) || (new_mtu > IEEE80211_DATA_LEN))
+ return -EINVAL;
+ dev->mtu = new_mtu;
+ return 0;
+}
+
+static struct net_device_stats *ieee80211_generic_get_stats(
+ struct net_device *dev)
+{
+ struct ieee80211_device *ieee = netdev_priv(dev);
+ return &ieee->stats;
+}
+
+struct net_device *alloc_ieee80211(int sizeof_priv)
+{
+ struct ieee80211_device *ieee;
+ struct net_device *dev;
+ int err;
+
+ IEEE80211_DEBUG_INFO("Initializing...\n");
+
+ dev = alloc_etherdev(sizeof(struct ieee80211_device) + sizeof_priv);
+ if (!dev) {
+ IEEE80211_ERROR("Unable to allocate network device.\n");
+ goto failed;
+ }
+ ieee = netdev_priv(dev);
+ dev->hard_start_xmit = ieee80211_xmit;
+ dev->change_mtu = ieee80211_change_mtu;
+
+ /* Drivers are free to override this if the generic implementation
+ * does not meet their needs. */
+ dev->get_stats = ieee80211_generic_get_stats;
+
+ ieee->dev = dev;
+
+ err = ieee80211_networks_allocate(ieee);
+ if (err) {
+ IEEE80211_ERROR("Unable to allocate beacon storage: %d\n", err);
+ goto failed_free_netdev;
+ }
+ ieee80211_networks_initialize(ieee);
+
+ /* Default fragmentation threshold is maximum payload size */
+ ieee->fts = DEFAULT_FTS;
+ ieee->rts = DEFAULT_FTS;
+ ieee->scan_age = DEFAULT_MAX_SCAN_AGE;
+ ieee->open_wep = 1;
+
+ /* Default to enabling full open WEP with host based encrypt/decrypt */
+ ieee->host_encrypt = 1;
+ ieee->host_decrypt = 1;
+ ieee->host_mc_decrypt = 1;
+
+ /* Host fragementation in Open mode. Default is enabled.
+ * Note: host fragmentation is always enabled if host encryption
+ * is enabled. For cards can do hardware encryption, they must do
+ * hardware fragmentation as well. So we don't need a variable
+ * like host_enc_frag. */
+ ieee->host_open_frag = 1;
+ ieee->ieee802_1x = 1; /* Default to supporting 802.1x */
+
+ spin_lock_init(&ieee->lock);
+
+ lib80211_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock);
+
+ ieee->wpa_enabled = 0;
+ ieee->drop_unencrypted = 0;
+ ieee->privacy_invoked = 0;
+
+ return dev;
+
+failed_free_netdev:
+ free_netdev(dev);
+failed:
+ return NULL;
+}
+
+void free_ieee80211(struct net_device *dev)
+{
+ struct ieee80211_device *ieee = netdev_priv(dev);
+
+ lib80211_crypt_info_free(&ieee->crypt_info);
+
+ ieee80211_networks_free(ieee);
+ free_netdev(dev);
+}
+
+#ifdef CONFIG_IEEE80211_DEBUG
+
+static int debug = 0;
+u32 ieee80211_debug_level = 0;
+EXPORT_SYMBOL_GPL(ieee80211_debug_level);
+static struct proc_dir_entry *ieee80211_proc = NULL;
+
+static int show_debug_level(char *page, char **start, off_t offset,
+ int count, int *eof, void *data)
+{
+ return snprintf(page, count, "0x%08X\n", ieee80211_debug_level);
+}
+
+static int store_debug_level(struct file *file, const char __user * buffer,
+ unsigned long count, void *data)
+{
+ char buf[] = "0x00000000\n";
+ unsigned long len = min((unsigned long)sizeof(buf) - 1, count);
+ unsigned long val;
+
+ if (copy_from_user(buf, buffer, len))
+ return count;
+ buf[len] = 0;
+ if (sscanf(buf, "%li", &val) != 1)
+ printk(KERN_INFO DRV_NAME
+ ": %s is not in hex or decimal form.\n", buf);
+ else
+ ieee80211_debug_level = val;
+
+ return strnlen(buf, len);
+}
+#endif /* CONFIG_IEEE80211_DEBUG */
+
+static int __init ieee80211_init(void)
+{
+#ifdef CONFIG_IEEE80211_DEBUG
+ struct proc_dir_entry *e;
+
+ ieee80211_debug_level = debug;
+ ieee80211_proc = proc_mkdir(DRV_NAME, init_net.proc_net);
+ if (ieee80211_proc == NULL) {
+ IEEE80211_ERROR("Unable to create " DRV_NAME
+ " proc directory\n");
+ return -EIO;
+ }
+ e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR,
+ ieee80211_proc);
+ if (!e) {
+ remove_proc_entry(DRV_NAME, init_net.proc_net);
+ ieee80211_proc = NULL;
+ return -EIO;
+ }
+ e->read_proc = show_debug_level;
+ e->write_proc = store_debug_level;
+ e->data = NULL;
+#endif /* CONFIG_IEEE80211_DEBUG */
+
+ printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
+ printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n");
+
+ return 0;
+}
+
+static void __exit ieee80211_exit(void)
+{
+#ifdef CONFIG_IEEE80211_DEBUG
+ if (ieee80211_proc) {
+ remove_proc_entry("debug_level", ieee80211_proc);
+ remove_proc_entry(DRV_NAME, init_net.proc_net);
+ ieee80211_proc = NULL;
+ }
+#endif /* CONFIG_IEEE80211_DEBUG */
+}
+
+#ifdef CONFIG_IEEE80211_DEBUG
+#include <linux/moduleparam.h>
+module_param(debug, int, 0444);
+MODULE_PARM_DESC(debug, "debug output mask");
+#endif /* CONFIG_IEEE80211_DEBUG */
+
+module_exit(ieee80211_exit);
+module_init(ieee80211_init);
+
+EXPORT_SYMBOL(alloc_ieee80211);
+EXPORT_SYMBOL(free_ieee80211);
diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c
new file mode 100644
index 000000000000..9c67dfae4320
--- /dev/null
+++ b/drivers/net/wireless/ipw2x00/libipw_rx.c
@@ -0,0 +1,1799 @@
+/*
+ * Original code based Host AP (software wireless LAN access point) driver
+ * for Intersil Prism2/2.5/3 - hostap.o module, common routines
+ *
+ * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ * <j@w1.fi>
+ * Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2005, Intel Corporation
+ *
+ * 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. See README and COPYING for
+ * more details.
+ */
+
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/in6.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/wireless.h>
+#include <linux/etherdevice.h>
+#include <asm/uaccess.h>
+#include <linux/ctype.h>
+
+#include <net/lib80211.h>
+#include <net/ieee80211.h>
+
+static void ieee80211_monitor_rx(struct ieee80211_device *ieee,
+ struct sk_buff *skb,
+ struct ieee80211_rx_stats *rx_stats)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ u16 fc = le16_to_cpu(hdr->frame_control);
+
+ skb->dev = ieee->dev;
+ skb_reset_mac_header(skb);
+ skb_pull(skb, ieee80211_get_hdrlen(fc));
+ skb->pkt_type = PACKET_OTHERHOST;
+ skb->protocol = htons(ETH_P_80211_RAW);
+ memset(skb->cb, 0, sizeof(skb->cb));
+ netif_rx(skb);
+}
+
+/* Called only as a tasklet (software IRQ) */
+static struct ieee80211_frag_entry *ieee80211_frag_cache_find(struct
+ ieee80211_device
+ *ieee,
+ unsigned int seq,
+ unsigned int frag,
+ u8 * src,
+ u8 * dst)
+{
+ struct ieee80211_frag_entry *entry;
+ int i;
+
+ for (i = 0; i < IEEE80211_FRAG_CACHE_LEN; i++) {
+ entry = &ieee->frag_cache[i];
+ if (entry->skb != NULL &&
+ time_after(jiffies, entry->first_frag_time + 2 * HZ)) {
+ IEEE80211_DEBUG_FRAG("expiring fragment cache entry "
+ "seq=%u last_frag=%u\n",
+ entry->seq, entry->last_frag);
+ dev_kfree_skb_any(entry->skb);
+ entry->skb = NULL;
+ }
+
+ if (entry->skb != NULL && entry->seq == seq &&
+ (entry->last_frag + 1 == frag || frag == -1) &&
+ !compare_ether_addr(entry->src_addr, src) &&
+ !compare_ether_addr(entry->dst_addr, dst))
+ return entry;
+ }
+
+ return NULL;
+}
+
+/* Called only as a tasklet (software IRQ) */
+static struct sk_buff *ieee80211_frag_cache_get(struct ieee80211_device *ieee,
+ struct ieee80211_hdr_4addr *hdr)
+{
+ struct sk_buff *skb = NULL;
+ u16 sc;
+ unsigned int frag, seq;
+ struct ieee80211_frag_entry *entry;
+
+ sc = le16_to_cpu(hdr->seq_ctl);
+ frag = WLAN_GET_SEQ_FRAG(sc);
+ seq = WLAN_GET_SEQ_SEQ(sc);
+
+ if (frag == 0) {
+ /* Reserve enough space to fit maximum frame length */
+ skb = dev_alloc_skb(ieee->dev->mtu +
+ sizeof(struct ieee80211_hdr_4addr) +
+ 8 /* LLC */ +
+ 2 /* alignment */ +
+ 8 /* WEP */ + ETH_ALEN /* WDS */ );
+ if (skb == NULL)
+ return NULL;
+
+ entry = &ieee->frag_cache[ieee->frag_next_idx];
+ ieee->frag_next_idx++;
+ if (ieee->frag_next_idx >= IEEE80211_FRAG_CACHE_LEN)
+ ieee->frag_next_idx = 0;
+
+ if (entry->skb != NULL)
+ dev_kfree_skb_any(entry->skb);
+
+ entry->first_frag_time = jiffies;
+ entry->seq = seq;
+ entry->last_frag = frag;
+ entry->skb = skb;
+ memcpy(entry->src_addr, hdr->addr2, ETH_ALEN);
+ memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN);
+ } else {
+ /* received a fragment of a frame for which the head fragment
+ * should have already been received */
+ entry = ieee80211_frag_cache_find(ieee, seq, frag, hdr->addr2,
+ hdr->addr1);
+ if (entry != NULL) {
+ entry->last_frag = frag;
+ skb = entry->skb;
+ }
+ }
+
+ return skb;
+}
+
+/* Called only as a tasklet (software IRQ) */
+static int ieee80211_frag_cache_invalidate(struct ieee80211_device *ieee,
+ struct ieee80211_hdr_4addr *hdr)
+{
+ u16 sc;
+ unsigned int seq;
+ struct ieee80211_frag_entry *entry;
+
+ sc = le16_to_cpu(hdr->seq_ctl);
+ seq = WLAN_GET_SEQ_SEQ(sc);
+
+ entry = ieee80211_frag_cache_find(ieee, seq, -1, hdr->addr2,
+ hdr->addr1);
+
+ if (entry == NULL) {
+ IEEE80211_DEBUG_FRAG("could not invalidate fragment cache "
+ "entry (seq=%u)\n", seq);
+ return -1;
+ }
+
+ entry->skb = NULL;
+ return 0;
+}
+
+#ifdef NOT_YET
+/* ieee80211_rx_frame_mgtmt
+ *
+ * Responsible for handling management control frames
+ *
+ * Called by ieee80211_rx */
+static int
+ieee80211_rx_frame_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb,
+ struct ieee80211_rx_stats *rx_stats, u16 type,
+ u16 stype)
+{
+ if (ieee->iw_mode == IW_MODE_MASTER) {
+ printk(KERN_DEBUG "%s: Master mode not yet suppported.\n",
+ ieee->dev->name);
+ return 0;
+/*
+ hostap_update_sta_ps(ieee, (struct hostap_ieee80211_hdr_4addr *)
+ skb->data);*/
+ }
+
+ if (ieee->hostapd && type == WLAN_FC_TYPE_MGMT) {
+ if (stype == WLAN_FC_STYPE_BEACON &&
+ ieee->iw_mode == IW_MODE_MASTER) {
+ struct sk_buff *skb2;
+ /* Process beacon frames also in kernel driver to
+ * update STA(AP) table statistics */
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (skb2)
+ hostap_rx(skb2->dev, skb2, rx_stats);
+ }
+
+ /* send management frames to the user space daemon for
+ * processing */
+ ieee->apdevstats.rx_packets++;
+ ieee->apdevstats.rx_bytes += skb->len;
+ prism2_rx_80211(ieee->apdev, skb, rx_stats, PRISM2_RX_MGMT);
+ return 0;
+ }
+
+ if (ieee->iw_mode == IW_MODE_MASTER) {
+ if (type != WLAN_FC_TYPE_MGMT && type != WLAN_FC_TYPE_CTRL) {
+ printk(KERN_DEBUG "%s: unknown management frame "
+ "(type=0x%02x, stype=0x%02x) dropped\n",
+ skb->dev->name, type, stype);
+ return -1;
+ }
+
+ hostap_rx(skb->dev, skb, rx_stats);
+ return 0;
+ }
+
+ printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: management frame "
+ "received in non-Host AP mode\n", skb->dev->name);
+ return -1;
+}
+#endif
+
+/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
+/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
+static unsigned char rfc1042_header[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+
+/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
+static unsigned char bridge_tunnel_header[] =
+ { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
+/* No encapsulation header if EtherType < 0x600 (=length) */
+
+/* Called by ieee80211_rx_frame_decrypt */
+static int ieee80211_is_eapol_frame(struct ieee80211_device *ieee,
+ struct sk_buff *skb)
+{
+ struct net_device *dev = ieee->dev;
+ u16 fc, ethertype;
+ struct ieee80211_hdr_3addr *hdr;
+ u8 *pos;
+
+ if (skb->len < 24)
+ return 0;
+
+ hdr = (struct ieee80211_hdr_3addr *)skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+
+ /* check that the frame is unicast frame to us */
+ if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+ IEEE80211_FCTL_TODS &&
+ !compare_ether_addr(hdr->addr1, dev->dev_addr) &&
+ !compare_ether_addr(hdr->addr3, dev->dev_addr)) {
+ /* ToDS frame with own addr BSSID and DA */
+ } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+ IEEE80211_FCTL_FROMDS &&
+ !compare_ether_addr(hdr->addr1, dev->dev_addr)) {
+ /* FromDS frame with own addr as DA */
+ } else
+ return 0;
+
+ if (skb->len < 24 + 8)
+ return 0;
+
+ /* check for port access entity Ethernet type */
+ pos = skb->data + 24;
+ ethertype = (pos[6] << 8) | pos[7];
+ if (ethertype == ETH_P_PAE)
+ return 1;
+
+ return 0;
+}
+
+/* Called only as a tasklet (software IRQ), by ieee80211_rx */
+static int
+ieee80211_rx_frame_decrypt(struct ieee80211_device *ieee, struct sk_buff *skb,
+ struct lib80211_crypt_data *crypt)
+{
+ struct ieee80211_hdr_3addr *hdr;
+ int res, hdrlen;
+
+ if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL)
+ return 0;
+
+ hdr = (struct ieee80211_hdr_3addr *)skb->data;
+ hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
+
+ atomic_inc(&crypt->refcnt);
+ res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv);
+ atomic_dec(&crypt->refcnt);
+ if (res < 0) {
+ IEEE80211_DEBUG_DROP("decryption failed (SA=%pM) res=%d\n",
+ hdr->addr2, res);
+ if (res == -2)
+ IEEE80211_DEBUG_DROP("Decryption failed ICV "
+ "mismatch (key %d)\n",
+ skb->data[hdrlen + 3] >> 6);
+ ieee->ieee_stats.rx_discards_undecryptable++;
+ return -1;
+ }
+
+ return res;
+}
+
+/* Called only as a tasklet (software IRQ), by ieee80211_rx */
+static int
+ieee80211_rx_frame_decrypt_msdu(struct ieee80211_device *ieee,
+ struct sk_buff *skb, int keyidx,
+ struct lib80211_crypt_data *crypt)
+{
+ struct ieee80211_hdr_3addr *hdr;
+ int res, hdrlen;
+
+ if (crypt == NULL || crypt->ops->decrypt_msdu == NULL)
+ return 0;
+
+ hdr = (struct ieee80211_hdr_3addr *)skb->data;
+ hdrlen = ieee80211_get_hdrlen(le16_to_cpu(hdr->frame_ctl));
+
+ atomic_inc(&crypt->refcnt);
+ res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv);
+ atomic_dec(&crypt->refcnt);
+ if (res < 0) {
+ printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed"
+ " (SA=%pM keyidx=%d)\n", ieee->dev->name, hdr->addr2,
+ keyidx);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* All received frames are sent to this function. @skb contains the frame in
+ * IEEE 802.11 format, i.e., in the format it was sent over air.
+ * This function is called only as a tasklet (software IRQ). */
+int ieee80211_rx(struct ieee80211_device *ieee, struct sk_buff *skb,
+ struct ieee80211_rx_stats *rx_stats)
+{
+ struct net_device *dev = ieee->dev;
+ struct ieee80211_hdr_4addr *hdr;
+ size_t hdrlen;
+ u16 fc, type, stype, sc;
+ struct net_device_stats *stats;
+ unsigned int frag;
+ u8 *payload;
+ u16 ethertype;
+#ifdef NOT_YET
+ struct net_device *wds = NULL;
+ struct sk_buff *skb2 = NULL;
+ struct net_device *wds = NULL;
+ int frame_authorized = 0;
+ int from_assoc_ap = 0;
+ void *sta = NULL;
+#endif
+ u8 dst[ETH_ALEN];
+ u8 src[ETH_ALEN];
+ struct lib80211_crypt_data *crypt = NULL;
+ int keyidx = 0;
+ int can_be_decrypted = 0;
+
+ hdr = (struct ieee80211_hdr_4addr *)skb->data;
+ stats = &ieee->stats;
+
+ if (skb->len < 10) {
+ printk(KERN_INFO "%s: SKB length < 10\n", dev->name);
+ goto rx_dropped;
+ }
+
+ fc = le16_to_cpu(hdr->frame_ctl);
+ type = WLAN_FC_GET_TYPE(fc);
+ stype = WLAN_FC_GET_STYPE(fc);
+ sc = le16_to_cpu(hdr->seq_ctl);
+ frag = WLAN_GET_SEQ_FRAG(sc);
+ hdrlen = ieee80211_get_hdrlen(fc);
+
+ if (skb->len < hdrlen) {
+ printk(KERN_INFO "%s: invalid SKB length %d\n",
+ dev->name, skb->len);
+ goto rx_dropped;
+ }
+
+ /* Put this code here so that we avoid duplicating it in all
+ * Rx paths. - Jean II */
+#ifdef CONFIG_WIRELESS_EXT
+#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */
+ /* If spy monitoring on */
+ if (ieee->spy_data.spy_number > 0) {
+ struct iw_quality wstats;
+
+ wstats.updated = 0;
+ if (rx_stats->mask & IEEE80211_STATMASK_RSSI) {
+ wstats.level = rx_stats->signal;
+ wstats.updated |= IW_QUAL_LEVEL_UPDATED;
+ } else
+ wstats.updated |= IW_QUAL_LEVEL_INVALID;
+
+ if (rx_stats->mask & IEEE80211_STATMASK_NOISE) {
+ wstats.noise = rx_stats->noise;
+ wstats.updated |= IW_QUAL_NOISE_UPDATED;
+ } else
+ wstats.updated |= IW_QUAL_NOISE_INVALID;
+
+ if (rx_stats->mask & IEEE80211_STATMASK_SIGNAL) {
+ wstats.qual = rx_stats->signal;
+ wstats.updated |= IW_QUAL_QUAL_UPDATED;
+ } else
+ wstats.updated |= IW_QUAL_QUAL_INVALID;
+
+ /* Update spy records */
+ wireless_spy_update(ieee->dev, hdr->addr2, &wstats);
+ }
+#endif /* IW_WIRELESS_SPY */
+#endif /* CONFIG_WIRELESS_EXT */
+
+#ifdef NOT_YET
+ hostap_update_rx_stats(local->ap, hdr, rx_stats);
+#endif
+
+ if (ieee->iw_mode == IW_MODE_MONITOR) {
+ stats->rx_packets++;
+ stats->rx_bytes += skb->len;
+ ieee80211_monitor_rx(ieee, skb, rx_stats);
+ return 1;
+ }
+
+ can_be_decrypted = (is_multicast_ether_addr(hdr->addr1) ||
+ is_broadcast_ether_addr(hdr->addr2)) ?
+ ieee->host_mc_decrypt : ieee->host_decrypt;
+
+ if (can_be_decrypted) {
+ if (skb->len >= hdrlen + 3) {
+ /* Top two-bits of byte 3 are the key index */
+ keyidx = skb->data[hdrlen + 3] >> 6;
+ }
+
+ /* ieee->crypt[] is WEP_KEY (4) in length. Given that keyidx
+ * is only allowed 2-bits of storage, no value of keyidx can
+ * be provided via above code that would result in keyidx
+ * being out of range */
+ crypt = ieee->crypt_info.crypt[keyidx];
+
+#ifdef NOT_YET
+ sta = NULL;
+
+ /* Use station specific key to override default keys if the
+ * receiver address is a unicast address ("individual RA"). If
+ * bcrx_sta_key parameter is set, station specific key is used
+ * even with broad/multicast targets (this is against IEEE
+ * 802.11, but makes it easier to use different keys with
+ * stations that do not support WEP key mapping). */
+
+ if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key)
+ (void)hostap_handle_sta_crypto(local, hdr, &crypt,
+ &sta);
+#endif
+
+ /* allow NULL decrypt to indicate an station specific override
+ * for default encryption */
+ if (crypt && (crypt->ops == NULL ||
+ crypt->ops->decrypt_mpdu == NULL))
+ crypt = NULL;
+
+ if (!crypt && (fc & IEEE80211_FCTL_PROTECTED)) {
+ /* This seems to be triggered by some (multicast?)
+ * frames from other than current BSS, so just drop the
+ * frames silently instead of filling system log with
+ * these reports. */
+ IEEE80211_DEBUG_DROP("Decryption failed (not set)"
+ " (SA=%pM)\n", hdr->addr2);
+ ieee->ieee_stats.rx_discards_undecryptable++;
+ goto rx_dropped;
+ }
+ }
+#ifdef NOT_YET
+ if (type != WLAN_FC_TYPE_DATA) {
+ if (type == WLAN_FC_TYPE_MGMT && stype == WLAN_FC_STYPE_AUTH &&
+ fc & IEEE80211_FCTL_PROTECTED && ieee->host_decrypt &&
+ (keyidx = hostap_rx_frame_decrypt(ieee, skb, crypt)) < 0) {
+ printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth "
+ "from %pM\n", dev->name, hdr->addr2);
+ /* TODO: could inform hostapd about this so that it
+ * could send auth failure report */
+ goto rx_dropped;
+ }
+
+ if (ieee80211_rx_frame_mgmt(ieee, skb, rx_stats, type, stype))
+ goto rx_dropped;
+ else
+ goto rx_exit;
+ }
+#endif
+ /* drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.29) */
+ if (sc == ieee->prev_seq_ctl)
+ goto rx_dropped;
+ else
+ ieee->prev_seq_ctl = sc;
+
+ /* Data frame - extract src/dst addresses */
+ if (skb->len < IEEE80211_3ADDR_LEN)
+ goto rx_dropped;
+
+ switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
+ case IEEE80211_FCTL_FROMDS:
+ memcpy(dst, hdr->addr1, ETH_ALEN);
+ memcpy(src, hdr->addr3, ETH_ALEN);
+ break;
+ case IEEE80211_FCTL_TODS:
+ memcpy(dst, hdr->addr3, ETH_ALEN);
+ memcpy(src, hdr->addr2, ETH_ALEN);
+ break;
+ case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
+ if (skb->len < IEEE80211_4ADDR_LEN)
+ goto rx_dropped;
+ memcpy(dst, hdr->addr3, ETH_ALEN);
+ memcpy(src, hdr->addr4, ETH_ALEN);
+ break;
+ case 0:
+ memcpy(dst, hdr->addr1, ETH_ALEN);
+ memcpy(src, hdr->addr2, ETH_ALEN);
+ break;
+ }
+
+#ifdef NOT_YET
+ if (hostap_rx_frame_wds(ieee, hdr, fc, &wds))
+ goto rx_dropped;
+ if (wds) {
+ skb->dev = dev = wds;
+ stats = hostap_get_stats(dev);
+ }
+
+ if (ieee->iw_mode == IW_MODE_MASTER && !wds &&
+ (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+ IEEE80211_FCTL_FROMDS && ieee->stadev
+ && !compare_ether_addr(hdr->addr2, ieee->assoc_ap_addr)) {
+ /* Frame from BSSID of the AP for which we are a client */
+ skb->dev = dev = ieee->stadev;
+ stats = hostap_get_stats(dev);
+ from_assoc_ap = 1;
+ }
+#endif
+
+#ifdef NOT_YET
+ if ((ieee->iw_mode == IW_MODE_MASTER ||
+ ieee->iw_mode == IW_MODE_REPEAT) && !from_assoc_ap) {
+ switch (hostap_handle_sta_rx(ieee, dev, skb, rx_stats,
+ wds != NULL)) {
+ case AP_RX_CONTINUE_NOT_AUTHORIZED:
+ frame_authorized = 0;
+ break;
+ case AP_RX_CONTINUE:
+ frame_authorized = 1;
+ break;
+ case AP_RX_DROP:
+ goto rx_dropped;
+ case AP_RX_EXIT:
+ goto rx_exit;
+ }
+ }
+#endif
+
+ /* Nullfunc frames may have PS-bit set, so they must be passed to
+ * hostap_handle_sta_rx() before being dropped here. */
+
+ stype &= ~IEEE80211_STYPE_QOS_DATA;
+
+ if (stype != IEEE80211_STYPE_DATA &&
+ stype != IEEE80211_STYPE_DATA_CFACK &&
+ stype != IEEE80211_STYPE_DATA_CFPOLL &&
+ stype != IEEE80211_STYPE_DATA_CFACKPOLL) {
+ if (stype != IEEE80211_STYPE_NULLFUNC)
+ IEEE80211_DEBUG_DROP("RX: dropped data frame "
+ "with no data (type=0x%02x, "
+ "subtype=0x%02x, len=%d)\n",
+ type, stype, skb->len);
+ goto rx_dropped;
+ }
+
+ /* skb: hdr + (possibly fragmented, possibly encrypted) payload */
+
+ if ((fc & IEEE80211_FCTL_PROTECTED) && can_be_decrypted &&
+ (keyidx = ieee80211_rx_frame_decrypt(ieee, skb, crypt)) < 0)
+ goto rx_dropped;
+
+ hdr = (struct ieee80211_hdr_4addr *)skb->data;
+
+ /* skb: hdr + (possibly fragmented) plaintext payload */
+ // PR: FIXME: hostap has additional conditions in the "if" below:
+ // ieee->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) &&
+ if ((frag != 0) || (fc & IEEE80211_FCTL_MOREFRAGS)) {
+ int flen;
+ struct sk_buff *frag_skb = ieee80211_frag_cache_get(ieee, hdr);
+ IEEE80211_DEBUG_FRAG("Rx Fragment received (%u)\n", frag);
+
+ if (!frag_skb) {
+ IEEE80211_DEBUG(IEEE80211_DL_RX | IEEE80211_DL_FRAG,
+ "Rx cannot get skb from fragment "
+ "cache (morefrag=%d seq=%u frag=%u)\n",
+ (fc & IEEE80211_FCTL_MOREFRAGS) != 0,
+ WLAN_GET_SEQ_SEQ(sc), frag);
+ goto rx_dropped;
+ }
+
+ flen = skb->len;
+ if (frag != 0)
+ flen -= hdrlen;
+
+ if (frag_skb->tail + flen > frag_skb->end) {
+ printk(KERN_WARNING "%s: host decrypted and "
+ "reassembled frame did not fit skb\n",
+ dev->name);
+ ieee80211_frag_cache_invalidate(ieee, hdr);
+ goto rx_dropped;
+ }
+
+ if (frag == 0) {
+ /* copy first fragment (including full headers) into
+ * beginning of the fragment cache skb */
+ skb_copy_from_linear_data(skb, skb_put(frag_skb, flen), flen);
+ } else {
+ /* append frame payload to the end of the fragment
+ * cache skb */
+ skb_copy_from_linear_data_offset(skb, hdrlen,
+ skb_put(frag_skb, flen), flen);
+ }
+ dev_kfree_skb_any(skb);
+ skb = NULL;
+
+ if (fc & IEEE80211_FCTL_MOREFRAGS) {
+ /* more fragments expected - leave the skb in fragment
+ * cache for now; it will be delivered to upper layers
+ * after all fragments have been received */
+ goto rx_exit;
+ }
+
+ /* this was the last fragment and the frame will be
+ * delivered, so remove skb from fragment cache */
+ skb = frag_skb;
+ hdr = (struct ieee80211_hdr_4addr *)skb->data;
+ ieee80211_frag_cache_invalidate(ieee, hdr);
+ }
+
+ /* skb: hdr + (possible reassembled) full MSDU payload; possibly still
+ * encrypted/authenticated */
+ if ((fc & IEEE80211_FCTL_PROTECTED) && can_be_decrypted &&
+ ieee80211_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt))
+ goto rx_dropped;
+
+ hdr = (struct ieee80211_hdr_4addr *)skb->data;
+ if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep) {
+ if ( /*ieee->ieee802_1x && */
+ ieee80211_is_eapol_frame(ieee, skb)) {
+ /* pass unencrypted EAPOL frames even if encryption is
+ * configured */
+ } else {
+ IEEE80211_DEBUG_DROP("encryption configured, but RX "
+ "frame not encrypted (SA=%pM)\n",
+ hdr->addr2);
+ goto rx_dropped;
+ }
+ }
+
+ if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep &&
+ !ieee80211_is_eapol_frame(ieee, skb)) {
+ IEEE80211_DEBUG_DROP("dropped unencrypted RX data "
+ "frame from %pM (drop_unencrypted=1)\n",
+ hdr->addr2);
+ goto rx_dropped;
+ }
+
+ /* If the frame was decrypted in hardware, we may need to strip off
+ * any security data (IV, ICV, etc) that was left behind */
+ if (!can_be_decrypted && (fc & IEEE80211_FCTL_PROTECTED) &&
+ ieee->host_strip_iv_icv) {
+ int trimlen = 0;
+
+ /* Top two-bits of byte 3 are the key index */
+ if (skb->len >= hdrlen + 3)
+ keyidx = skb->data[hdrlen + 3] >> 6;
+
+ /* To strip off any security data which appears before the
+ * payload, we simply increase hdrlen (as the header gets
+ * chopped off immediately below). For the security data which
+ * appears after the payload, we use skb_trim. */
+
+ switch (ieee->sec.encode_alg[keyidx]) {
+ case SEC_ALG_WEP:
+ /* 4 byte IV */
+ hdrlen += 4;
+ /* 4 byte ICV */
+ trimlen = 4;
+ break;
+ case SEC_ALG_TKIP:
+ /* 4 byte IV, 4 byte ExtIV */
+ hdrlen += 8;
+ /* 8 byte MIC, 4 byte ICV */
+ trimlen = 12;
+ break;
+ case SEC_ALG_CCMP:
+ /* 8 byte CCMP header */
+ hdrlen += 8;
+ /* 8 byte MIC */
+ trimlen = 8;
+ break;
+ }
+
+ if (skb->len < trimlen)
+ goto rx_dropped;
+
+ __skb_trim(skb, skb->len - trimlen);
+
+ if (skb->len < hdrlen)
+ goto rx_dropped;
+ }
+
+ /* skb: hdr + (possible reassembled) full plaintext payload */
+
+ payload = skb->data + hdrlen;
+ ethertype = (payload[6] << 8) | payload[7];
+
+#ifdef NOT_YET
+ /* If IEEE 802.1X is used, check whether the port is authorized to send
+ * the received frame. */
+ if (ieee->ieee802_1x && ieee->iw_mode == IW_MODE_MASTER) {
+ if (ethertype == ETH_P_PAE) {
+ printk(KERN_DEBUG "%s: RX: IEEE 802.1X frame\n",
+ dev->name);
+ if (ieee->hostapd && ieee->apdev) {
+ /* Send IEEE 802.1X frames to the user
+ * space daemon for processing */
+ prism2_rx_80211(ieee->apdev, skb, rx_stats,
+ PRISM2_RX_MGMT);
+ ieee->apdevstats.rx_packets++;
+ ieee->apdevstats.rx_bytes += skb->len;
+ goto rx_exit;
+ }
+ } else if (!frame_authorized) {
+ printk(KERN_DEBUG "%s: dropped frame from "
+ "unauthorized port (IEEE 802.1X): "
+ "ethertype=0x%04x\n", dev->name, ethertype);
+ goto rx_dropped;
+ }
+ }
+#endif
+
+ /* convert hdr + possible LLC headers into Ethernet header */
+ if (skb->len - hdrlen >= 8 &&
+ ((memcmp(payload, rfc1042_header, SNAP_SIZE) == 0 &&
+ ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
+ memcmp(payload, bridge_tunnel_header, SNAP_SIZE) == 0)) {
+ /* remove RFC1042 or Bridge-Tunnel encapsulation and
+ * replace EtherType */
+ skb_pull(skb, hdrlen + SNAP_SIZE);
+ memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
+ memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
+ } else {
+ __be16 len;
+ /* Leave Ethernet header part of hdr and full payload */
+ skb_pull(skb, hdrlen);
+ len = htons(skb->len);
+ memcpy(skb_push(skb, 2), &len, 2);
+ memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
+ memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
+ }
+
+#ifdef NOT_YET
+ if (wds && ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) ==
+ IEEE80211_FCTL_TODS) && skb->len >= ETH_HLEN + ETH_ALEN) {
+ /* Non-standard frame: get addr4 from its bogus location after
+ * the payload */
+ skb_copy_to_linear_data_offset(skb, ETH_ALEN,
+ skb->data + skb->len - ETH_ALEN,
+ ETH_ALEN);
+ skb_trim(skb, skb->len - ETH_ALEN);
+ }
+#endif
+
+ stats->rx_packets++;
+ stats->rx_bytes += skb->len;
+
+#ifdef NOT_YET
+ if (ieee->iw_mode == IW_MODE_MASTER && !wds && ieee->ap->bridge_packets) {
+ if (dst[0] & 0x01) {
+ /* copy multicast frame both to the higher layers and
+ * to the wireless media */
+ ieee->ap->bridged_multicast++;
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (skb2 == NULL)
+ printk(KERN_DEBUG "%s: skb_clone failed for "
+ "multicast frame\n", dev->name);
+ } else if (hostap_is_sta_assoc(ieee->ap, dst)) {
+ /* send frame directly to the associated STA using
+ * wireless media and not passing to higher layers */
+ ieee->ap->bridged_unicast++;
+ skb2 = skb;
+ skb = NULL;
+ }
+ }
+
+ if (skb2 != NULL) {
+ /* send to wireless media */
+ skb2->dev = dev;
+ skb2->protocol = htons(ETH_P_802_3);
+ skb_reset_mac_header(skb2);
+ skb_reset_network_header(skb2);
+ /* skb2->network_header += ETH_HLEN; */
+ dev_queue_xmit(skb2);
+ }
+#endif
+
+ if (skb) {
+ skb->protocol = eth_type_trans(skb, dev);
+ memset(skb->cb, 0, sizeof(skb->cb));
+ skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */
+ if (netif_rx(skb) == NET_RX_DROP) {
+ /* netif_rx always succeeds, but it might drop
+ * the packet. If it drops the packet, we log that
+ * in our stats. */
+ IEEE80211_DEBUG_DROP
+ ("RX: netif_rx dropped the packet\n");
+ stats->rx_dropped++;
+ }
+ }
+
+ rx_exit:
+#ifdef NOT_YET
+ if (sta)
+ hostap_handle_sta_release(sta);
+#endif
+ return 1;
+
+ rx_dropped:
+ stats->rx_dropped++;
+
+ /* Returning 0 indicates to caller that we have not handled the SKB--
+ * so it is still allocated and can be used again by underlying
+ * hardware as a DMA target */
+ return 0;
+}
+
+/* Filter out unrelated packets, call ieee80211_rx[_mgt]
+ * This function takes over the skb, it should not be used again after calling
+ * this function. */
+void ieee80211_rx_any(struct ieee80211_device *ieee,
+ struct sk_buff *skb, struct ieee80211_rx_stats *stats)
+{
+ struct ieee80211_hdr_4addr *hdr;
+ int is_packet_for_us;
+ u16 fc;
+
+ if (ieee->iw_mode == IW_MODE_MONITOR) {
+ if (!ieee80211_rx(ieee, skb, stats))
+ dev_kfree_skb_irq(skb);
+ return;
+ }
+
+ if (skb->len < sizeof(struct ieee80211_hdr))
+ goto drop_free;
+
+ hdr = (struct ieee80211_hdr_4addr *)skb->data;
+ fc = le16_to_cpu(hdr->frame_ctl);
+
+ if ((fc & IEEE80211_FCTL_VERS) != 0)
+ goto drop_free;
+
+ switch (fc & IEEE80211_FCTL_FTYPE) {
+ case IEEE80211_FTYPE_MGMT:
+ if (skb->len < sizeof(struct ieee80211_hdr_3addr))
+ goto drop_free;
+ ieee80211_rx_mgt(ieee, hdr, stats);
+ dev_kfree_skb_irq(skb);
+ return;
+ case IEEE80211_FTYPE_DATA:
+ break;
+ case IEEE80211_FTYPE_CTL:
+ return;
+ default:
+ return;
+ }
+
+ is_packet_for_us = 0;
+ switch (ieee->iw_mode) {
+ case IW_MODE_ADHOC:
+ /* our BSS and not from/to DS */
+ if (memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) == 0)
+ if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == 0) {
+ /* promisc: get all */
+ if (ieee->dev->flags & IFF_PROMISC)
+ is_packet_for_us = 1;
+ /* to us */
+ else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0)
+ is_packet_for_us = 1;
+ /* mcast */
+ else if (is_multicast_ether_addr(hdr->addr1))
+ is_packet_for_us = 1;
+ }
+ break;
+ case IW_MODE_INFRA:
+ /* our BSS (== from our AP) and from DS */
+ if (memcmp(hdr->addr2, ieee->bssid, ETH_ALEN) == 0)
+ if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS) {
+ /* promisc: get all */
+ if (ieee->dev->flags & IFF_PROMISC)
+ is_packet_for_us = 1;
+ /* to us */
+ else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0)
+ is_packet_for_us = 1;
+ /* mcast */
+ else if (is_multicast_ether_addr(hdr->addr1)) {
+ /* not our own packet bcasted from AP */
+ if (memcmp(hdr->addr3, ieee->dev->dev_addr, ETH_ALEN))
+ is_packet_for_us = 1;
+ }
+ }
+ break;
+ default:
+ /* ? */
+ break;
+ }
+
+ if (is_packet_for_us)
+ if (!ieee80211_rx(ieee, skb, stats))
+ dev_kfree_skb_irq(skb);
+ return;
+
+drop_free:
+ dev_kfree_skb_irq(skb);
+ ieee->stats.rx_dropped++;
+ return;
+}
+
+#define MGMT_FRAME_FIXED_PART_LENGTH 0x24
+
+static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
+
+/*
+* Make ther structure we read from the beacon packet has
+* the right values
+*/
+static int ieee80211_verify_qos_info(struct ieee80211_qos_information_element
+ *info_element, int sub_type)
+{
+
+ if (info_element->qui_subtype != sub_type)
+ return -1;
+ if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN))
+ return -1;
+ if (info_element->qui_type != QOS_OUI_TYPE)
+ return -1;
+ if (info_element->version != QOS_VERSION_1)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * Parse a QoS parameter element
+ */
+static int ieee80211_read_qos_param_element(struct ieee80211_qos_parameter_info
+ *element_param, struct ieee80211_info_element
+ *info_element)
+{
+ int ret = 0;
+ u16 size = sizeof(struct ieee80211_qos_parameter_info) - 2;
+
+ if ((info_element == NULL) || (element_param == NULL))
+ return -1;
+
+ if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) {
+ memcpy(element_param->info_element.qui, info_element->data,
+ info_element->len);
+ element_param->info_element.elementID = info_element->id;
+ element_param->info_element.length = info_element->len;
+ } else
+ ret = -1;
+ if (ret == 0)
+ ret = ieee80211_verify_qos_info(&element_param->info_element,
+ QOS_OUI_PARAM_SUB_TYPE);
+ return ret;
+}
+
+/*
+ * Parse a QoS information element
+ */
+static int ieee80211_read_qos_info_element(struct
+ ieee80211_qos_information_element
+ *element_info, struct ieee80211_info_element
+ *info_element)
+{
+ int ret = 0;
+ u16 size = sizeof(struct ieee80211_qos_information_element) - 2;
+
+ if (element_info == NULL)
+ return -1;
+ if (info_element == NULL)
+ return -1;
+
+ if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) {
+ memcpy(element_info->qui, info_element->data,
+ info_element->len);
+ element_info->elementID = info_element->id;
+ element_info->length = info_element->len;
+ } else
+ ret = -1;
+
+ if (ret == 0)
+ ret = ieee80211_verify_qos_info(element_info,
+ QOS_OUI_INFO_SUB_TYPE);
+ return ret;
+}
+
+/*
+ * Write QoS parameters from the ac parameters.
+ */
+static int ieee80211_qos_convert_ac_to_parameters(struct
+ ieee80211_qos_parameter_info
+ *param_elm, struct
+ ieee80211_qos_parameters
+ *qos_param)
+{
+ int rc = 0;
+ int i;
+ struct ieee80211_qos_ac_parameter *ac_params;
+ u32 txop;
+ u8 cw_min;
+ u8 cw_max;
+
+ for (i = 0; i < QOS_QUEUE_NUM; i++) {
+ ac_params = &(param_elm->ac_params_record[i]);
+
+ qos_param->aifs[i] = (ac_params->aci_aifsn) & 0x0F;
+ qos_param->aifs[i] -= (qos_param->aifs[i] < 2) ? 0 : 2;
+
+ cw_min = ac_params->ecw_min_max & 0x0F;
+ qos_param->cw_min[i] = cpu_to_le16((1 << cw_min) - 1);
+
+ cw_max = (ac_params->ecw_min_max & 0xF0) >> 4;
+ qos_param->cw_max[i] = cpu_to_le16((1 << cw_max) - 1);
+
+ qos_param->flag[i] =
+ (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00;
+
+ txop = le16_to_cpu(ac_params->tx_op_limit) * 32;
+ qos_param->tx_op_limit[i] = cpu_to_le16(txop);
+ }
+ return rc;
+}
+
+/*
+ * we have a generic data element which it may contain QoS information or
+ * parameters element. check the information element length to decide
+ * which type to read
+ */
+static int ieee80211_parse_qos_info_param_IE(struct ieee80211_info_element
+ *info_element,
+ struct ieee80211_network *network)
+{
+ int rc = 0;
+ struct ieee80211_qos_parameters *qos_param = NULL;
+ struct ieee80211_qos_information_element qos_info_element;
+
+ rc = ieee80211_read_qos_info_element(&qos_info_element, info_element);
+
+ if (rc == 0) {
+ network->qos_data.param_count = qos_info_element.ac_info & 0x0F;
+ network->flags |= NETWORK_HAS_QOS_INFORMATION;
+ } else {
+ struct ieee80211_qos_parameter_info param_element;
+
+ rc = ieee80211_read_qos_param_element(&param_element,
+ info_element);
+ if (rc == 0) {
+ qos_param = &(network->qos_data.parameters);
+ ieee80211_qos_convert_ac_to_parameters(&param_element,
+ qos_param);
+ network->flags |= NETWORK_HAS_QOS_PARAMETERS;
+ network->qos_data.param_count =
+ param_element.info_element.ac_info & 0x0F;
+ }
+ }
+
+ if (rc == 0) {
+ IEEE80211_DEBUG_QOS("QoS is supported\n");
+ network->qos_data.supported = 1;
+ }
+ return rc;
+}
+
+#ifdef CONFIG_IEEE80211_DEBUG
+#define MFIE_STRING(x) case MFIE_TYPE_ ##x: return #x
+
+static const char *get_info_element_string(u16 id)
+{
+ switch (id) {
+ MFIE_STRING(SSID);
+ MFIE_STRING(RATES);
+ MFIE_STRING(FH_SET);
+ MFIE_STRING(DS_SET);
+ MFIE_STRING(CF_SET);
+ MFIE_STRING(TIM);
+ MFIE_STRING(IBSS_SET);
+ MFIE_STRING(COUNTRY);
+ MFIE_STRING(HOP_PARAMS);
+ MFIE_STRING(HOP_TABLE);
+ MFIE_STRING(REQUEST);
+ MFIE_STRING(CHALLENGE);
+ MFIE_STRING(POWER_CONSTRAINT);
+ MFIE_STRING(POWER_CAPABILITY);
+ MFIE_STRING(TPC_REQUEST);
+ MFIE_STRING(TPC_REPORT);
+ MFIE_STRING(SUPP_CHANNELS);
+ MFIE_STRING(CSA);
+ MFIE_STRING(MEASURE_REQUEST);
+ MFIE_STRING(MEASURE_REPORT);
+ MFIE_STRING(QUIET);
+ MFIE_STRING(IBSS_DFS);
+ MFIE_STRING(ERP_INFO);
+ MFIE_STRING(RSN);
+ MFIE_STRING(RATES_EX);
+ MFIE_STRING(GENERIC);
+ MFIE_STRING(QOS_PARAMETER);
+ default:
+ return "UNKNOWN";
+ }
+}
+#endif
+
+static int ieee80211_parse_info_param(struct ieee80211_info_element
+ *info_element, u16 length,
+ struct ieee80211_network *network)
+{
+ DECLARE_SSID_BUF(ssid);
+ u8 i;
+#ifdef CONFIG_IEEE80211_DEBUG
+ char rates_str[64];
+ char *p;
+#endif
+
+ while (length >= sizeof(*info_element)) {
+ if (sizeof(*info_element) + info_element->len > length) {
+ IEEE80211_DEBUG_MGMT("Info elem: parse failed: "
+ "info_element->len + 2 > left : "
+ "info_element->len+2=%zd left=%d, id=%d.\n",
+ info_element->len +
+ sizeof(*info_element),
+ length, info_element->id);
+ /* We stop processing but don't return an error here
+ * because some misbehaviour APs break this rule. ie.
+ * Orinoco AP1000. */
+ break;
+ }
+
+ switch (info_element->id) {
+ case MFIE_TYPE_SSID:
+ network->ssid_len = min(info_element->len,
+ (u8) IW_ESSID_MAX_SIZE);
+ memcpy(network->ssid, info_element->data,
+ network->ssid_len);
+ if (network->ssid_len < IW_ESSID_MAX_SIZE)
+ memset(network->ssid + network->ssid_len, 0,
+ IW_ESSID_MAX_SIZE - network->ssid_len);
+
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_SSID: '%s' len=%d.\n",
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->ssid_len);
+ break;
+
+ case MFIE_TYPE_RATES:
+#ifdef CONFIG_IEEE80211_DEBUG
+ p = rates_str;
+#endif
+ network->rates_len = min(info_element->len,
+ MAX_RATES_LENGTH);
+ for (i = 0; i < network->rates_len; i++) {
+ network->rates[i] = info_element->data[i];
+#ifdef CONFIG_IEEE80211_DEBUG
+ p += snprintf(p, sizeof(rates_str) -
+ (p - rates_str), "%02X ",
+ network->rates[i]);
+#endif
+ if (ieee80211_is_ofdm_rate
+ (info_element->data[i])) {
+ network->flags |= NETWORK_HAS_OFDM;
+ if (info_element->data[i] &
+ IEEE80211_BASIC_RATE_MASK)
+ network->flags &=
+ ~NETWORK_HAS_CCK;
+ }
+ }
+
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES: '%s' (%d)\n",
+ rates_str, network->rates_len);
+ break;
+
+ case MFIE_TYPE_RATES_EX:
+#ifdef CONFIG_IEEE80211_DEBUG
+ p = rates_str;
+#endif
+ network->rates_ex_len = min(info_element->len,
+ MAX_RATES_EX_LENGTH);
+ for (i = 0; i < network->rates_ex_len; i++) {
+ network->rates_ex[i] = info_element->data[i];
+#ifdef CONFIG_IEEE80211_DEBUG
+ p += snprintf(p, sizeof(rates_str) -
+ (p - rates_str), "%02X ",
+ network->rates[i]);
+#endif
+ if (ieee80211_is_ofdm_rate
+ (info_element->data[i])) {
+ network->flags |= NETWORK_HAS_OFDM;
+ if (info_element->data[i] &
+ IEEE80211_BASIC_RATE_MASK)
+ network->flags &=
+ ~NETWORK_HAS_CCK;
+ }
+ }
+
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_RATES_EX: '%s' (%d)\n",
+ rates_str, network->rates_ex_len);
+ break;
+
+ case MFIE_TYPE_DS_SET:
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_DS_SET: %d\n",
+ info_element->data[0]);
+ network->channel = info_element->data[0];
+ break;
+
+ case MFIE_TYPE_FH_SET:
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_FH_SET: ignored\n");
+ break;
+
+ case MFIE_TYPE_CF_SET:
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_CF_SET: ignored\n");
+ break;
+
+ case MFIE_TYPE_TIM:
+ network->tim.tim_count = info_element->data[0];
+ network->tim.tim_period = info_element->data[1];
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_TIM: partially ignored\n");
+ break;
+
+ case MFIE_TYPE_ERP_INFO:
+ network->erp_value = info_element->data[0];
+ network->flags |= NETWORK_HAS_ERP_VALUE;
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n",
+ network->erp_value);
+ break;
+
+ case MFIE_TYPE_IBSS_SET:
+ network->atim_window = info_element->data[0];
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_IBSS_SET: %d\n",
+ network->atim_window);
+ break;
+
+ case MFIE_TYPE_CHALLENGE:
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_CHALLENGE: ignored\n");
+ break;
+
+ case MFIE_TYPE_GENERIC:
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_GENERIC: %d bytes\n",
+ info_element->len);
+ if (!ieee80211_parse_qos_info_param_IE(info_element,
+ network))
+ break;
+
+ if (info_element->len >= 4 &&
+ info_element->data[0] == 0x00 &&
+ info_element->data[1] == 0x50 &&
+ info_element->data[2] == 0xf2 &&
+ info_element->data[3] == 0x01) {
+ network->wpa_ie_len = min(info_element->len + 2,
+ MAX_WPA_IE_LEN);
+ memcpy(network->wpa_ie, info_element,
+ network->wpa_ie_len);
+ }
+ break;
+
+ case MFIE_TYPE_RSN:
+ IEEE80211_DEBUG_MGMT("MFIE_TYPE_RSN: %d bytes\n",
+ info_element->len);
+ network->rsn_ie_len = min(info_element->len + 2,
+ MAX_WPA_IE_LEN);
+ memcpy(network->rsn_ie, info_element,
+ network->rsn_ie_len);
+ break;
+
+ case MFIE_TYPE_QOS_PARAMETER:
+ printk(KERN_ERR
+ "QoS Error need to parse QOS_PARAMETER IE\n");
+ break;
+ /* 802.11h */
+ case MFIE_TYPE_POWER_CONSTRAINT:
+ network->power_constraint = info_element->data[0];
+ network->flags |= NETWORK_HAS_POWER_CONSTRAINT;
+ break;
+
+ case MFIE_TYPE_CSA:
+ network->power_constraint = info_element->data[0];
+ network->flags |= NETWORK_HAS_CSA;
+ break;
+
+ case MFIE_TYPE_QUIET:
+ network->quiet.count = info_element->data[0];
+ network->quiet.period = info_element->data[1];
+ network->quiet.duration = info_element->data[2];
+ network->quiet.offset = info_element->data[3];
+ network->flags |= NETWORK_HAS_QUIET;
+ break;
+
+ case MFIE_TYPE_IBSS_DFS:
+ if (network->ibss_dfs)
+ break;
+ network->ibss_dfs = kmemdup(info_element->data,
+ info_element->len,
+ GFP_ATOMIC);
+ if (!network->ibss_dfs)
+ return 1;
+ network->flags |= NETWORK_HAS_IBSS_DFS;
+ break;
+
+ case MFIE_TYPE_TPC_REPORT:
+ network->tpc_report.transmit_power =
+ info_element->data[0];
+ network->tpc_report.link_margin = info_element->data[1];
+ network->flags |= NETWORK_HAS_TPC_REPORT;
+ break;
+
+ default:
+ IEEE80211_DEBUG_MGMT
+ ("Unsupported info element: %s (%d)\n",
+ get_info_element_string(info_element->id),
+ info_element->id);
+ break;
+ }
+
+ length -= sizeof(*info_element) + info_element->len;
+ info_element =
+ (struct ieee80211_info_element *)&info_element->
+ data[info_element->len];
+ }
+
+ return 0;
+}
+
+static int ieee80211_handle_assoc_resp(struct ieee80211_device *ieee, struct ieee80211_assoc_response
+ *frame, struct ieee80211_rx_stats *stats)
+{
+ struct ieee80211_network network_resp = {
+ .ibss_dfs = NULL,
+ };
+ struct ieee80211_network *network = &network_resp;
+ struct net_device *dev = ieee->dev;
+
+ network->flags = 0;
+ network->qos_data.active = 0;
+ network->qos_data.supported = 0;
+ network->qos_data.param_count = 0;
+ network->qos_data.old_param_count = 0;
+
+ //network->atim_window = le16_to_cpu(frame->aid) & (0x3FFF);
+ network->atim_window = le16_to_cpu(frame->aid);
+ network->listen_interval = le16_to_cpu(frame->status);
+ memcpy(network->bssid, frame->header.addr3, ETH_ALEN);
+ network->capability = le16_to_cpu(frame->capability);
+ network->last_scanned = jiffies;
+ network->rates_len = network->rates_ex_len = 0;
+ network->last_associate = 0;
+ network->ssid_len = 0;
+ network->erp_value =
+ (network->capability & WLAN_CAPABILITY_IBSS) ? 0x3 : 0x0;
+
+ if (stats->freq == IEEE80211_52GHZ_BAND) {
+ /* for A band (No DS info) */
+ network->channel = stats->received_channel;
+ } else
+ network->flags |= NETWORK_HAS_CCK;
+
+ network->wpa_ie_len = 0;
+ network->rsn_ie_len = 0;
+
+ if (ieee80211_parse_info_param
+ (frame->info_element, stats->len - sizeof(*frame), network))
+ return 1;
+
+ network->mode = 0;
+ if (stats->freq == IEEE80211_52GHZ_BAND)
+ network->mode = IEEE_A;
+ else {
+ if (network->flags & NETWORK_HAS_OFDM)
+ network->mode |= IEEE_G;
+ if (network->flags & NETWORK_HAS_CCK)
+ network->mode |= IEEE_B;
+ }
+
+ memcpy(&network->stats, stats, sizeof(network->stats));
+
+ if (ieee->handle_assoc_response != NULL)
+ ieee->handle_assoc_response(dev, frame, network);
+
+ return 0;
+}
+
+/***************************************************/
+
+static int ieee80211_network_init(struct ieee80211_device *ieee, struct ieee80211_probe_response
+ *beacon,
+ struct ieee80211_network *network,
+ struct ieee80211_rx_stats *stats)
+{
+ DECLARE_SSID_BUF(ssid);
+
+ network->qos_data.active = 0;
+ network->qos_data.supported = 0;
+ network->qos_data.param_count = 0;
+ network->qos_data.old_param_count = 0;
+
+ /* Pull out fixed field data */
+ memcpy(network->bssid, beacon->header.addr3, ETH_ALEN);
+ network->capability = le16_to_cpu(beacon->capability);
+ network->last_scanned = jiffies;
+ network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]);
+ network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]);
+ network->beacon_interval = le16_to_cpu(beacon->beacon_interval);
+ /* Where to pull this? beacon->listen_interval; */
+ network->listen_interval = 0x0A;
+ network->rates_len = network->rates_ex_len = 0;
+ network->last_associate = 0;
+ network->ssid_len = 0;
+ network->flags = 0;
+ network->atim_window = 0;
+ network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ?
+ 0x3 : 0x0;
+
+ if (stats->freq == IEEE80211_52GHZ_BAND) {
+ /* for A band (No DS info) */
+ network->channel = stats->received_channel;
+ } else
+ network->flags |= NETWORK_HAS_CCK;
+
+ network->wpa_ie_len = 0;
+ network->rsn_ie_len = 0;
+
+ if (ieee80211_parse_info_param
+ (beacon->info_element, stats->len - sizeof(*beacon), network))
+ return 1;
+
+ network->mode = 0;
+ if (stats->freq == IEEE80211_52GHZ_BAND)
+ network->mode = IEEE_A;
+ else {
+ if (network->flags & NETWORK_HAS_OFDM)
+ network->mode |= IEEE_G;
+ if (network->flags & NETWORK_HAS_CCK)
+ network->mode |= IEEE_B;
+ }
+
+ if (network->mode == 0) {
+ IEEE80211_DEBUG_SCAN("Filtered out '%s (%pM)' "
+ "network.\n",
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid);
+ return 1;
+ }
+
+ memcpy(&network->stats, stats, sizeof(network->stats));
+
+ return 0;
+}
+
+static inline int is_same_network(struct ieee80211_network *src,
+ struct ieee80211_network *dst)
+{
+ /* A network is only a duplicate if the channel, BSSID, and ESSID
+ * all match. We treat all <hidden> with the same BSSID and channel
+ * as one network */
+ return ((src->ssid_len == dst->ssid_len) &&
+ (src->channel == dst->channel) &&
+ !compare_ether_addr(src->bssid, dst->bssid) &&
+ !memcmp(src->ssid, dst->ssid, src->ssid_len));
+}
+
+static void update_network(struct ieee80211_network *dst,
+ struct ieee80211_network *src)
+{
+ int qos_active;
+ u8 old_param;
+
+ ieee80211_network_reset(dst);
+ dst->ibss_dfs = src->ibss_dfs;
+
+ /* We only update the statistics if they were created by receiving
+ * the network information on the actual channel the network is on.
+ *
+ * This keeps beacons received on neighbor channels from bringing
+ * down the signal level of an AP. */
+ if (dst->channel == src->stats.received_channel)
+ memcpy(&dst->stats, &src->stats,
+ sizeof(struct ieee80211_rx_stats));
+ else
+ IEEE80211_DEBUG_SCAN("Network %pM info received "
+ "off channel (%d vs. %d)\n", src->bssid,
+ dst->channel, src->stats.received_channel);
+
+ dst->capability = src->capability;
+ memcpy(dst->rates, src->rates, src->rates_len);
+ dst->rates_len = src->rates_len;
+ memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len);
+ dst->rates_ex_len = src->rates_ex_len;
+
+ dst->mode = src->mode;
+ dst->flags = src->flags;
+ dst->time_stamp[0] = src->time_stamp[0];
+ dst->time_stamp[1] = src->time_stamp[1];
+
+ dst->beacon_interval = src->beacon_interval;
+ dst->listen_interval = src->listen_interval;
+ dst->atim_window = src->atim_window;
+ dst->erp_value = src->erp_value;
+ dst->tim = src->tim;
+
+ memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len);
+ dst->wpa_ie_len = src->wpa_ie_len;
+ memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len);
+ dst->rsn_ie_len = src->rsn_ie_len;
+
+ dst->last_scanned = jiffies;
+ qos_active = src->qos_data.active;
+ old_param = dst->qos_data.old_param_count;
+ if (dst->flags & NETWORK_HAS_QOS_MASK)
+ memcpy(&dst->qos_data, &src->qos_data,
+ sizeof(struct ieee80211_qos_data));
+ else {
+ dst->qos_data.supported = src->qos_data.supported;
+ dst->qos_data.param_count = src->qos_data.param_count;
+ }
+
+ if (dst->qos_data.supported == 1) {
+ if (dst->ssid_len)
+ IEEE80211_DEBUG_QOS
+ ("QoS the network %s is QoS supported\n",
+ dst->ssid);
+ else
+ IEEE80211_DEBUG_QOS
+ ("QoS the network is QoS supported\n");
+ }
+ dst->qos_data.active = qos_active;
+ dst->qos_data.old_param_count = old_param;
+
+ /* dst->last_associate is not overwritten */
+}
+
+static inline int is_beacon(__le16 fc)
+{
+ return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON);
+}
+
+static void ieee80211_process_probe_response(struct ieee80211_device
+ *ieee, struct
+ ieee80211_probe_response
+ *beacon, struct ieee80211_rx_stats
+ *stats)
+{
+ struct net_device *dev = ieee->dev;
+ struct ieee80211_network network = {
+ .ibss_dfs = NULL,
+ };
+ struct ieee80211_network *target;
+ struct ieee80211_network *oldest = NULL;
+#ifdef CONFIG_IEEE80211_DEBUG
+ struct ieee80211_info_element *info_element = beacon->info_element;
+#endif
+ unsigned long flags;
+ DECLARE_SSID_BUF(ssid);
+
+ IEEE80211_DEBUG_SCAN("'%s' (%pM"
+ "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n",
+ print_ssid(ssid, info_element->data, info_element->len),
+ beacon->header.addr3,
+ (beacon->capability & cpu_to_le16(1 << 0xf)) ? '1' : '0',
+ (beacon->capability & cpu_to_le16(1 << 0xe)) ? '1' : '0',
+ (beacon->capability & cpu_to_le16(1 << 0xd)) ? '1' : '0',
+ (beacon->capability & cpu_to_le16(1 << 0xc)) ? '1' : '0',
+ (beacon->capability & cpu_to_le16(1 << 0xb)) ? '1' : '0',
+ (beacon->capability & cpu_to_le16(1 << 0xa)) ? '1' : '0',
+ (beacon->capability & cpu_to_le16(1 << 0x9)) ? '1' : '0',
+ (beacon->capability & cpu_to_le16(1 << 0x8)) ? '1' : '0',
+ (beacon->capability & cpu_to_le16(1 << 0x7)) ? '1' : '0',
+ (beacon->capability & cpu_to_le16(1 << 0x6)) ? '1' : '0',
+ (beacon->capability & cpu_to_le16(1 << 0x5)) ? '1' : '0',
+ (beacon->capability & cpu_to_le16(1 << 0x4)) ? '1' : '0',
+ (beacon->capability & cpu_to_le16(1 << 0x3)) ? '1' : '0',
+ (beacon->capability & cpu_to_le16(1 << 0x2)) ? '1' : '0',
+ (beacon->capability & cpu_to_le16(1 << 0x1)) ? '1' : '0',
+ (beacon->capability & cpu_to_le16(1 << 0x0)) ? '1' : '0');
+
+ if (ieee80211_network_init(ieee, beacon, &network, stats)) {
+ IEEE80211_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n",
+ print_ssid(ssid, info_element->data,
+ info_element->len),
+ beacon->header.addr3,
+ is_beacon(beacon->header.frame_ctl) ?
+ "BEACON" : "PROBE RESPONSE");
+ return;
+ }
+
+ /* The network parsed correctly -- so now we scan our known networks
+ * to see if we can find it in our list.
+ *
+ * NOTE: This search is definitely not optimized. Once its doing
+ * the "right thing" we'll optimize it for efficiency if
+ * necessary */
+
+ /* Search for this entry in the list and update it if it is
+ * already there. */
+
+ spin_lock_irqsave(&ieee->lock, flags);
+
+ list_for_each_entry(target, &ieee->network_list, list) {
+ if (is_same_network(target, &network))
+ break;
+
+ if ((oldest == NULL) ||
+ (target->last_scanned < oldest->last_scanned))
+ oldest = target;
+ }
+
+ /* If we didn't find a match, then get a new network slot to initialize
+ * with this beacon's information */
+ if (&target->list == &ieee->network_list) {
+ if (list_empty(&ieee->network_free_list)) {
+ /* If there are no more slots, expire the oldest */
+ list_del(&oldest->list);
+ target = oldest;
+ IEEE80211_DEBUG_SCAN("Expired '%s' (%pM) from "
+ "network list.\n",
+ print_ssid(ssid, target->ssid,
+ target->ssid_len),
+ target->bssid);
+ ieee80211_network_reset(target);
+ } else {
+ /* Otherwise just pull from the free list */
+ target = list_entry(ieee->network_free_list.next,
+ struct ieee80211_network, list);
+ list_del(ieee->network_free_list.next);
+ }
+
+#ifdef CONFIG_IEEE80211_DEBUG
+ IEEE80211_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n",
+ print_ssid(ssid, network.ssid,
+ network.ssid_len),
+ network.bssid,
+ is_beacon(beacon->header.frame_ctl) ?
+ "BEACON" : "PROBE RESPONSE");
+#endif
+ memcpy(target, &network, sizeof(*target));
+ network.ibss_dfs = NULL;
+ list_add_tail(&target->list, &ieee->network_list);
+ } else {
+ IEEE80211_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n",
+ print_ssid(ssid, target->ssid,
+ target->ssid_len),
+ target->bssid,
+ is_beacon(beacon->header.frame_ctl) ?
+ "BEACON" : "PROBE RESPONSE");
+ update_network(target, &network);
+ network.ibss_dfs = NULL;
+ }
+
+ spin_unlock_irqrestore(&ieee->lock, flags);
+
+ if (is_beacon(beacon->header.frame_ctl)) {
+ if (ieee->handle_beacon != NULL)
+ ieee->handle_beacon(dev, beacon, target);
+ } else {
+ if (ieee->handle_probe_response != NULL)
+ ieee->handle_probe_response(dev, beacon, target);
+ }
+}
+
+void ieee80211_rx_mgt(struct ieee80211_device *ieee,
+ struct ieee80211_hdr_4addr *header,
+ struct ieee80211_rx_stats *stats)
+{
+ switch (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl))) {
+ case IEEE80211_STYPE_ASSOC_RESP:
+ IEEE80211_DEBUG_MGMT("received ASSOCIATION RESPONSE (%d)\n",
+ WLAN_FC_GET_STYPE(le16_to_cpu
+ (header->frame_ctl)));
+ ieee80211_handle_assoc_resp(ieee,
+ (struct ieee80211_assoc_response *)
+ header, stats);
+ break;
+
+ case IEEE80211_STYPE_REASSOC_RESP:
+ IEEE80211_DEBUG_MGMT("received REASSOCIATION RESPONSE (%d)\n",
+ WLAN_FC_GET_STYPE(le16_to_cpu
+ (header->frame_ctl)));
+ break;
+
+ case IEEE80211_STYPE_PROBE_REQ:
+ IEEE80211_DEBUG_MGMT("received auth (%d)\n",
+ WLAN_FC_GET_STYPE(le16_to_cpu
+ (header->frame_ctl)));
+
+ if (ieee->handle_probe_request != NULL)
+ ieee->handle_probe_request(ieee->dev,
+ (struct
+ ieee80211_probe_request *)
+ header, stats);
+ break;
+
+ case IEEE80211_STYPE_PROBE_RESP:
+ IEEE80211_DEBUG_MGMT("received PROBE RESPONSE (%d)\n",
+ WLAN_FC_GET_STYPE(le16_to_cpu
+ (header->frame_ctl)));
+ IEEE80211_DEBUG_SCAN("Probe response\n");
+ ieee80211_process_probe_response(ieee,
+ (struct
+ ieee80211_probe_response *)
+ header, stats);
+ break;
+
+ case IEEE80211_STYPE_BEACON:
+ IEEE80211_DEBUG_MGMT("received BEACON (%d)\n",
+ WLAN_FC_GET_STYPE(le16_to_cpu
+ (header->frame_ctl)));
+ IEEE80211_DEBUG_SCAN("Beacon\n");
+ ieee80211_process_probe_response(ieee,
+ (struct
+ ieee80211_probe_response *)
+ header, stats);
+ break;
+ case IEEE80211_STYPE_AUTH:
+
+ IEEE80211_DEBUG_MGMT("received auth (%d)\n",
+ WLAN_FC_GET_STYPE(le16_to_cpu
+ (header->frame_ctl)));
+
+ if (ieee->handle_auth != NULL)
+ ieee->handle_auth(ieee->dev,
+ (struct ieee80211_auth *)header);
+ break;
+
+ case IEEE80211_STYPE_DISASSOC:
+ if (ieee->handle_disassoc != NULL)
+ ieee->handle_disassoc(ieee->dev,
+ (struct ieee80211_disassoc *)
+ header);
+ break;
+
+ case IEEE80211_STYPE_ACTION:
+ IEEE80211_DEBUG_MGMT("ACTION\n");
+ if (ieee->handle_action)
+ ieee->handle_action(ieee->dev,
+ (struct ieee80211_action *)
+ header, stats);
+ break;
+
+ case IEEE80211_STYPE_REASSOC_REQ:
+ IEEE80211_DEBUG_MGMT("received reassoc (%d)\n",
+ WLAN_FC_GET_STYPE(le16_to_cpu
+ (header->frame_ctl)));
+
+ IEEE80211_DEBUG_MGMT("%s: IEEE80211_REASSOC_REQ received\n",
+ ieee->dev->name);
+ if (ieee->handle_reassoc_request != NULL)
+ ieee->handle_reassoc_request(ieee->dev,
+ (struct ieee80211_reassoc_request *)
+ header);
+ break;
+
+ case IEEE80211_STYPE_ASSOC_REQ:
+ IEEE80211_DEBUG_MGMT("received assoc (%d)\n",
+ WLAN_FC_GET_STYPE(le16_to_cpu
+ (header->frame_ctl)));
+
+ IEEE80211_DEBUG_MGMT("%s: IEEE80211_ASSOC_REQ received\n",
+ ieee->dev->name);
+ if (ieee->handle_assoc_request != NULL)
+ ieee->handle_assoc_request(ieee->dev);
+ break;
+
+ case IEEE80211_STYPE_DEAUTH:
+ IEEE80211_DEBUG_MGMT("DEAUTH\n");
+ if (ieee->handle_deauth != NULL)
+ ieee->handle_deauth(ieee->dev,
+ (struct ieee80211_deauth *)
+ header);
+ break;
+ default:
+ IEEE80211_DEBUG_MGMT("received UNKNOWN (%d)\n",
+ WLAN_FC_GET_STYPE(le16_to_cpu
+ (header->frame_ctl)));
+ IEEE80211_DEBUG_MGMT("%s: Unknown management packet: %d\n",
+ ieee->dev->name,
+ WLAN_FC_GET_STYPE(le16_to_cpu
+ (header->frame_ctl)));
+ break;
+ }
+}
+
+EXPORT_SYMBOL_GPL(ieee80211_rx_any);
+EXPORT_SYMBOL(ieee80211_rx_mgt);
+EXPORT_SYMBOL(ieee80211_rx);
diff --git a/drivers/net/wireless/ipw2x00/libipw_tx.c b/drivers/net/wireless/ipw2x00/libipw_tx.c
new file mode 100644
index 000000000000..f78f57e8844a
--- /dev/null
+++ b/drivers/net/wireless/ipw2x00/libipw_tx.c
@@ -0,0 +1,546 @@
+/******************************************************************************
+
+ Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ 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., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************/
+#include <linux/compiler.h>
+#include <linux/errno.h>
+#include <linux/if_arp.h>
+#include <linux/in6.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/tcp.h>
+#include <linux/types.h>
+#include <linux/wireless.h>
+#include <linux/etherdevice.h>
+#include <asm/uaccess.h>
+
+#include <net/ieee80211.h>
+
+/*
+
+802.11 Data Frame
+
+ ,-------------------------------------------------------------------.
+Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 |
+ |------|------|---------|---------|---------|------|---------|------|
+Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs |
+ | | tion | (BSSID) | | | ence | data | |
+ `--------------------------------------------------| |------'
+Total: 28 non-data bytes `----.----'
+ |
+ .- 'Frame data' expands, if WEP enabled, to <----------'
+ |
+ V
+ ,-----------------------.
+Bytes | 4 | 0-2296 | 4 |
+ |-----|-----------|-----|
+Desc. | IV | Encrypted | ICV |
+ | | Packet | |
+ `-----| |-----'
+ `-----.-----'
+ |
+ .- 'Encrypted Packet' expands to
+ |
+ V
+ ,---------------------------------------------------.
+Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 |
+ |------|------|---------|----------|------|---------|
+Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP |
+ | DSAP | SSAP | | | | Packet |
+ | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | |
+ `----------------------------------------------------
+Total: 8 non-data bytes
+
+802.3 Ethernet Data Frame
+
+ ,-----------------------------------------.
+Bytes | 6 | 6 | 2 | Variable | 4 |
+ |-------|-------|------|-----------|------|
+Desc. | Dest. | Source| Type | IP Packet | fcs |
+ | MAC | MAC | | | |
+ `-----------------------------------------'
+Total: 18 non-data bytes
+
+In the event that fragmentation is required, the incoming payload is split into
+N parts of size ieee->fts. The first fragment contains the SNAP header and the
+remaining packets are just data.
+
+If encryption is enabled, each fragment payload size is reduced by enough space
+to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP)
+So if you have 1500 bytes of payload with ieee->fts set to 500 without
+encryption it will take 3 frames. With WEP it will take 4 frames as the
+payload of each frame is reduced to 492 bytes.
+
+* SKB visualization
+*
+* ,- skb->data
+* |
+* | ETHERNET HEADER ,-<-- PAYLOAD
+* | | 14 bytes from skb->data
+* | 2 bytes for Type --> ,T. | (sizeof ethhdr)
+* | | | |
+* |,-Dest.--. ,--Src.---. | | |
+* | 6 bytes| | 6 bytes | | | |
+* v | | | | | |
+* 0 | v 1 | v | v 2
+* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+* ^ | ^ | ^ |
+* | | | | | |
+* | | | | `T' <---- 2 bytes for Type
+* | | | |
+* | | '---SNAP--' <-------- 6 bytes for SNAP
+* | |
+* `-IV--' <-------------------- 4 bytes for IV (WEP)
+*
+* SNAP HEADER
+*
+*/
+
+static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
+static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
+
+static int ieee80211_copy_snap(u8 * data, __be16 h_proto)
+{
+ struct ieee80211_snap_hdr *snap;
+ u8 *oui;
+
+ snap = (struct ieee80211_snap_hdr *)data;
+ snap->dsap = 0xaa;
+ snap->ssap = 0xaa;
+ snap->ctrl = 0x03;
+
+ if (h_proto == htons(ETH_P_AARP) || h_proto == htons(ETH_P_IPX))
+ oui = P802_1H_OUI;
+ else
+ oui = RFC1042_OUI;
+ snap->oui[0] = oui[0];
+ snap->oui[1] = oui[1];
+ snap->oui[2] = oui[2];
+
+ memcpy(data + SNAP_SIZE, &h_proto, sizeof(u16));
+
+ return SNAP_SIZE + sizeof(u16);
+}
+
+static int ieee80211_encrypt_fragment(struct ieee80211_device *ieee,
+ struct sk_buff *frag, int hdr_len)
+{
+ struct lib80211_crypt_data *crypt =
+ ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
+ int res;
+
+ if (crypt == NULL)
+ return -1;
+
+ /* To encrypt, frame format is:
+ * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */
+ atomic_inc(&crypt->refcnt);
+ res = 0;
+ if (crypt->ops && crypt->ops->encrypt_mpdu)
+ res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv);
+
+ atomic_dec(&crypt->refcnt);
+ if (res < 0) {
+ printk(KERN_INFO "%s: Encryption failed: len=%d.\n",
+ ieee->dev->name, frag->len);
+ ieee->ieee_stats.tx_discards++;
+ return -1;
+ }
+
+ return 0;
+}
+
+void ieee80211_txb_free(struct ieee80211_txb *txb)
+{
+ int i;
+ if (unlikely(!txb))
+ return;
+ for (i = 0; i < txb->nr_frags; i++)
+ if (txb->fragments[i])
+ dev_kfree_skb_any(txb->fragments[i]);
+ kfree(txb);
+}
+
+static struct ieee80211_txb *ieee80211_alloc_txb(int nr_frags, int txb_size,
+ int headroom, gfp_t gfp_mask)
+{
+ struct ieee80211_txb *txb;
+ int i;
+ txb = kmalloc(sizeof(struct ieee80211_txb) + (sizeof(u8 *) * nr_frags),
+ gfp_mask);
+ if (!txb)
+ return NULL;
+
+ memset(txb, 0, sizeof(struct ieee80211_txb));
+ txb->nr_frags = nr_frags;
+ txb->frag_size = txb_size;
+
+ for (i = 0; i < nr_frags; i++) {
+ txb->fragments[i] = __dev_alloc_skb(txb_size + headroom,
+ gfp_mask);
+ if (unlikely(!txb->fragments[i])) {
+ i--;
+ break;
+ }
+ skb_reserve(txb->fragments[i], headroom);
+ }
+ if (unlikely(i != nr_frags)) {
+ while (i >= 0)
+ dev_kfree_skb_any(txb->fragments[i--]);
+ kfree(txb);
+ return NULL;
+ }
+ return txb;
+}
+
+static int ieee80211_classify(struct sk_buff *skb)
+{
+ struct ethhdr *eth;
+ struct iphdr *ip;
+
+ eth = (struct ethhdr *)skb->data;
+ if (eth->h_proto != htons(ETH_P_IP))
+ return 0;
+
+ ip = ip_hdr(skb);
+ switch (ip->tos & 0xfc) {
+ case 0x20:
+ return 2;
+ case 0x40:
+ return 1;
+ case 0x60:
+ return 3;
+ case 0x80:
+ return 4;
+ case 0xa0:
+ return 5;
+ case 0xc0:
+ return 6;
+ case 0xe0:
+ return 7;
+ default:
+ return 0;
+ }
+}
+
+/* Incoming skb is converted to a txb which consists of
+ * a block of 802.11 fragment packets (stored as skbs) */
+int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct ieee80211_device *ieee = netdev_priv(dev);
+ struct ieee80211_txb *txb = NULL;
+ struct ieee80211_hdr_3addrqos *frag_hdr;
+ int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size,
+ rts_required;
+ unsigned long flags;
+ struct net_device_stats *stats = &ieee->stats;
+ int encrypt, host_encrypt, host_encrypt_msdu, host_build_iv;
+ __be16 ether_type;
+ int bytes, fc, hdr_len;
+ struct sk_buff *skb_frag;
+ struct ieee80211_hdr_3addrqos header = {/* Ensure zero initialized */
+ .duration_id = 0,
+ .seq_ctl = 0,
+ .qos_ctl = 0
+ };
+ u8 dest[ETH_ALEN], src[ETH_ALEN];
+ struct lib80211_crypt_data *crypt;
+ int priority = skb->priority;
+ int snapped = 0;
+
+ if (ieee->is_queue_full && (*ieee->is_queue_full) (dev, priority))
+ return NETDEV_TX_BUSY;
+
+ spin_lock_irqsave(&ieee->lock, flags);
+
+ /* If there is no driver handler to take the TXB, dont' bother
+ * creating it... */
+ if (!ieee->hard_start_xmit) {
+ printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name);
+ goto success;
+ }
+
+ if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) {
+ printk(KERN_WARNING "%s: skb too small (%d).\n",
+ ieee->dev->name, skb->len);
+ goto success;
+ }
+
+ ether_type = ((struct ethhdr *)skb->data)->h_proto;
+
+ crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx];
+
+ encrypt = !(ether_type == htons(ETH_P_PAE) && ieee->ieee802_1x) &&
+ ieee->sec.encrypt;
+
+ host_encrypt = ieee->host_encrypt && encrypt && crypt;
+ host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt && crypt;
+ host_build_iv = ieee->host_build_iv && encrypt && crypt;
+
+ if (!encrypt && ieee->ieee802_1x &&
+ ieee->drop_unencrypted && ether_type != htons(ETH_P_PAE)) {
+ stats->tx_dropped++;
+ goto success;
+ }
+
+ /* Save source and destination addresses */
+ skb_copy_from_linear_data(skb, dest, ETH_ALEN);
+ skb_copy_from_linear_data_offset(skb, ETH_ALEN, src, ETH_ALEN);
+
+ if (host_encrypt || host_build_iv)
+ fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA |
+ IEEE80211_FCTL_PROTECTED;
+ else
+ fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA;
+
+ if (ieee->iw_mode == IW_MODE_INFRA) {
+ fc |= IEEE80211_FCTL_TODS;
+ /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */
+ memcpy(header.addr1, ieee->bssid, ETH_ALEN);
+ memcpy(header.addr2, src, ETH_ALEN);
+ memcpy(header.addr3, dest, ETH_ALEN);
+ } else if (ieee->iw_mode == IW_MODE_ADHOC) {
+ /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */
+ memcpy(header.addr1, dest, ETH_ALEN);
+ memcpy(header.addr2, src, ETH_ALEN);
+ memcpy(header.addr3, ieee->bssid, ETH_ALEN);
+ }
+ hdr_len = IEEE80211_3ADDR_LEN;
+
+ if (ieee->is_qos_active && ieee->is_qos_active(dev, skb)) {
+ fc |= IEEE80211_STYPE_QOS_DATA;
+ hdr_len += 2;
+
+ skb->priority = ieee80211_classify(skb);
+ header.qos_ctl |= cpu_to_le16(skb->priority & IEEE80211_QCTL_TID);
+ }
+ header.frame_ctl = cpu_to_le16(fc);
+
+ /* Advance the SKB to the start of the payload */
+ skb_pull(skb, sizeof(struct ethhdr));
+
+ /* Determine total amount of storage required for TXB packets */
+ bytes = skb->len + SNAP_SIZE + sizeof(u16);
+
+ /* Encrypt msdu first on the whole data packet. */
+ if ((host_encrypt || host_encrypt_msdu) &&
+ crypt && crypt->ops && crypt->ops->encrypt_msdu) {
+ int res = 0;
+ int len = bytes + hdr_len + crypt->ops->extra_msdu_prefix_len +
+ crypt->ops->extra_msdu_postfix_len;
+ struct sk_buff *skb_new = dev_alloc_skb(len);
+
+ if (unlikely(!skb_new))
+ goto failed;
+
+ skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len);
+ memcpy(skb_put(skb_new, hdr_len), &header, hdr_len);
+ snapped = 1;
+ ieee80211_copy_snap(skb_put(skb_new, SNAP_SIZE + sizeof(u16)),
+ ether_type);
+ skb_copy_from_linear_data(skb, skb_put(skb_new, skb->len), skb->len);
+ res = crypt->ops->encrypt_msdu(skb_new, hdr_len, crypt->priv);
+ if (res < 0) {
+ IEEE80211_ERROR("msdu encryption failed\n");
+ dev_kfree_skb_any(skb_new);
+ goto failed;
+ }
+ dev_kfree_skb_any(skb);
+ skb = skb_new;
+ bytes += crypt->ops->extra_msdu_prefix_len +
+ crypt->ops->extra_msdu_postfix_len;
+ skb_pull(skb, hdr_len);
+ }
+
+ if (host_encrypt || ieee->host_open_frag) {
+ /* Determine fragmentation size based on destination (multicast
+ * and broadcast are not fragmented) */
+ if (is_multicast_ether_addr(dest) ||
+ is_broadcast_ether_addr(dest))
+ frag_size = MAX_FRAG_THRESHOLD;
+ else
+ frag_size = ieee->fts;
+
+ /* Determine amount of payload per fragment. Regardless of if
+ * this stack is providing the full 802.11 header, one will
+ * eventually be affixed to this fragment -- so we must account
+ * for it when determining the amount of payload space. */
+ bytes_per_frag = frag_size - hdr_len;
+ if (ieee->config &
+ (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
+ bytes_per_frag -= IEEE80211_FCS_LEN;
+
+ /* Each fragment may need to have room for encryptiong
+ * pre/postfix */
+ if (host_encrypt)
+ bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len +
+ crypt->ops->extra_mpdu_postfix_len;
+
+ /* Number of fragments is the total
+ * bytes_per_frag / payload_per_fragment */
+ nr_frags = bytes / bytes_per_frag;
+ bytes_last_frag = bytes % bytes_per_frag;
+ if (bytes_last_frag)
+ nr_frags++;
+ else
+ bytes_last_frag = bytes_per_frag;
+ } else {
+ nr_frags = 1;
+ bytes_per_frag = bytes_last_frag = bytes;
+ frag_size = bytes + hdr_len;
+ }
+
+ rts_required = (frag_size > ieee->rts
+ && ieee->config & CFG_IEEE80211_RTS);
+ if (rts_required)
+ nr_frags++;
+
+ /* When we allocate the TXB we allocate enough space for the reserve
+ * and full fragment bytes (bytes_per_frag doesn't include prefix,
+ * postfix, header, FCS, etc.) */
+ txb = ieee80211_alloc_txb(nr_frags, frag_size,
+ ieee->tx_headroom, GFP_ATOMIC);
+ if (unlikely(!txb)) {
+ printk(KERN_WARNING "%s: Could not allocate TXB\n",
+ ieee->dev->name);
+ goto failed;
+ }
+ txb->encrypted = encrypt;
+ if (host_encrypt)
+ txb->payload_size = frag_size * (nr_frags - 1) +
+ bytes_last_frag;
+ else
+ txb->payload_size = bytes;
+
+ if (rts_required) {
+ skb_frag = txb->fragments[0];
+ frag_hdr =
+ (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
+
+ /*
+ * Set header frame_ctl to the RTS.
+ */
+ header.frame_ctl =
+ cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
+ memcpy(frag_hdr, &header, hdr_len);
+
+ /*
+ * Restore header frame_ctl to the original data setting.
+ */
+ header.frame_ctl = cpu_to_le16(fc);
+
+ if (ieee->config &
+ (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
+ skb_put(skb_frag, 4);
+
+ txb->rts_included = 1;
+ i = 1;
+ } else
+ i = 0;
+
+ for (; i < nr_frags; i++) {
+ skb_frag = txb->fragments[i];
+
+ if (host_encrypt || host_build_iv)
+ skb_reserve(skb_frag,
+ crypt->ops->extra_mpdu_prefix_len);
+
+ frag_hdr =
+ (struct ieee80211_hdr_3addrqos *)skb_put(skb_frag, hdr_len);
+ memcpy(frag_hdr, &header, hdr_len);
+
+ /* If this is not the last fragment, then add the MOREFRAGS
+ * bit to the frame control */
+ if (i != nr_frags - 1) {
+ frag_hdr->frame_ctl =
+ cpu_to_le16(fc | IEEE80211_FCTL_MOREFRAGS);
+ bytes = bytes_per_frag;
+ } else {
+ /* The last fragment takes the remaining length */
+ bytes = bytes_last_frag;
+ }
+
+ if (i == 0 && !snapped) {
+ ieee80211_copy_snap(skb_put
+ (skb_frag, SNAP_SIZE + sizeof(u16)),
+ ether_type);
+ bytes -= SNAP_SIZE + sizeof(u16);
+ }
+
+ skb_copy_from_linear_data(skb, skb_put(skb_frag, bytes), bytes);
+
+ /* Advance the SKB... */
+ skb_pull(skb, bytes);
+
+ /* Encryption routine will move the header forward in order
+ * to insert the IV between the header and the payload */
+ if (host_encrypt)
+ ieee80211_encrypt_fragment(ieee, skb_frag, hdr_len);
+ else if (host_build_iv) {
+ atomic_inc(&crypt->refcnt);
+ if (crypt->ops->build_iv)
+ crypt->ops->build_iv(skb_frag, hdr_len,
+ ieee->sec.keys[ieee->sec.active_key],
+ ieee->sec.key_sizes[ieee->sec.active_key],
+ crypt->priv);
+ atomic_dec(&crypt->refcnt);
+ }
+
+ if (ieee->config &
+ (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS))
+ skb_put(skb_frag, 4);
+ }
+
+ success:
+ spin_unlock_irqrestore(&ieee->lock, flags);
+
+ dev_kfree_skb_any(skb);
+
+ if (txb) {
+ int ret = (*ieee->hard_start_xmit) (txb, dev, priority);
+ if (ret == 0) {
+ stats->tx_packets++;
+ stats->tx_bytes += txb->payload_size;
+ return 0;
+ }
+
+ ieee80211_txb_free(txb);
+ }
+
+ return 0;
+
+ failed:
+ spin_unlock_irqrestore(&ieee->lock, flags);
+ netif_stop_queue(dev);
+ stats->tx_errors++;
+ return 1;
+}
+
+EXPORT_SYMBOL(ieee80211_txb_free);
diff --git a/drivers/net/wireless/ipw2x00/libipw_wx.c b/drivers/net/wireless/ipw2x00/libipw_wx.c
new file mode 100644
index 000000000000..31ea3abfc327
--- /dev/null
+++ b/drivers/net/wireless/ipw2x00/libipw_wx.c
@@ -0,0 +1,760 @@
+/******************************************************************************
+
+ Copyright(c) 2004-2005 Intel Corporation. All rights reserved.
+
+ Portions of this file are based on the WEP enablement code provided by the
+ Host AP project hostap-drivers v0.1.3
+ Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen
+ <j@w1.fi>
+ Copyright (c) 2002-2003, Jouni Malinen <j@w1.fi>
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ 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., 59
+ Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The full GNU General Public License is included in this distribution in the
+ file called LICENSE.
+
+ Contact Information:
+ James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+
+******************************************************************************/
+
+#include <linux/kmod.h>
+#include <linux/module.h>
+#include <linux/jiffies.h>
+
+#include <net/lib80211.h>
+#include <net/ieee80211.h>
+#include <linux/wireless.h>
+
+static const char *ieee80211_modes[] = {
+ "?", "a", "b", "ab", "g", "ag", "bg", "abg"
+};
+
+#define MAX_CUSTOM_LEN 64
+static char *ieee80211_translate_scan(struct ieee80211_device *ieee,
+ char *start, char *stop,
+ struct ieee80211_network *network,
+ struct iw_request_info *info)
+{
+ char custom[MAX_CUSTOM_LEN];
+ char *p;
+ struct iw_event iwe;
+ int i, j;
+ char *current_val; /* For rates */
+ u8 rate;
+
+ /* First entry *MUST* be the AP MAC address */
+ iwe.cmd = SIOCGIWAP;
+ iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+ memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN);
+ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
+
+ /* Remaining entries will be displayed in the order we provide them */
+
+ /* Add the ESSID */
+ iwe.cmd = SIOCGIWESSID;
+ iwe.u.data.flags = 1;
+ iwe.u.data.length = min(network->ssid_len, (u8) 32);
+ start = iwe_stream_add_point(info, start, stop,
+ &iwe, network->ssid);
+
+ /* Add the protocol name */
+ iwe.cmd = SIOCGIWNAME;
+ snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s",
+ ieee80211_modes[network->mode]);
+ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
+
+ /* Add mode */
+ iwe.cmd = SIOCGIWMODE;
+ if (network->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
+ if (network->capability & WLAN_CAPABILITY_ESS)
+ iwe.u.mode = IW_MODE_MASTER;
+ else
+ iwe.u.mode = IW_MODE_ADHOC;
+
+ start = iwe_stream_add_event(info, start, stop,
+ &iwe, IW_EV_UINT_LEN);
+ }
+
+ /* Add channel and frequency */
+ /* Note : userspace automatically computes channel using iwrange */
+ iwe.cmd = SIOCGIWFREQ;
+ iwe.u.freq.m = ieee80211_channel_to_freq(ieee, network->channel);
+ iwe.u.freq.e = 6;
+ iwe.u.freq.i = 0;
+ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN);
+
+ /* Add encryption capability */
+ iwe.cmd = SIOCGIWENCODE;
+ if (network->capability & WLAN_CAPABILITY_PRIVACY)
+ iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+ else
+ iwe.u.data.flags = IW_ENCODE_DISABLED;
+ iwe.u.data.length = 0;
+ start = iwe_stream_add_point(info, start, stop,
+ &iwe, network->ssid);
+
+ /* Add basic and extended rates */
+ /* Rate : stuffing multiple values in a single event require a bit
+ * more of magic - Jean II */
+ current_val = start + iwe_stream_lcp_len(info);
+ iwe.cmd = SIOCGIWRATE;
+ /* Those two flags are ignored... */
+ iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+
+ for (i = 0, j = 0; i < network->rates_len;) {
+ if (j < network->rates_ex_len &&
+ ((network->rates_ex[j] & 0x7F) <
+ (network->rates[i] & 0x7F)))
+ rate = network->rates_ex[j++] & 0x7F;
+ else
+ rate = network->rates[i++] & 0x7F;
+ /* Bit rate given in 500 kb/s units (+ 0x80) */
+ iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
+ /* Add new value to event */
+ current_val = iwe_stream_add_value(info, start, current_val,
+ stop, &iwe, IW_EV_PARAM_LEN);
+ }
+ for (; j < network->rates_ex_len; j++) {
+ rate = network->rates_ex[j] & 0x7F;
+ /* Bit rate given in 500 kb/s units (+ 0x80) */
+ iwe.u.bitrate.value = ((rate & 0x7f) * 500000);
+ /* Add new value to event */
+ current_val = iwe_stream_add_value(info, start, current_val,
+ stop, &iwe, IW_EV_PARAM_LEN);
+ }
+ /* Check if we added any rate */
+ if ((current_val - start) > iwe_stream_lcp_len(info))
+ start = current_val;
+
+ /* Add quality statistics */
+ iwe.cmd = IWEVQUAL;
+ iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED |
+ IW_QUAL_NOISE_UPDATED;
+
+ if (!(network->stats.mask & IEEE80211_STATMASK_RSSI)) {
+ iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID |
+ IW_QUAL_LEVEL_INVALID;
+ iwe.u.qual.qual = 0;
+ } else {
+ if (ieee->perfect_rssi == ieee->worst_rssi)
+ iwe.u.qual.qual = 100;
+ else
+ iwe.u.qual.qual =
+ (100 *
+ (ieee->perfect_rssi - ieee->worst_rssi) *
+ (ieee->perfect_rssi - ieee->worst_rssi) -
+ (ieee->perfect_rssi - network->stats.rssi) *
+ (15 * (ieee->perfect_rssi - ieee->worst_rssi) +
+ 62 * (ieee->perfect_rssi -
+ network->stats.rssi))) /
+ ((ieee->perfect_rssi -
+ ieee->worst_rssi) * (ieee->perfect_rssi -
+ ieee->worst_rssi));
+ if (iwe.u.qual.qual > 100)
+ iwe.u.qual.qual = 100;
+ else if (iwe.u.qual.qual < 1)
+ iwe.u.qual.qual = 0;
+ }
+
+ if (!(network->stats.mask & IEEE80211_STATMASK_NOISE)) {
+ iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID;
+ iwe.u.qual.noise = 0;
+ } else {
+ iwe.u.qual.noise = network->stats.noise;
+ }
+
+ if (!(network->stats.mask & IEEE80211_STATMASK_SIGNAL)) {
+ iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID;
+ iwe.u.qual.level = 0;
+ } else {
+ iwe.u.qual.level = network->stats.signal;
+ }
+
+ start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
+
+ iwe.cmd = IWEVCUSTOM;
+ p = custom;
+
+ iwe.u.data.length = p - custom;
+ if (iwe.u.data.length)
+ start = iwe_stream_add_point(info, start, stop, &iwe, custom);
+
+ memset(&iwe, 0, sizeof(iwe));
+ if (network->wpa_ie_len) {
+ char buf[MAX_WPA_IE_LEN];
+ memcpy(buf, network->wpa_ie, network->wpa_ie_len);
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = network->wpa_ie_len;
+ start = iwe_stream_add_point(info, start, stop, &iwe, buf);
+ }
+
+ memset(&iwe, 0, sizeof(iwe));
+ if (network->rsn_ie_len) {
+ char buf[MAX_WPA_IE_LEN];
+ memcpy(buf, network->rsn_ie, network->rsn_ie_len);
+ iwe.cmd = IWEVGENIE;
+ iwe.u.data.length = network->rsn_ie_len;
+ start = iwe_stream_add_point(info, start, stop, &iwe, buf);
+ }
+
+ /* Add EXTRA: Age to display seconds since last beacon/probe response
+ * for given network. */
+ iwe.cmd = IWEVCUSTOM;
+ p = custom;
+ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom),
+ " Last beacon: %dms ago",
+ jiffies_to_msecs(jiffies - network->last_scanned));
+ iwe.u.data.length = p - custom;
+ if (iwe.u.data.length)
+ start = iwe_stream_add_point(info, start, stop, &iwe, custom);
+
+ /* Add spectrum management information */
+ iwe.cmd = -1;
+ p = custom;
+ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Channel flags: ");
+
+ if (ieee80211_get_channel_flags(ieee, network->channel) &
+ IEEE80211_CH_INVALID) {
+ iwe.cmd = IWEVCUSTOM;
+ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "INVALID ");
+ }
+
+ if (ieee80211_get_channel_flags(ieee, network->channel) &
+ IEEE80211_CH_RADAR_DETECT) {
+ iwe.cmd = IWEVCUSTOM;
+ p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "DFS ");
+ }
+
+ if (iwe.cmd == IWEVCUSTOM) {
+ iwe.u.data.length = p - custom;
+ start = iwe_stream_add_point(info, start, stop, &iwe, custom);
+ }
+
+ return start;
+}
+
+#define SCAN_ITEM_SIZE 128
+
+int ieee80211_wx_get_scan(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct ieee80211_network *network;
+ unsigned long flags;
+ int err = 0;
+
+ char *ev = extra;
+ char *stop = ev + wrqu->data.length;
+ int i = 0;
+ DECLARE_SSID_BUF(ssid);
+
+ IEEE80211_DEBUG_WX("Getting scan\n");
+
+ spin_lock_irqsave(&ieee->lock, flags);
+
+ list_for_each_entry(network, &ieee->network_list, list) {
+ i++;
+ if (stop - ev < SCAN_ITEM_SIZE) {
+ err = -E2BIG;
+ break;
+ }
+
+ if (ieee->scan_age == 0 ||
+ time_after(network->last_scanned + ieee->scan_age, jiffies))
+ ev = ieee80211_translate_scan(ieee, ev, stop, network,
+ info);
+ else
+ IEEE80211_DEBUG_SCAN("Not showing network '%s ("
+ "%pM)' due to age (%dms).\n",
+ print_ssid(ssid, network->ssid,
+ network->ssid_len),
+ network->bssid,
+ jiffies_to_msecs(jiffies -
+ network->
+ last_scanned));
+ }
+
+ spin_unlock_irqrestore(&ieee->lock, flags);
+
+ wrqu->data.length = ev - extra;
+ wrqu->data.flags = 0;
+
+ IEEE80211_DEBUG_WX("exit: %d networks returned.\n", i);
+
+ return err;
+}
+
+int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *keybuf)
+{
+ struct iw_point *erq = &(wrqu->encoding);
+ struct net_device *dev = ieee->dev;
+ struct ieee80211_security sec = {
+ .flags = 0
+ };
+ int i, key, key_provided, len;
+ struct lib80211_crypt_data **crypt;
+ int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv;
+ DECLARE_SSID_BUF(ssid);
+
+ IEEE80211_DEBUG_WX("SET_ENCODE\n");
+
+ key = erq->flags & IW_ENCODE_INDEX;
+ if (key) {
+ if (key > WEP_KEYS)
+ return -EINVAL;
+ key--;
+ key_provided = 1;
+ } else {
+ key_provided = 0;
+ key = ieee->crypt_info.tx_keyidx;
+ }
+
+ IEEE80211_DEBUG_WX("Key: %d [%s]\n", key, key_provided ?
+ "provided" : "default");
+
+ crypt = &ieee->crypt_info.crypt[key];
+
+ if (erq->flags & IW_ENCODE_DISABLED) {
+ if (key_provided && *crypt) {
+ IEEE80211_DEBUG_WX("Disabling encryption on key %d.\n",
+ key);
+ lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
+ } else
+ IEEE80211_DEBUG_WX("Disabling encryption.\n");
+
+ /* Check all the keys to see if any are still configured,
+ * and if no key index was provided, de-init them all */
+ for (i = 0; i < WEP_KEYS; i++) {
+ if (ieee->crypt_info.crypt[i] != NULL) {
+ if (key_provided)
+ break;
+ lib80211_crypt_delayed_deinit(&ieee->crypt_info,
+ &ieee->crypt_info.crypt[i]);
+ }
+ }
+
+ if (i == WEP_KEYS) {
+ sec.enabled = 0;
+ sec.encrypt = 0;
+ sec.level = SEC_LEVEL_0;
+ sec.flags |= SEC_ENABLED | SEC_LEVEL | SEC_ENCRYPT;
+ }
+
+ goto done;
+ }
+
+ sec.enabled = 1;
+ sec.encrypt = 1;
+ sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
+
+ if (*crypt != NULL && (*crypt)->ops != NULL &&
+ strcmp((*crypt)->ops->name, "WEP") != 0) {
+ /* changing to use WEP; deinit previously used algorithm
+ * on this key */
+ lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
+ }
+
+ if (*crypt == NULL && host_crypto) {
+ struct lib80211_crypt_data *new_crypt;
+
+ /* take WEP into use */
+ new_crypt = kzalloc(sizeof(struct lib80211_crypt_data),
+ GFP_KERNEL);
+ if (new_crypt == NULL)
+ return -ENOMEM;
+ new_crypt->ops = lib80211_get_crypto_ops("WEP");
+ if (!new_crypt->ops) {
+ request_module("lib80211_crypt_wep");
+ new_crypt->ops = lib80211_get_crypto_ops("WEP");
+ }
+
+ if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+ new_crypt->priv = new_crypt->ops->init(key);
+
+ if (!new_crypt->ops || !new_crypt->priv) {
+ kfree(new_crypt);
+ new_crypt = NULL;
+
+ printk(KERN_WARNING "%s: could not initialize WEP: "
+ "load module lib80211_crypt_wep\n", dev->name);
+ return -EOPNOTSUPP;
+ }
+ *crypt = new_crypt;
+ }
+
+ /* If a new key was provided, set it up */
+ if (erq->length > 0) {
+#ifdef CONFIG_IEEE80211_DEBUG
+ DECLARE_SSID_BUF(ssid);
+#endif
+
+ len = erq->length <= 5 ? 5 : 13;
+ memcpy(sec.keys[key], keybuf, erq->length);
+ if (len > erq->length)
+ memset(sec.keys[key] + erq->length, 0,
+ len - erq->length);
+ IEEE80211_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n",
+ key, print_ssid(ssid, sec.keys[key], len),
+ erq->length, len);
+ sec.key_sizes[key] = len;
+ if (*crypt)
+ (*crypt)->ops->set_key(sec.keys[key], len, NULL,
+ (*crypt)->priv);
+ sec.flags |= (1 << key);
+ /* This ensures a key will be activated if no key is
+ * explicitly set */
+ if (key == sec.active_key)
+ sec.flags |= SEC_ACTIVE_KEY;
+
+ } else {
+ if (host_crypto) {
+ len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN,
+ NULL, (*crypt)->priv);
+ if (len == 0) {
+ /* Set a default key of all 0 */
+ IEEE80211_DEBUG_WX("Setting key %d to all "
+ "zero.\n", key);
+ memset(sec.keys[key], 0, 13);
+ (*crypt)->ops->set_key(sec.keys[key], 13, NULL,
+ (*crypt)->priv);
+ sec.key_sizes[key] = 13;
+ sec.flags |= (1 << key);
+ }
+ }
+ /* No key data - just set the default TX key index */
+ if (key_provided) {
+ IEEE80211_DEBUG_WX("Setting key %d to default Tx "
+ "key.\n", key);
+ ieee->crypt_info.tx_keyidx = key;
+ sec.active_key = key;
+ sec.flags |= SEC_ACTIVE_KEY;
+ }
+ }
+ if (erq->flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED)) {
+ ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED);
+ sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN :
+ WLAN_AUTH_SHARED_KEY;
+ sec.flags |= SEC_AUTH_MODE;
+ IEEE80211_DEBUG_WX("Auth: %s\n",
+ sec.auth_mode == WLAN_AUTH_OPEN ?
+ "OPEN" : "SHARED KEY");
+ }
+
+ /* For now we just support WEP, so only set that security level...
+ * TODO: When WPA is added this is one place that needs to change */
+ sec.flags |= SEC_LEVEL;
+ sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */
+ sec.encode_alg[key] = SEC_ALG_WEP;
+
+ done:
+ if (ieee->set_security)
+ ieee->set_security(dev, &sec);
+
+ /* Do not reset port if card is in Managed mode since resetting will
+ * generate new IEEE 802.11 authentication which may end up in looping
+ * with IEEE 802.1X. If your hardware requires a reset after WEP
+ * configuration (for example... Prism2), implement the reset_port in
+ * the callbacks structures used to initialize the 802.11 stack. */
+ if (ieee->reset_on_keychange &&
+ ieee->iw_mode != IW_MODE_INFRA &&
+ ieee->reset_port && ieee->reset_port(dev)) {
+ printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int ieee80211_wx_get_encode(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *keybuf)
+{
+ struct iw_point *erq = &(wrqu->encoding);
+ int len, key;
+ struct lib80211_crypt_data *crypt;
+ struct ieee80211_security *sec = &ieee->sec;
+
+ IEEE80211_DEBUG_WX("GET_ENCODE\n");
+
+ key = erq->flags & IW_ENCODE_INDEX;
+ if (key) {
+ if (key > WEP_KEYS)
+ return -EINVAL;
+ key--;
+ } else
+ key = ieee->crypt_info.tx_keyidx;
+
+ crypt = ieee->crypt_info.crypt[key];
+ erq->flags = key + 1;
+
+ if (!sec->enabled) {
+ erq->length = 0;
+ erq->flags |= IW_ENCODE_DISABLED;
+ return 0;
+ }
+
+ len = sec->key_sizes[key];
+ memcpy(keybuf, sec->keys[key], len);
+
+ erq->length = len;
+ erq->flags |= IW_ENCODE_ENABLED;
+
+ if (ieee->open_wep)
+ erq->flags |= IW_ENCODE_OPEN;
+ else
+ erq->flags |= IW_ENCODE_RESTRICTED;
+
+ return 0;
+}
+
+int ieee80211_wx_set_encodeext(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct net_device *dev = ieee->dev;
+ struct iw_point *encoding = &wrqu->encoding;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ int i, idx, ret = 0;
+ int group_key = 0;
+ const char *alg, *module;
+ struct lib80211_crypto_ops *ops;
+ struct lib80211_crypt_data **crypt;
+
+ struct ieee80211_security sec = {
+ .flags = 0,
+ };
+
+ idx = encoding->flags & IW_ENCODE_INDEX;
+ if (idx) {
+ if (idx < 1 || idx > WEP_KEYS)
+ return -EINVAL;
+ idx--;
+ } else
+ idx = ieee->crypt_info.tx_keyidx;
+
+ if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
+ crypt = &ieee->crypt_info.crypt[idx];
+ group_key = 1;
+ } else {
+ /* some Cisco APs use idx>0 for unicast in dynamic WEP */
+ if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP)
+ return -EINVAL;
+ if (ieee->iw_mode == IW_MODE_INFRA)
+ crypt = &ieee->crypt_info.crypt[idx];
+ else
+ return -EINVAL;
+ }
+
+ sec.flags |= SEC_ENABLED | SEC_ENCRYPT;
+ if ((encoding->flags & IW_ENCODE_DISABLED) ||
+ ext->alg == IW_ENCODE_ALG_NONE) {
+ if (*crypt)
+ lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
+
+ for (i = 0; i < WEP_KEYS; i++)
+ if (ieee->crypt_info.crypt[i] != NULL)
+ break;
+
+ if (i == WEP_KEYS) {
+ sec.enabled = 0;
+ sec.encrypt = 0;
+ sec.level = SEC_LEVEL_0;
+ sec.flags |= SEC_LEVEL;
+ }
+ goto done;
+ }
+
+ sec.enabled = 1;
+ sec.encrypt = 1;
+
+ if (group_key ? !ieee->host_mc_decrypt :
+ !(ieee->host_encrypt || ieee->host_decrypt ||
+ ieee->host_encrypt_msdu))
+ goto skip_host_crypt;
+
+ switch (ext->alg) {
+ case IW_ENCODE_ALG_WEP:
+ alg = "WEP";
+ module = "lib80211_crypt_wep";
+ break;
+ case IW_ENCODE_ALG_TKIP:
+ alg = "TKIP";
+ module = "lib80211_crypt_tkip";
+ break;
+ case IW_ENCODE_ALG_CCMP:
+ alg = "CCMP";
+ module = "lib80211_crypt_ccmp";
+ break;
+ default:
+ IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
+ dev->name, ext->alg);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ops = lib80211_get_crypto_ops(alg);
+ if (ops == NULL) {
+ request_module(module);
+ ops = lib80211_get_crypto_ops(alg);
+ }
+ if (ops == NULL) {
+ IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
+ dev->name, ext->alg);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (*crypt == NULL || (*crypt)->ops != ops) {
+ struct lib80211_crypt_data *new_crypt;
+
+ lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt);
+
+ new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
+ if (new_crypt == NULL) {
+ ret = -ENOMEM;
+ goto done;
+ }
+ new_crypt->ops = ops;
+ if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+ new_crypt->priv = new_crypt->ops->init(idx);
+ if (new_crypt->priv == NULL) {
+ kfree(new_crypt);
+ ret = -EINVAL;
+ goto done;
+ }
+ *crypt = new_crypt;
+ }
+
+ if (ext->key_len > 0 && (*crypt)->ops->set_key &&
+ (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq,
+ (*crypt)->priv) < 0) {
+ IEEE80211_DEBUG_WX("%s: key setting failed\n", dev->name);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ skip_host_crypt:
+ if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+ ieee->crypt_info.tx_keyidx = idx;
+ sec.active_key = idx;
+ sec.flags |= SEC_ACTIVE_KEY;
+ }
+
+ if (ext->alg != IW_ENCODE_ALG_NONE) {
+ memcpy(sec.keys[idx], ext->key, ext->key_len);
+ sec.key_sizes[idx] = ext->key_len;
+ sec.flags |= (1 << idx);
+ if (ext->alg == IW_ENCODE_ALG_WEP) {
+ sec.encode_alg[idx] = SEC_ALG_WEP;
+ sec.flags |= SEC_LEVEL;
+ sec.level = SEC_LEVEL_1;
+ } else if (ext->alg == IW_ENCODE_ALG_TKIP) {
+ sec.encode_alg[idx] = SEC_ALG_TKIP;
+ sec.flags |= SEC_LEVEL;
+ sec.level = SEC_LEVEL_2;
+ } else if (ext->alg == IW_ENCODE_ALG_CCMP) {
+ sec.encode_alg[idx] = SEC_ALG_CCMP;
+ sec.flags |= SEC_LEVEL;
+ sec.level = SEC_LEVEL_3;
+ }
+ /* Don't set sec level for group keys. */
+ if (group_key)
+ sec.flags &= ~SEC_LEVEL;
+ }
+ done:
+ if (ieee->set_security)
+ ieee->set_security(ieee->dev, &sec);
+
+ /*
+ * Do not reset port if card is in Managed mode since resetting will
+ * generate new IEEE 802.11 authentication which may end up in looping
+ * with IEEE 802.1X. If your hardware requires a reset after WEP
+ * configuration (for example... Prism2), implement the reset_port in
+ * the callbacks structures used to initialize the 802.11 stack.
+ */
+ if (ieee->reset_on_keychange &&
+ ieee->iw_mode != IW_MODE_INFRA &&
+ ieee->reset_port && ieee->reset_port(dev)) {
+ IEEE80211_DEBUG_WX("%s: reset_port failed\n", dev->name);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+int ieee80211_wx_get_encodeext(struct ieee80211_device *ieee,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra)
+{
+ struct iw_point *encoding = &wrqu->encoding;
+ struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+ struct ieee80211_security *sec = &ieee->sec;
+ int idx, max_key_len;
+
+ max_key_len = encoding->length - sizeof(*ext);
+ if (max_key_len < 0)
+ return -EINVAL;
+
+ idx = encoding->flags & IW_ENCODE_INDEX;
+ if (idx) {
+ if (idx < 1 || idx > WEP_KEYS)
+ return -EINVAL;
+ idx--;
+ } else
+ idx = ieee->crypt_info.tx_keyidx;
+
+ if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) &&
+ ext->alg != IW_ENCODE_ALG_WEP)
+ if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA)
+ return -EINVAL;
+
+ encoding->flags = idx + 1;
+ memset(ext, 0, sizeof(*ext));
+
+ if (!sec->enabled) {
+ ext->alg = IW_ENCODE_ALG_NONE;
+ ext->key_len = 0;
+ encoding->flags |= IW_ENCODE_DISABLED;
+ } else {
+ if (sec->encode_alg[idx] == SEC_ALG_WEP)
+ ext->alg = IW_ENCODE_ALG_WEP;
+ else if (sec->encode_alg[idx] == SEC_ALG_TKIP)
+ ext->alg = IW_ENCODE_ALG_TKIP;
+ else if (sec->encode_alg[idx] == SEC_ALG_CCMP)
+ ext->alg = IW_ENCODE_ALG_CCMP;
+ else
+ return -EINVAL;
+
+ ext->key_len = sec->key_sizes[idx];
+ memcpy(ext->key, sec->keys[idx], ext->key_len);
+ encoding->flags |= IW_ENCODE_ENABLED;
+ if (ext->key_len &&
+ (ext->alg == IW_ENCODE_ALG_TKIP ||
+ ext->alg == IW_ENCODE_ALG_CCMP))
+ ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID;
+
+ }
+
+ return 0;
+}
+
+EXPORT_SYMBOL(ieee80211_wx_set_encodeext);
+EXPORT_SYMBOL(ieee80211_wx_get_encodeext);
+
+EXPORT_SYMBOL(ieee80211_wx_get_scan);
+EXPORT_SYMBOL(ieee80211_wx_set_encode);
+EXPORT_SYMBOL(ieee80211_wx_get_encode);
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index b0ac0ce3fb9f..47bee0ee0a7c 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -4,6 +4,7 @@ config IWLWIFI
config IWLCORE
tristate "Intel Wireless Wifi Core"
depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
+ select LIB80211
select IWLWIFI
select MAC80211_LEDS if IWLWIFI_LEDS
select LEDS_CLASS if IWLWIFI_LEDS
@@ -105,6 +106,7 @@ config IWL3945
tristate "Intel PRO/Wireless 3945ABG/BG Network Connection"
depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL
select FW_LOADER
+ select LIB80211
select IWLWIFI
select MAC80211_LEDS if IWL3945_LEDS
select LEDS_CLASS if IWL3945_LEDS
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile
index 47aa28f6a513..0be9e6b66aa0 100644
--- a/drivers/net/wireless/iwlwifi/Makefile
+++ b/drivers/net/wireless/iwlwifi/Makefile
@@ -5,9 +5,10 @@ iwlcore-objs += iwl-scan.o
iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o
iwlcore-$(CONFIG_IWLWIFI_RFKILL) += iwl-rfkill.o
+iwlcore-$(CONFIG_IWLAGN_SPECTRUM_MEASUREMENT) += iwl-spectrum.o
obj-$(CONFIG_IWLAGN) += iwlagn.o
-iwlagn-objs := iwl-agn.o iwl-agn-rs.o
+iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-hcmd-check.o
iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
iwlagn-$(CONFIG_IWL5000) += iwl-5000.o
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h
index 817ece773643..c6f4eb54a2b1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-commands.h
@@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@@ -69,6 +69,12 @@
#ifndef __iwl_3945_commands_h__
#define __iwl_3945_commands_h__
+/* uCode version contains 4 values: Major/Minor/API/Serial */
+#define IWL_UCODE_MAJOR(ver) (((ver) & 0xFF000000) >> 24)
+#define IWL_UCODE_MINOR(ver) (((ver) & 0x00FF0000) >> 16)
+#define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8)
+#define IWL_UCODE_SERIAL(ver) ((ver) & 0x000000FF)
+
enum {
REPLY_ALIVE = 0x1,
REPLY_ERROR = 0x2,
@@ -121,7 +127,7 @@ enum {
REPLY_TX_PWR_TABLE_CMD = 0x97,
MEASURE_ABORT_NOTIFICATION = 0x99, /* not used */
- /* Bluetooth device coexistance config command */
+ /* Bluetooth device coexistence config command */
REPLY_BT_CONFIG = 0x9b,
/* Statistics */
@@ -158,7 +164,7 @@ struct iwl3945_cmd_header {
u8 cmd; /* Command ID: REPLY_RXON, etc. */
u8 flags; /* IWL_CMD_* */
/*
- * The driver sets up the sequence number to values of its chosing.
+ * The driver sets up the sequence number to values of its choosing.
* uCode does not use this value, but passes it back to the driver
* when sending the response to each driver-originated command, so
* the driver can match the response to the command. Since the values
@@ -220,7 +226,7 @@ struct iwl3945_power_per_rate {
*
*****************************************************************************/
-#define UCODE_VALID_OK __constant_cpu_to_le32(0x1)
+#define UCODE_VALID_OK cpu_to_le32(0x1)
#define INITIALIZE_SUBTYPE (9)
/*
@@ -322,42 +328,42 @@ enum {
/* rx_config flags */
/* band & modulation selection */
-#define RXON_FLG_BAND_24G_MSK __constant_cpu_to_le32(1 << 0)
-#define RXON_FLG_CCK_MSK __constant_cpu_to_le32(1 << 1)
+#define RXON_FLG_BAND_24G_MSK cpu_to_le32(1 << 0)
+#define RXON_FLG_CCK_MSK cpu_to_le32(1 << 1)
/* auto detection enable */
-#define RXON_FLG_AUTO_DETECT_MSK __constant_cpu_to_le32(1 << 2)
+#define RXON_FLG_AUTO_DETECT_MSK cpu_to_le32(1 << 2)
/* TGg protection when tx */
-#define RXON_FLG_TGG_PROTECT_MSK __constant_cpu_to_le32(1 << 3)
+#define RXON_FLG_TGG_PROTECT_MSK cpu_to_le32(1 << 3)
/* cck short slot & preamble */
-#define RXON_FLG_SHORT_SLOT_MSK __constant_cpu_to_le32(1 << 4)
-#define RXON_FLG_SHORT_PREAMBLE_MSK __constant_cpu_to_le32(1 << 5)
+#define RXON_FLG_SHORT_SLOT_MSK cpu_to_le32(1 << 4)
+#define RXON_FLG_SHORT_PREAMBLE_MSK cpu_to_le32(1 << 5)
/* antenna selection */
-#define RXON_FLG_DIS_DIV_MSK __constant_cpu_to_le32(1 << 7)
-#define RXON_FLG_ANT_SEL_MSK __constant_cpu_to_le32(0x0f00)
-#define RXON_FLG_ANT_A_MSK __constant_cpu_to_le32(1 << 8)
-#define RXON_FLG_ANT_B_MSK __constant_cpu_to_le32(1 << 9)
+#define RXON_FLG_DIS_DIV_MSK cpu_to_le32(1 << 7)
+#define RXON_FLG_ANT_SEL_MSK cpu_to_le32(0x0f00)
+#define RXON_FLG_ANT_A_MSK cpu_to_le32(1 << 8)
+#define RXON_FLG_ANT_B_MSK cpu_to_le32(1 << 9)
/* radar detection enable */
-#define RXON_FLG_RADAR_DETECT_MSK __constant_cpu_to_le32(1 << 12)
-#define RXON_FLG_TGJ_NARROW_BAND_MSK __constant_cpu_to_le32(1 << 13)
+#define RXON_FLG_RADAR_DETECT_MSK cpu_to_le32(1 << 12)
+#define RXON_FLG_TGJ_NARROW_BAND_MSK cpu_to_le32(1 << 13)
/* rx response to host with 8-byte TSF
* (according to ON_AIR deassertion) */
-#define RXON_FLG_TSF2HOST_MSK __constant_cpu_to_le32(1 << 15)
+#define RXON_FLG_TSF2HOST_MSK cpu_to_le32(1 << 15)
/* rx_config filter flags */
/* accept all data frames */
-#define RXON_FILTER_PROMISC_MSK __constant_cpu_to_le32(1 << 0)
+#define RXON_FILTER_PROMISC_MSK cpu_to_le32(1 << 0)
/* pass control & management to host */
-#define RXON_FILTER_CTL2HOST_MSK __constant_cpu_to_le32(1 << 1)
+#define RXON_FILTER_CTL2HOST_MSK cpu_to_le32(1 << 1)
/* accept multi-cast */
-#define RXON_FILTER_ACCEPT_GRP_MSK __constant_cpu_to_le32(1 << 2)
+#define RXON_FILTER_ACCEPT_GRP_MSK cpu_to_le32(1 << 2)
/* don't decrypt uni-cast frames */
-#define RXON_FILTER_DIS_DECRYPT_MSK __constant_cpu_to_le32(1 << 3)
+#define RXON_FILTER_DIS_DECRYPT_MSK cpu_to_le32(1 << 3)
/* don't decrypt multi-cast frames */
-#define RXON_FILTER_DIS_GRP_DECRYPT_MSK __constant_cpu_to_le32(1 << 4)
+#define RXON_FILTER_DIS_GRP_DECRYPT_MSK cpu_to_le32(1 << 4)
/* STA is associated */
-#define RXON_FILTER_ASSOC_MSK __constant_cpu_to_le32(1 << 5)
+#define RXON_FILTER_ASSOC_MSK cpu_to_le32(1 << 5)
/* transfer to host non bssid beacons in associated state */
-#define RXON_FILTER_BCON_AWARE_MSK __constant_cpu_to_le32(1 << 6)
+#define RXON_FILTER_BCON_AWARE_MSK cpu_to_le32(1 << 6)
/**
* REPLY_RXON = 0x10 (command, has simple generic response)
@@ -471,9 +477,9 @@ struct iwl3945_ac_qos {
} __attribute__ ((packed));
/* QoS flags defines */
-#define QOS_PARAM_FLG_UPDATE_EDCA_MSK __constant_cpu_to_le32(0x01)
-#define QOS_PARAM_FLG_TGN_MSK __constant_cpu_to_le32(0x02)
-#define QOS_PARAM_FLG_TXOP_TYPE_MSK __constant_cpu_to_le32(0x10)
+#define QOS_PARAM_FLG_UPDATE_EDCA_MSK cpu_to_le32(0x01)
+#define QOS_PARAM_FLG_TGN_MSK cpu_to_le32(0x02)
+#define QOS_PARAM_FLG_TXOP_TYPE_MSK cpu_to_le32(0x10)
/* Number of Access Categories (AC) (EDCA), queues 0..3 */
#define AC_NUM 4
@@ -508,27 +514,27 @@ struct iwl3945_qosparam_cmd {
#define IWL_STATION_COUNT 32 /* MAX(3945,4965)*/
#define IWL_INVALID_STATION 255
-#define STA_FLG_TX_RATE_MSK __constant_cpu_to_le32(1 << 2);
-#define STA_FLG_PWR_SAVE_MSK __constant_cpu_to_le32(1 << 8);
+#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2);
+#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8);
/* Use in mode field. 1: modify existing entry, 0: add new station entry */
#define STA_CONTROL_MODIFY_MSK 0x01
/* key flags __le16*/
-#define STA_KEY_FLG_ENCRYPT_MSK __constant_cpu_to_le16(0x0007)
-#define STA_KEY_FLG_NO_ENC __constant_cpu_to_le16(0x0000)
-#define STA_KEY_FLG_WEP __constant_cpu_to_le16(0x0001)
-#define STA_KEY_FLG_CCMP __constant_cpu_to_le16(0x0002)
-#define STA_KEY_FLG_TKIP __constant_cpu_to_le16(0x0003)
+#define STA_KEY_FLG_ENCRYPT_MSK cpu_to_le16(0x0007)
+#define STA_KEY_FLG_NO_ENC cpu_to_le16(0x0000)
+#define STA_KEY_FLG_WEP cpu_to_le16(0x0001)
+#define STA_KEY_FLG_CCMP cpu_to_le16(0x0002)
+#define STA_KEY_FLG_TKIP cpu_to_le16(0x0003)
#define STA_KEY_FLG_KEYID_POS 8
-#define STA_KEY_FLG_INVALID __constant_cpu_to_le16(0x0800)
+#define STA_KEY_FLG_INVALID cpu_to_le16(0x0800)
/* wep key is either from global key (0) or from station info array (1) */
-#define STA_KEY_FLG_WEP_KEY_MAP_MSK __constant_cpu_to_le16(0x0008)
+#define STA_KEY_FLG_WEP_KEY_MAP_MSK cpu_to_le16(0x0008)
/* wep key in STA: 5-bytes (0) or 13-bytes (1) */
-#define STA_KEY_FLG_KEY_SIZE_MSK __constant_cpu_to_le16(0x1000)
-#define STA_KEY_MULTICAST_MSK __constant_cpu_to_le16(0x4000)
+#define STA_KEY_FLG_KEY_SIZE_MSK cpu_to_le16(0x1000)
+#define STA_KEY_MULTICAST_MSK cpu_to_le16(0x4000)
/* Flags indicate whether to modify vs. don't change various station params */
#define STA_MODIFY_KEY_MASK 0x01
@@ -666,14 +672,14 @@ struct iwl3945_rx_frame_hdr {
u8 payload[0];
} __attribute__ ((packed));
-#define RX_RES_STATUS_NO_CRC32_ERROR __constant_cpu_to_le32(1 << 0)
-#define RX_RES_STATUS_NO_RXE_OVERFLOW __constant_cpu_to_le32(1 << 1)
+#define RX_RES_STATUS_NO_CRC32_ERROR cpu_to_le32(1 << 0)
+#define RX_RES_STATUS_NO_RXE_OVERFLOW cpu_to_le32(1 << 1)
-#define RX_RES_PHY_FLAGS_BAND_24_MSK __constant_cpu_to_le16(1 << 0)
-#define RX_RES_PHY_FLAGS_MOD_CCK_MSK __constant_cpu_to_le16(1 << 1)
-#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK __constant_cpu_to_le16(1 << 2)
-#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK __constant_cpu_to_le16(1 << 3)
-#define RX_RES_PHY_FLAGS_ANTENNA_MSK __constant_cpu_to_le16(0xf0)
+#define RX_RES_PHY_FLAGS_BAND_24_MSK cpu_to_le16(1 << 0)
+#define RX_RES_PHY_FLAGS_MOD_CCK_MSK cpu_to_le16(1 << 1)
+#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK cpu_to_le16(1 << 2)
+#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK cpu_to_le16(1 << 3)
+#define RX_RES_PHY_FLAGS_ANTENNA_MSK cpu_to_le16(0xf0)
#define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8)
#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8)
@@ -733,57 +739,57 @@ struct iwl3945_rx_frame {
/* 1: Use Request-To-Send protocol before this frame.
* Mutually exclusive vs. TX_CMD_FLG_CTS_MSK. */
-#define TX_CMD_FLG_RTS_MSK __constant_cpu_to_le32(1 << 1)
+#define TX_CMD_FLG_RTS_MSK cpu_to_le32(1 << 1)
/* 1: Transmit Clear-To-Send to self before this frame.
* Driver should set this for AUTH/DEAUTH/ASSOC-REQ/REASSOC mgmnt frames.
* Mutually exclusive vs. TX_CMD_FLG_RTS_MSK. */
-#define TX_CMD_FLG_CTS_MSK __constant_cpu_to_le32(1 << 2)
+#define TX_CMD_FLG_CTS_MSK cpu_to_le32(1 << 2)
/* 1: Expect ACK from receiving station
* 0: Don't expect ACK (MAC header's duration field s/b 0)
* Set this for unicast frames, but not broadcast/multicast. */
-#define TX_CMD_FLG_ACK_MSK __constant_cpu_to_le32(1 << 3)
+#define TX_CMD_FLG_ACK_MSK cpu_to_le32(1 << 3)
/* 1: Use rate scale table (see REPLY_TX_LINK_QUALITY_CMD).
* Tx command's initial_rate_index indicates first rate to try;
* uCode walks through table for additional Tx attempts.
* 0: Use Tx rate/MCS from Tx command's rate_n_flags field.
* This rate will be used for all Tx attempts; it will not be scaled. */
-#define TX_CMD_FLG_STA_RATE_MSK __constant_cpu_to_le32(1 << 4)
+#define TX_CMD_FLG_STA_RATE_MSK cpu_to_le32(1 << 4)
/* 1: Expect immediate block-ack.
* Set when Txing a block-ack request frame. Also set TX_CMD_FLG_ACK_MSK. */
-#define TX_CMD_FLG_IMM_BA_RSP_MASK __constant_cpu_to_le32(1 << 6)
+#define TX_CMD_FLG_IMM_BA_RSP_MASK cpu_to_le32(1 << 6)
/* 1: Frame requires full Tx-Op protection.
* Set this if either RTS or CTS Tx Flag gets set. */
-#define TX_CMD_FLG_FULL_TXOP_PROT_MSK __constant_cpu_to_le32(1 << 7)
+#define TX_CMD_FLG_FULL_TXOP_PROT_MSK cpu_to_le32(1 << 7)
/* Tx antenna selection field; used only for 3945, reserved (0) for 4965.
* Set field to "0" to allow 3945 uCode to select antenna (normal usage). */
-#define TX_CMD_FLG_ANT_SEL_MSK __constant_cpu_to_le32(0xf00)
-#define TX_CMD_FLG_ANT_A_MSK __constant_cpu_to_le32(1 << 8)
-#define TX_CMD_FLG_ANT_B_MSK __constant_cpu_to_le32(1 << 9)
+#define TX_CMD_FLG_ANT_SEL_MSK cpu_to_le32(0xf00)
+#define TX_CMD_FLG_ANT_A_MSK cpu_to_le32(1 << 8)
+#define TX_CMD_FLG_ANT_B_MSK cpu_to_le32(1 << 9)
/* 1: Ignore Bluetooth priority for this frame.
* 0: Delay Tx until Bluetooth device is done (normal usage). */
-#define TX_CMD_FLG_BT_DIS_MSK __constant_cpu_to_le32(1 << 12)
+#define TX_CMD_FLG_BT_DIS_MSK cpu_to_le32(1 << 12)
/* 1: uCode overrides sequence control field in MAC header.
* 0: Driver provides sequence control field in MAC header.
* Set this for management frames, non-QOS data frames, non-unicast frames,
* and also in Tx command embedded in REPLY_SCAN_CMD for active scans. */
-#define TX_CMD_FLG_SEQ_CTL_MSK __constant_cpu_to_le32(1 << 13)
+#define TX_CMD_FLG_SEQ_CTL_MSK cpu_to_le32(1 << 13)
/* 1: This frame is non-last MPDU; more fragments are coming.
* 0: Last fragment, or not using fragmentation. */
-#define TX_CMD_FLG_MORE_FRAG_MSK __constant_cpu_to_le32(1 << 14)
+#define TX_CMD_FLG_MORE_FRAG_MSK cpu_to_le32(1 << 14)
/* 1: uCode calculates and inserts Timestamp Function (TSF) in outgoing frame.
* 0: No TSF required in outgoing frame.
* Set this for transmitting beacons and probe responses. */
-#define TX_CMD_FLG_TSF_MSK __constant_cpu_to_le32(1 << 16)
+#define TX_CMD_FLG_TSF_MSK cpu_to_le32(1 << 16)
/* 1: Driver inserted 2 bytes pad after the MAC header, for (required) dword
* alignment of frame's payload data field.
@@ -791,10 +797,10 @@ struct iwl3945_rx_frame {
* Set this for MAC headers with 26 or 30 bytes, i.e. those with QOS or ADDR4
* field (but not both). Driver must align frame data (i.e. data following
* MAC header) to DWORD boundary. */
-#define TX_CMD_FLG_MH_PAD_MSK __constant_cpu_to_le32(1 << 20)
+#define TX_CMD_FLG_MH_PAD_MSK cpu_to_le32(1 << 20)
/* HCCA-AP - disable duration overwriting. */
-#define TX_CMD_FLG_DUR_MSK __constant_cpu_to_le32(1 << 25)
+#define TX_CMD_FLG_DUR_MSK cpu_to_le32(1 << 25)
/*
* TX command security control
@@ -991,7 +997,7 @@ struct iwl3945_rate_scaling_cmd {
*
* 3945 and 4965 support hardware handshake with Bluetooth device on
* same platform. Bluetooth device alerts wireless device when it will Tx;
- * wireless device can delay or kill its own Tx to accomodate.
+ * wireless device can delay or kill its own Tx to accommodate.
*/
struct iwl3945_bt_cmd {
u8 flags;
@@ -1158,9 +1164,9 @@ struct iwl3945_spectrum_notification {
*/
#define IWL_POWER_VEC_SIZE 5
-#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK __constant_cpu_to_le32(1 << 0)
-#define IWL_POWER_SLEEP_OVER_DTIM_MSK __constant_cpu_to_le32(1 << 2)
-#define IWL_POWER_PCI_PM_MSK __constant_cpu_to_le32(1 << 3)
+#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK cpu_to_le32(1 << 0)
+#define IWL_POWER_SLEEP_OVER_DTIM_MSK cpu_to_le32(1 << 2)
+#define IWL_POWER_PCI_PM_MSK cpu_to_le32(1 << 3)
struct iwl3945_powertable_cmd {
__le32 flags;
__le32 rx_data_timeout;
@@ -1278,8 +1284,8 @@ struct iwl3945_ssid_ie {
} __attribute__ ((packed));
#define PROBE_OPTION_MAX 0x4
-#define TX_CMD_LIFE_TIME_INFINITE __constant_cpu_to_le32(0xFFFFFFFF)
-#define IWL_GOOD_CRC_TH __constant_cpu_to_le16(1)
+#define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF)
+#define IWL_GOOD_CRC_TH cpu_to_le16(1)
#define IWL_MAX_SCAN_SIZE 1024
/*
@@ -1379,7 +1385,7 @@ struct iwl3945_scan_cmd {
} __attribute__ ((packed));
/* Can abort will notify by complete notification with abort status. */
-#define CAN_ABORT_STATUS __constant_cpu_to_le32(0x1)
+#define CAN_ABORT_STATUS cpu_to_le32(0x1)
/* complete notification statuses */
#define ABORT_STATUS 0x2
@@ -1572,8 +1578,8 @@ struct statistics_general {
* STATISTICS_NOTIFICATIONs after received beacons (see below). This flag
* does not affect the response to the REPLY_STATISTICS_CMD 0x9c itself.
*/
-#define IWL_STATS_CONF_CLEAR_STATS __constant_cpu_to_le32(0x1) /* see above */
-#define IWL_STATS_CONF_DISABLE_NOTIF __constant_cpu_to_le32(0x2)/* see above */
+#define IWL_STATS_CONF_CLEAR_STATS cpu_to_le32(0x1) /* see above */
+#define IWL_STATS_CONF_DISABLE_NOTIF cpu_to_le32(0x2)/* see above */
struct iwl3945_statistics_cmd {
__le32 configuration_flags; /* IWL_STATS_CONF_* */
} __attribute__ ((packed));
@@ -1593,8 +1599,8 @@ struct iwl3945_statistics_cmd {
* appropriately so that each notification contains statistics for only the
* one channel that has just been scanned.
*/
-#define STATISTICS_REPLY_FLG_BAND_24G_MSK __constant_cpu_to_le32(0x2)
-#define STATISTICS_REPLY_FLG_FAT_MODE_MSK __constant_cpu_to_le32(0x8)
+#define STATISTICS_REPLY_FLG_BAND_24G_MSK cpu_to_le32(0x2)
+#define STATISTICS_REPLY_FLG_FAT_MODE_MSK cpu_to_le32(0x8)
struct iwl3945_notif_statistics {
__le32 flag;
struct statistics_rx rx;
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-core.h b/drivers/net/wireless/iwlwifi/iwl-3945-core.h
index bc12f97ba0b1..6f463555402c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-core.h
@@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
- * Tomas Winkler <tomas.winkler@intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@@ -71,9 +71,33 @@
#define IWL_SKU_G 0x1
#define IWL_SKU_A 0x2
+/**
+ * struct iwl_3945_cfg
+ * @fw_name_pre: Firmware filename prefix. The api version and extension
+ * (.ucode) will be added to filename before loading from disk. The
+ * filename is constructed as fw_name_pre<api>.ucode.
+ * @ucode_api_max: Highest version of uCode API supported by driver.
+ * @ucode_api_min: Lowest version of uCode API supported by driver.
+ *
+ * We enable the driver to be backward compatible wrt API version. The
+ * driver specifies which APIs it supports (with @ucode_api_max being the
+ * highest and @ucode_api_min the lowest). Firmware will only be loaded if
+ * it has a supported API version. The firmware's API version will be
+ * stored in @iwl_priv, enabling the driver to make runtime changes based
+ * on firmware version used.
+ *
+ * For example,
+ * if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
+ * Driver interacts with Firmware API version >= 2.
+ * } else {
+ * Driver interacts with Firmware API version 1.
+ * }
+ */
struct iwl_3945_cfg {
const char *name;
- const char *fw_name;
+ const char *fw_name_pre;
+ const unsigned int ucode_api_max;
+ const unsigned int ucode_api_min;
unsigned int sku;
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-debug.h b/drivers/net/wireless/iwlwifi/iwl-3945-debug.h
index 33016fb5e9b3..85eb778f9df1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-debug.h
@@ -21,7 +21,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
index 644bd9e08052..94ea0e60c410 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
@@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@@ -103,7 +103,6 @@
* Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG.
*/
#define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */
-#define IWL_EEPROM_ACCESS_DELAY 10 /* uSec */
/*
* Regulatory channel usage flags in EEPROM struct iwl_eeprom_channel.flags.
@@ -321,6 +320,7 @@ struct iwl3945_eeprom {
/* RSSR */
#define FH_RSSR_CTRL (FH_RSSR_TABLE+0x000)
#define FH_RSSR_STATUS (FH_RSSR_TABLE+0x004)
+#define FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (0x01000000)
/* TCSR */
#define FH_TCSR(_channel) (FH_TCSR_TABLE+(_channel)*0x20)
#define FH_TCSR_CONFIG(_channel) (FH_TCSR(_channel)+0x00)
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-io.h b/drivers/net/wireless/iwlwifi/iwl-3945-io.h
index b3fe48de3ae7..2440fd664dd5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-io.h
@@ -21,7 +21,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -53,7 +53,7 @@
* _iwl3945_read32.)
*
* These declarations are *extremely* useful in quickly isolating code deltas
- * which result in misconfiguring of the hardware I/O. In combination with
+ * which result in misconfiguration of the hardware I/O. In combination with
* git-bisect and the IO debug level you can quickly determine the specific
* commit which breaks the IO sequence to the hardware.
*
@@ -93,7 +93,7 @@ static inline int _iwl3945_poll_bit(struct iwl3945_priv *priv, u32 addr,
do {
if ((_iwl3945_read32(priv, addr) & mask) == (bits & mask))
return i;
- mdelay(10);
+ udelay(10);
i += 10;
} while (i < timeout);
@@ -107,7 +107,7 @@ static inline int __iwl3945_poll_bit(const char *f, u32 l,
int ret = _iwl3945_poll_bit(priv, addr, bits, mask, timeout);
IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n",
addr, bits, mask,
- unlikely(ret == -ETIMEDOUT)?"timeout":"", f, l);
+ unlikely(ret == -ETIMEDOUT) ? "timeout" : "", f, l);
return ret;
}
#define iwl3945_poll_bit(priv, addr, bits, mask, timeout) \
@@ -271,16 +271,7 @@ static inline void iwl3945_write_reg_buf(struct iwl3945_priv *priv,
static inline int _iwl3945_poll_direct_bit(struct iwl3945_priv *priv,
u32 addr, u32 mask, int timeout)
{
- int i = 0;
-
- do {
- if ((_iwl3945_read_direct32(priv, addr) & mask) == mask)
- return i;
- mdelay(10);
- i += 10;
- } while (i < timeout);
-
- return -ETIMEDOUT;
+ return _iwl3945_poll_bit(priv, addr, mask, mask, timeout);
}
#ifdef CONFIG_IWL3945_DEBUG
@@ -307,6 +298,7 @@ static inline int __iwl3945_poll_direct_bit(const char *f, u32 l,
static inline u32 _iwl3945_read_prph(struct iwl3945_priv *priv, u32 reg)
{
_iwl3945_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
+ rmb();
return _iwl3945_read_direct32(priv, HBUS_TARG_PRPH_RDAT);
}
#ifdef CONFIG_IWL3945_DEBUG
@@ -328,6 +320,7 @@ static inline void _iwl3945_write_prph(struct iwl3945_priv *priv,
{
_iwl3945_write_direct32(priv, HBUS_TARG_PRPH_WADDR,
((addr & 0x0000FFFF) | (3 << 24)));
+ wmb();
_iwl3945_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val);
}
#ifdef CONFIG_IWL3945_DEBUG
@@ -389,12 +382,14 @@ static inline void iwl3945_clear_bits_prph(struct iwl3945_priv
static inline u32 iwl3945_read_targ_mem(struct iwl3945_priv *priv, u32 addr)
{
iwl3945_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr);
+ rmb();
return iwl3945_read_direct32(priv, HBUS_TARG_MEM_RDAT);
}
static inline void iwl3945_write_targ_mem(struct iwl3945_priv *priv, u32 addr, u32 val)
{
iwl3945_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
+ wmb();
iwl3945_write_direct32(priv, HBUS_TARG_MEM_WDAT, val);
}
@@ -402,6 +397,7 @@ static inline void iwl3945_write_targ_mem_buf(struct iwl3945_priv *priv, u32 add
u32 len, u32 *values)
{
iwl3945_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
+ wmb();
for (; 0 < len; len -= sizeof(u32), values++)
iwl3945_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c
index 705c65bed9fd..4c638909a7db 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c
@@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h
index 2fbd126c1347..749ac035fd6a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-led.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.h
@@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
index 6fc5e7361f26..9b60a0c5de5f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
@@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -63,6 +63,9 @@ struct iwl3945_rs_sta {
u8 ibss_sta_added;
struct timer_list rate_scale_flush;
struct iwl3945_rate_scale_data win[IWL_RATE_COUNT];
+#ifdef CONFIG_MAC80211_DEBUGFS
+ struct dentry *rs_sta_dbgfs_stats_table_file;
+#endif
/* used to be in sta_info */
int last_txrate_idx;
@@ -114,9 +117,11 @@ static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
};
#define IWL_RATE_MAX_WINDOW 62
-#define IWL_RATE_FLUSH (3*HZ/10)
+#define IWL_RATE_FLUSH (3*HZ)
#define IWL_RATE_WIN_FLUSH (HZ/2)
#define IWL_RATE_HIGH_TH 11520
+#define IWL_SUCCESS_UP_TH 8960
+#define IWL_SUCCESS_DOWN_TH 10880
#define IWL_RATE_MIN_FAILURE_TH 8
#define IWL_RATE_MIN_SUCCESS_TH 8
#define IWL_RATE_DECREASE_TH 1920
@@ -203,6 +208,7 @@ static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta)
#define IWL_RATE_FLUSH_MAX 5000 /* msec */
#define IWL_RATE_FLUSH_MIN 50 /* msec */
+#define IWL_AVERAGE_PACKETS 1500
static void iwl3945_bg_rate_scale_flush(unsigned long data)
{
@@ -217,8 +223,6 @@ static void iwl3945_bg_rate_scale_flush(unsigned long data)
spin_lock_irqsave(&rs_sta->lock, flags);
- rs_sta->flush_pending = 0;
-
/* Number of packets Rx'd since last time this timer ran */
packet_count = (rs_sta->tx_packets - rs_sta->last_tx_packets) + 1;
@@ -227,7 +231,6 @@ static void iwl3945_bg_rate_scale_flush(unsigned long data)
if (unflushed) {
duration =
jiffies_to_msecs(jiffies - rs_sta->last_partial_flush);
-/* duration = jiffies_to_msecs(rs_sta->flush_time); */
IWL_DEBUG_RATE("Tx'd %d packets in %dms\n",
packet_count, duration);
@@ -239,9 +242,11 @@ static void iwl3945_bg_rate_scale_flush(unsigned long data)
pps = 0;
if (pps) {
- duration = IWL_RATE_FLUSH_MAX / pps;
+ duration = (IWL_AVERAGE_PACKETS * 1000) / pps;
if (duration < IWL_RATE_FLUSH_MIN)
duration = IWL_RATE_FLUSH_MIN;
+ else if (duration > IWL_RATE_FLUSH_MAX)
+ duration = IWL_RATE_FLUSH_MAX;
} else
duration = IWL_RATE_FLUSH_MAX;
@@ -254,8 +259,10 @@ static void iwl3945_bg_rate_scale_flush(unsigned long data)
rs_sta->flush_time);
rs_sta->last_partial_flush = jiffies;
+ } else {
+ rs_sta->flush_time = IWL_RATE_FLUSH;
+ rs_sta->flush_pending = 0;
}
-
/* If there weren't any unflushed entries, we don't schedule the timer
* to run again */
@@ -275,17 +282,18 @@ static void iwl3945_bg_rate_scale_flush(unsigned long data)
*/
static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta,
struct iwl3945_rate_scale_data *window,
- int success, int retries)
+ int success, int retries, int index)
{
unsigned long flags;
+ s32 fail_count;
if (!retries) {
IWL_DEBUG_RATE("leave: retries == 0 -- should be at least 1\n");
return;
}
+ spin_lock_irqsave(&rs_sta->lock, flags);
while (retries--) {
- spin_lock_irqsave(&rs_sta->lock, flags);
/* If we have filled up the window then subtract one from the
* success counter if the high-bit is counting toward
@@ -313,14 +321,25 @@ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta,
/* Tag this window as having been updated */
window->stamp = jiffies;
- spin_unlock_irqrestore(&rs_sta->lock, flags);
}
+
+ fail_count = window->counter - window->success_counter;
+ if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) ||
+ (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH))
+ window->average_tpt = ((window->success_ratio *
+ rs_sta->expected_tpt[index] + 64) / 128);
+ else
+ window->average_tpt = IWL_INV_TPT;
+
+ spin_unlock_irqrestore(&rs_sta->lock, flags);
+
}
-static void rs_rate_init(void *priv, struct ieee80211_supported_band *sband,
+static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta)
{
struct iwl3945_rs_sta *rs_sta = priv_sta;
+ struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r;
int i;
IWL_DEBUG_RATE("enter\n");
@@ -330,16 +349,21 @@ static void rs_rate_init(void *priv, struct ieee80211_supported_band *sband,
* previous packets? Need to have IEEE 802.1X auth succeed immediately
* after assoc.. */
- for (i = IWL_RATE_COUNT - 1; i >= 0; i--) {
+ for (i = sband->n_bitrates - 1; i >= 0; i--) {
if (sta->supp_rates[sband->band] & (1 << i)) {
rs_sta->last_txrate_idx = i;
break;
}
}
+ priv->sta_supp_rates = sta->supp_rates[sband->band];
/* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
- if (sband->band == IEEE80211_BAND_5GHZ)
+ if (sband->band == IEEE80211_BAND_5GHZ) {
rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
+ priv->sta_supp_rates = priv->sta_supp_rates <<
+ IWL_FIRST_OFDM_RATE;
+ }
+
IWL_DEBUG_RATE("leave\n");
}
@@ -355,12 +379,6 @@ static void rs_free(void *priv)
return;
}
-static void rs_clear(void *priv)
-{
- return;
-}
-
-
static void *rs_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp)
{
struct iwl3945_rs_sta *rs_sta;
@@ -422,34 +440,6 @@ static void rs_free_sta(void *priv, struct ieee80211_sta *sta,
}
-/*
- * get ieee prev rate from rate scale table.
- * for A and B mode we need to overright prev
- * value
- */
-static int rs_adjust_next_rate(struct iwl3945_priv *priv, int rate)
-{
- int next_rate = iwl3945_get_prev_ieee_rate(rate);
-
- switch (priv->band) {
- case IEEE80211_BAND_5GHZ:
- if (rate == IWL_RATE_12M_INDEX)
- next_rate = IWL_RATE_9M_INDEX;
- else if (rate == IWL_RATE_6M_INDEX)
- next_rate = IWL_RATE_6M_INDEX;
- break;
-/* XXX cannot be invoked in current mac80211 so not a regression
- case MODE_IEEE80211B:
- if (rate == IWL_RATE_11M_INDEX_TABLE)
- next_rate = IWL_RATE_5M_INDEX_TABLE;
- break;
- */
- default:
- break;
- }
-
- return next_rate;
-}
/**
* rs_tx_status - Update rate control values based on Tx results
*
@@ -460,7 +450,7 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband
struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb)
{
- u8 retries, current_count;
+ s8 retries = 0, current_count;
int scale_rate_index, first_index, last_index;
unsigned long flags;
struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate;
@@ -469,8 +459,9 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband
IWL_DEBUG_RATE("enter\n");
- retries = info->status.retry_count;
- first_index = sband->bitrates[info->tx_rate_idx].hw_value;
+ retries = info->status.rates[0].count;
+
+ first_index = sband->bitrates[info->status.rates[0].idx].hw_value;
if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) {
IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index);
return;
@@ -496,13 +487,13 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband
* at which the frame was finally transmitted (or failed if no
* ACK)
*/
- while (retries > 0) {
- if (retries < priv->retry_rate) {
- current_count = retries;
+ while (retries > 1) {
+ if ((retries - 1) < priv->retry_rate) {
+ current_count = (retries - 1);
last_index = scale_rate_index;
} else {
current_count = priv->retry_rate;
- last_index = rs_adjust_next_rate(priv,
+ last_index = iwl3945_rs_next_rate(priv,
scale_rate_index);
}
@@ -510,15 +501,13 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband
* as was used for it (per current_count) */
iwl3945_collect_tx_data(rs_sta,
&rs_sta->win[scale_rate_index],
- 0, current_count);
+ 0, current_count, scale_rate_index);
IWL_DEBUG_RATE("Update rate %d for %d retries.\n",
scale_rate_index, current_count);
retries -= current_count;
- if (retries)
- scale_rate_index =
- rs_adjust_next_rate(priv, scale_rate_index);
+ scale_rate_index = last_index;
}
@@ -529,7 +518,7 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband
"success" : "failure");
iwl3945_collect_tx_data(rs_sta,
&rs_sta->win[last_index],
- info->flags & IEEE80211_TX_STAT_ACK, 1);
+ info->flags & IEEE80211_TX_STAT_ACK, 1, last_index);
/* We updated the rate scale window -- if its been more than
* flush_time since the last run, schedule the flush
@@ -537,9 +526,10 @@ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband
spin_lock_irqsave(&rs_sta->lock, flags);
if (!rs_sta->flush_pending &&
- time_after(jiffies, rs_sta->last_partial_flush +
+ time_after(jiffies, rs_sta->last_flush +
rs_sta->flush_time)) {
+ rs_sta->last_partial_flush = jiffies;
rs_sta->flush_pending = 1;
mod_timer(&rs_sta->rate_scale_flush,
jiffies + rs_sta->flush_time);
@@ -630,10 +620,11 @@ static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
* rate table and must reference the driver allocated rate table
*
*/
-static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
- struct ieee80211_sta *sta, void *priv_sta,
- struct sk_buff *skb, struct rate_selection *sel)
+static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta,
+ void *priv_sta, struct ieee80211_tx_rate_control *txrc)
{
+ struct ieee80211_supported_band *sband = txrc->sband;
+ struct sk_buff *skb = txrc->skb;
u8 low = IWL_RATE_INVALID;
u8 high = IWL_RATE_INVALID;
u16 high_low;
@@ -649,7 +640,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
u16 fc, rate_mask;
struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r;
- DECLARE_MAC_BUF(mac);
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
IWL_DEBUG_RATE("enter\n");
@@ -660,7 +651,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
is_multicast_ether_addr(hdr->addr1) ||
!sta || !priv_sta) {
IWL_DEBUG_RATE("leave: No STA priv data to update!\n");
- sel->rate_idx = rate_lowest_index(sband, sta);
+ info->control.rates[0].idx = rate_lowest_index(sband, sta);
return;
}
@@ -675,8 +666,8 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
u8 sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
if (sta_id == IWL_INVALID_STATION) {
- IWL_DEBUG_RATE("LQ: ADD station %s\n",
- print_mac(mac, hdr->addr1));
+ IWL_DEBUG_RATE("LQ: ADD station %pm\n",
+ hdr->addr1);
sta_id = iwl3945_add_station(priv,
hdr->addr1, 0, CMD_ASYNC);
}
@@ -686,8 +677,13 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
spin_lock_irqsave(&rs_sta->lock, flags);
+ /* for recent assoc, choose best rate regarding
+ * to rssi value
+ */
if (rs_sta->start_rate != IWL_RATE_INVALID) {
- index = rs_sta->start_rate;
+ if (rs_sta->start_rate < index &&
+ (rate_mask & (1 << rs_sta->start_rate)))
+ index = rs_sta->start_rate;
rs_sta->start_rate = IWL_RATE_INVALID;
}
@@ -697,7 +693,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
if (((fail_count <= IWL_RATE_MIN_FAILURE_TH) &&
(window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) {
- window->average_tpt = IWL_INV_TPT;
spin_unlock_irqrestore(&rs_sta->lock, flags);
IWL_DEBUG_RATE("Invalid average_tpt on rate %d: "
@@ -711,8 +706,6 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
}
- window->average_tpt = ((window->success_ratio *
- rs_sta->expected_tpt[index] + 64) / 128);
current_tpt = window->average_tpt;
high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask,
@@ -760,13 +753,15 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
}
}
- if ((window->success_ratio > IWL_RATE_HIGH_TH) ||
- (current_tpt > window->average_tpt)) {
- IWL_DEBUG_RATE("No action -- success_ratio [%d] > HIGH_TH or "
- "current_tpt [%d] > average_tpt [%d]\n",
- window->success_ratio,
- current_tpt, window->average_tpt);
- scale_action = 0;
+ if (scale_action == -1) {
+ if (window->success_ratio > IWL_SUCCESS_DOWN_TH)
+ scale_action = 0;
+ } else if (scale_action == 1) {
+ if (window->success_ratio < IWL_SUCCESS_UP_TH) {
+ IWL_DEBUG_RATE("No action -- success_ratio [%d] < "
+ "SUCCESS UP\n", window->success_ratio);
+ scale_action = 0;
+ }
}
switch (scale_action) {
@@ -793,24 +788,83 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
rs_sta->last_txrate_idx = index;
if (sband->band == IEEE80211_BAND_5GHZ)
- sel->rate_idx = rs_sta->last_txrate_idx - IWL_FIRST_OFDM_RATE;
+ info->control.rates[0].idx = rs_sta->last_txrate_idx -
+ IWL_FIRST_OFDM_RATE;
else
- sel->rate_idx = rs_sta->last_txrate_idx;
+ info->control.rates[0].idx = rs_sta->last_txrate_idx;
IWL_DEBUG_RATE("leave: %d\n", index);
}
+#ifdef CONFIG_MAC80211_DEBUGFS
+static int iwl3945_open_file_generic(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+static ssize_t iwl3945_sta_dbgfs_stats_table_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ char buff[1024];
+ int desc = 0;
+ int j;
+ struct iwl3945_rs_sta *lq_sta = file->private_data;
+
+ desc += sprintf(buff + desc, "tx packets=%d last rate index=%d\n"
+ "rate=0x%X flush time %d\n",
+ lq_sta->tx_packets,
+ lq_sta->last_txrate_idx,
+ lq_sta->start_rate, jiffies_to_msecs(lq_sta->flush_time));
+ for (j = 0; j < IWL_RATE_COUNT; j++) {
+ desc += sprintf(buff+desc,
+ "counter=%d success=%d %%=%d\n",
+ lq_sta->win[j].counter,
+ lq_sta->win[j].success_counter,
+ lq_sta->win[j].success_ratio);
+ }
+ return simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+}
+
+static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
+ .read = iwl3945_sta_dbgfs_stats_table_read,
+ .open = iwl3945_open_file_generic,
+};
+
+static void iwl3945_add_debugfs(void *priv, void *priv_sta,
+ struct dentry *dir)
+{
+ struct iwl3945_rs_sta *lq_sta = priv_sta;
+
+ lq_sta->rs_sta_dbgfs_stats_table_file =
+ debugfs_create_file("rate_stats_table", 0600, dir,
+ lq_sta, &rs_sta_dbgfs_stats_table_ops);
+
+}
+
+static void iwl3945_remove_debugfs(void *priv, void *priv_sta)
+{
+ struct iwl3945_rs_sta *lq_sta = priv_sta;
+ debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
+}
+#endif
+
static struct rate_control_ops rs_ops = {
.module = NULL,
.name = RS_NAME,
.tx_status = rs_tx_status,
.get_rate = rs_get_rate,
.rate_init = rs_rate_init,
- .clear = rs_clear,
.alloc = rs_alloc,
.free = rs_free,
.alloc_sta = rs_alloc_sta,
.free_sta = rs_free_sta,
+#ifdef CONFIG_MAC80211_DEBUGFS
+ .add_sta_debugfs = iwl3945_add_debugfs,
+ .remove_sta_debugfs = iwl3945_remove_debugfs,
+#endif
+
};
void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
@@ -827,13 +881,12 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
rcu_read_lock();
sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr);
- psta = (void *) sta->drv_priv;
- if (!sta || !psta) {
- IWL_DEBUG_RATE("leave - no private rate data!\n");
+ if (!sta) {
rcu_read_unlock();
return;
}
+ psta = (void *) sta->drv_priv;
rs_sta = psta->rs_sta;
spin_lock_irqsave(&rs_sta->lock, flags);
@@ -857,7 +910,6 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
break;
}
- rcu_read_unlock();
spin_unlock_irqrestore(&rs_sta->lock, flags);
rssi = priv->last_rx_rssi;
@@ -871,6 +923,7 @@ void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
IWL_DEBUG_RATE("leave: rssi %d assign rate index: "
"%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
iwl3945_rates[rs_sta->start_rate].plcp);
+ rcu_read_unlock();
}
int iwl3945_rate_control_register(void)
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
index 98b17ae6ef24..b5a66135dedd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-rs.h
@@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 7ca5627cc078..8fdb34222c0a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -200,7 +200,7 @@ static int iwl3945_hwrate_to_plcp_idx(u8 plcp)
* priv->eeprom is used to determine if antenna AUX/MAIN are reversed
* priv->antenna specifies the antenna diversity mode:
*
- * IWL_ANTENNA_DIVERISTY - NIC selects best antenna by itself
+ * IWL_ANTENNA_DIVERSITY - NIC selects best antenna by itself
* IWL_ANTENNA_MAIN - Force MAIN antenna
* IWL_ANTENNA_AUX - Force AUX antenna
*/
@@ -261,6 +261,37 @@ static inline const char *iwl3945_get_tx_fail_reason(u32 status)
}
#endif
+/*
+ * get ieee prev rate from rate scale table.
+ * for A and B mode we need to overright prev
+ * value
+ */
+int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate)
+{
+ int next_rate = iwl3945_get_prev_ieee_rate(rate);
+
+ switch (priv->band) {
+ case IEEE80211_BAND_5GHZ:
+ if (rate == IWL_RATE_12M_INDEX)
+ next_rate = IWL_RATE_9M_INDEX;
+ else if (rate == IWL_RATE_6M_INDEX)
+ next_rate = IWL_RATE_6M_INDEX;
+ break;
+ case IEEE80211_BAND_2GHZ:
+ if (!(priv->sta_supp_rates & IWL_OFDM_RATES_MASK) &&
+ iwl3945_is_associated(priv)) {
+ if (rate == IWL_RATE_11M_INDEX)
+ next_rate = IWL_RATE_5M_INDEX;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return next_rate;
+}
+
/**
* iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
@@ -308,6 +339,7 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
u32 status = le32_to_cpu(tx_resp->status);
int rate_idx;
+ int fail;
if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) {
IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
@@ -318,9 +350,18 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
}
info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]);
- memset(&info->status, 0, sizeof(info->status));
+ ieee80211_tx_info_clear_status(info);
+
+ /* Fill the MRR chain with some info about on-chip retransmissions */
+ rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate);
+ if (info->band == IEEE80211_BAND_5GHZ)
+ rate_idx -= IWL_FIRST_OFDM_RATE;
+
+ fail = tx_resp->failure_frame;
+
+ info->status.rates[0].idx = rate_idx;
+ info->status.rates[0].count = fail + 1; /* add final attempt */
- info->status.retry_count = tx_resp->failure_frame;
/* tx_status->rts_retry_count = tx_resp->failure_rts; */
info->flags |= ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ?
IEEE80211_TX_STAT_ACK : 0;
@@ -329,10 +370,6 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv,
txq_id, iwl3945_get_tx_fail_reason(status), status,
tx_resp->rate, tx_resp->failure_frame);
- rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate);
- if (info->band == IEEE80211_BAND_5GHZ)
- rate_idx -= IWL_FIRST_OFDM_RATE;
- info->tx_rate_idx = rate_idx;
IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
iwl3945_tx_queue_reclaim(priv, txq_id, index);
@@ -756,13 +793,19 @@ int iwl3945_hw_txq_free_tfd(struct iwl3945_priv *priv, struct iwl3945_tx_queue *
u8 iwl3945_hw_find_station(struct iwl3945_priv *priv, const u8 *addr)
{
- int i;
+ int i, start = IWL_AP_ID;
int ret = IWL_INVALID_STATION;
unsigned long flags;
- DECLARE_MAC_BUF(mac);
+
+ if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) ||
+ (priv->iw_mode == NL80211_IFTYPE_AP))
+ start = IWL_STA_ID;
+
+ if (is_broadcast_ether_addr(addr))
+ return priv->hw_setting.bcast_sta_id;
spin_lock_irqsave(&priv->sta_lock, flags);
- for (i = IWL_STA_ID; i < priv->hw_setting.max_stations; i++)
+ for (i = start; i < priv->hw_setting.max_stations; i++)
if ((priv->stations[i].used) &&
(!compare_ether_addr
(priv->stations[i].sta.sta.addr, addr))) {
@@ -770,8 +813,8 @@ u8 iwl3945_hw_find_station(struct iwl3945_priv *priv, const u8 *addr)
goto out;
}
- IWL_DEBUG_INFO("can not find STA %s (total %d)\n",
- print_mac(mac, addr), priv->num_stations);
+ IWL_DEBUG_INFO("can not find STA %pM (total %d)\n",
+ addr, priv->num_stations);
out:
spin_unlock_irqrestore(&priv->sta_lock, flags);
return ret;
@@ -1060,9 +1103,8 @@ int iwl3945_hw_nic_init(struct iwl3945_priv *priv)
CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
- rc = iwl3945_poll_bit(priv, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+ rc = iwl3945_poll_direct_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
if (rc < 0) {
spin_unlock_irqrestore(&priv->lock, flags);
IWL_DEBUG_INFO("Failed to init the card\n");
@@ -1243,8 +1285,7 @@ int iwl3945_hw_nic_stop_master(struct iwl3945_priv *priv)
IWL_DEBUG_INFO("Card in power save, master is already "
"stopped\n");
else {
- rc = iwl3945_poll_bit(priv, CSR_RESET,
- CSR_RESET_REG_FLAG_MASTER_DISABLED,
+ rc = iwl3945_poll_direct_bit(priv, CSR_RESET,
CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
if (rc < 0) {
spin_unlock_irqrestore(&priv->lock, flags);
@@ -1269,9 +1310,8 @@ int iwl3945_hw_nic_reset(struct iwl3945_priv *priv)
iwl3945_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
- rc = iwl3945_poll_bit(priv, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+ iwl3945_poll_direct_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
rc = iwl3945_grab_nic_access(priv);
if (!rc) {
@@ -1830,7 +1870,7 @@ static int iwl3945_hw_reg_comp_txpower_temp(struct iwl3945_priv *priv)
ref_temp = (s16)priv->eeprom.groups[ch_info->group_index].
temperature;
- /* get power index adjustment based on curr and factory
+ /* get power index adjustment based on current and factory
* temps */
delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature,
ref_temp);
@@ -2268,7 +2308,8 @@ int iwl3945_hw_rxq_stop(struct iwl3945_priv *priv)
}
iwl3945_write_direct32(priv, FH_RCSR_CONFIG(0), 0);
- rc = iwl3945_poll_direct_bit(priv, FH_RSSR_STATUS, (1 << 24), 1000);
+ rc = iwl3945_poll_direct_bit(priv, FH_RSSR_STATUS,
+ FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
if (rc < 0)
IWL_ERROR("Can't stop Rx DMA.\n");
@@ -2337,7 +2378,8 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
iwl3945_hw_set_rate_n_flags(iwl3945_rates[i].plcp, 0);
table[index].try_cnt = priv->retry_rate;
prev_index = iwl3945_get_prev_ieee_rate(i);
- table[index].next_rate_index = iwl3945_rates[prev_index].table_rs_index;
+ table[index].next_rate_index =
+ iwl3945_rates[prev_index].table_rs_index;
}
switch (priv->band) {
@@ -2345,11 +2387,14 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
IWL_DEBUG_RATE("Select A mode rate scale\n");
/* If one of the following CCK rates is used,
* have it fall back to the 6M OFDM rate */
- for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++)
- table[i].next_rate_index = iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
+ for (i = IWL_RATE_1M_INDEX_TABLE;
+ i <= IWL_RATE_11M_INDEX_TABLE; i++)
+ table[i].next_rate_index =
+ iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
/* Don't fall back to CCK rates */
- table[IWL_RATE_12M_INDEX_TABLE].next_rate_index = IWL_RATE_9M_INDEX_TABLE;
+ table[IWL_RATE_12M_INDEX_TABLE].next_rate_index =
+ IWL_RATE_9M_INDEX_TABLE;
/* Don't drop out of OFDM rates */
table[IWL_RATE_6M_INDEX_TABLE].next_rate_index =
@@ -2360,11 +2405,20 @@ int iwl3945_init_hw_rate_table(struct iwl3945_priv *priv)
IWL_DEBUG_RATE("Select B/G mode rate scale\n");
/* If an OFDM rate is used, have it fall back to the
* 1M CCK rates */
- for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE; i++)
- table[i].next_rate_index = iwl3945_rates[IWL_FIRST_CCK_RATE].table_rs_index;
- /* CCK shouldn't fall back to OFDM... */
- table[IWL_RATE_11M_INDEX_TABLE].next_rate_index = IWL_RATE_5M_INDEX_TABLE;
+ if (!(priv->sta_supp_rates & IWL_OFDM_RATES_MASK) &&
+ iwl3945_is_associated(priv)) {
+
+ index = IWL_FIRST_CCK_RATE;
+ for (i = IWL_RATE_6M_INDEX_TABLE;
+ i <= IWL_RATE_54M_INDEX_TABLE; i++)
+ table[i].next_rate_index =
+ iwl3945_rates[index].table_rs_index;
+
+ index = IWL_RATE_11M_INDEX_TABLE;
+ /* CCK shouldn't fall back to OFDM... */
+ table[index].next_rate_index = IWL_RATE_5M_INDEX_TABLE;
+ }
break;
default:
@@ -2428,7 +2482,6 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv,
frame_size = iwl3945_fill_beacon_frame(priv,
tx_beacon_cmd->frame,
- iwl3945_broadcast_addr,
sizeof(frame->u) - sizeof(*tx_beacon_cmd));
BUG_ON(frame_size > MAX_MPDU_SIZE);
@@ -2467,13 +2520,17 @@ void iwl3945_hw_cancel_deferred_work(struct iwl3945_priv *priv)
static struct iwl_3945_cfg iwl3945_bg_cfg = {
.name = "3945BG",
- .fw_name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode",
+ .fw_name_pre = IWL3945_FW_PRE,
+ .ucode_api_max = IWL3945_UCODE_API_MAX,
+ .ucode_api_min = IWL3945_UCODE_API_MIN,
.sku = IWL_SKU_G,
};
static struct iwl_3945_cfg iwl3945_abg_cfg = {
.name = "3945ABG",
- .fw_name = "iwlwifi-3945" IWL3945_UCODE_API ".ucode",
+ .fw_name_pre = IWL3945_FW_PRE,
+ .ucode_api_max = IWL3945_UCODE_API_MAX,
+ .ucode_api_min = IWL3945_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G,
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index bdd32475b99c..2c0ddc5110c6 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -50,11 +50,15 @@ extern struct pci_device_id iwl3945_hw_card_ids[];
#include "iwl-3945-debug.h"
#include "iwl-3945-led.h"
-/* Change firmware file name, using "-" and incrementing number,
- * *only* when uCode interface or architecture changes so that it
- * is not compatible with earlier drivers.
- * This number will also appear in << 8 position of 1st dword of uCode file */
-#define IWL3945_UCODE_API "-1"
+/* Highest firmware API version supported */
+#define IWL3945_UCODE_API_MAX 2
+
+/* Lowest firmware API version supported */
+#define IWL3945_UCODE_API_MIN 1
+
+#define IWL3945_FW_PRE "iwlwifi-3945-"
+#define _IWL3945_MODULE_FIRMWARE(api) IWL3945_FW_PRE #api ".ucode"
+#define IWL3945_MODULE_FIRMWARE(api) _IWL3945_MODULE_FIRMWARE(api)
/* Default noise level to report when noise measurement is not available.
* This may be because we're:
@@ -401,12 +405,6 @@ struct iwl3945_rx_queue {
#define SCAN_INTERVAL 100
-#define MAX_A_CHANNELS 252
-#define MIN_A_CHANNELS 7
-
-#define MAX_B_CHANNELS 14
-#define MIN_B_CHANNELS 1
-
#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */
#define STATUS_INT_ENABLED 2
@@ -472,7 +470,6 @@ union iwl3945_qos_capabity {
/* QoS structures */
struct iwl3945_qos_info {
- int qos_enable;
int qos_active;
union iwl3945_qos_capabity qos_cap;
struct iwl3945_qosparam_cmd def_qos_parm;
@@ -505,7 +502,7 @@ struct fw_desc {
/* uCode file layout */
struct iwl3945_ucode {
- __le32 ver; /* major/minor/subminor */
+ __le32 ver; /* major/minor/API/serial */
__le32 inst_size; /* bytes of runtime instructions */
__le32 data_size; /* bytes of runtime data */
__le32 init_size; /* bytes of initialization instructions */
@@ -587,8 +584,7 @@ extern int iwl3945_send_cmd_pdu(struct iwl3945_priv *priv, u8 id, u16 len,
extern int __must_check iwl3945_send_cmd(struct iwl3945_priv *priv,
struct iwl3945_host_cmd *cmd);
extern unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv,
- struct ieee80211_hdr *hdr,
- const u8 *dest, int left);
+ struct ieee80211_hdr *hdr,int left);
extern int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv,
struct iwl3945_rx_queue *q);
extern int iwl3945_send_statistics_request(struct iwl3945_priv *priv);
@@ -762,6 +758,8 @@ struct iwl3945_priv {
void __iomem *hw_base;
/* uCode images, save to reload in case of failure */
+ u32 ucode_ver; /* ucode version, copy of
+ iwl3945_ucode.ver */
struct fw_desc ucode_code; /* runtime inst */
struct fw_desc ucode_data; /* runtime data original */
struct fw_desc ucode_data_backup; /* runtime data save/restore */
@@ -804,6 +802,8 @@ struct iwl3945_priv {
u16 active_rate;
u16 active_rate_basic;
+ u32 sta_supp_rates;
+
u8 call_post_assoc_from_beacon;
/* Rate scaling data */
s8 data_retry_limit;
@@ -828,8 +828,6 @@ struct iwl3945_priv {
unsigned long last_statistics_time;
/* context information */
- u8 essid[IW_ESSID_MAX_SIZE];
- u8 essid_len;
u16 rates_mask;
u32 power_mode;
@@ -888,7 +886,6 @@ struct iwl3945_priv {
struct work_struct report_work;
struct work_struct request_scan;
struct work_struct beacon_update;
- struct work_struct set_monitor;
struct tasklet_struct irq_tasklet;
@@ -903,9 +900,6 @@ struct iwl3945_priv {
s8 user_txpower_limit;
s8 max_channel_txpower_limit;
-#ifdef CONFIG_PM
- u32 pm_state[16];
-#endif
#ifdef CONFIG_IWL3945_DEBUG
/* debugging info */
@@ -954,6 +948,8 @@ static inline int is_channel_ibss(const struct iwl3945_channel_info *ch)
extern const struct iwl3945_channel_info *iwl3945_get_channel_info(
const struct iwl3945_priv *priv, enum ieee80211_band band, u16 channel);
+extern int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate);
+
/* Requires full declaration of iwl3945_priv before including */
#include "iwl-3945-io.h"
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
index f4793a609443..6649f7b55650 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
@@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@@ -71,7 +71,7 @@
#include "iwl-fh.h"
-/* EERPROM */
+/* EEPROM */
#define IWL4965_EEPROM_IMG_SIZE 1024
/*
@@ -84,12 +84,6 @@
#define IWL_CMD_FIFO_NUM 4
#define IWL49_FIRST_AMPDU_QUEUE 7
-/* Tx rates */
-#define IWL_CCK_RATES 4
-#define IWL_OFDM_RATES 8
-#define IWL_HT_RATES 16
-#define IWL_MAX_RATES (IWL_CCK_RATES+IWL_OFDM_RATES+IWL_HT_RATES)
-
/* Time constants */
#define SHORT_SLOT_TIME 9
#define LONG_SLOT_TIME 20
@@ -111,7 +105,6 @@
#define PCI_CFG_CMD_REG_INT_DIS_MSK 0x04
#define PCI_CFG_PMC_PME_FROM_D3COLD_SUPPORT (0x80000000)
-#define TFD_QUEUE_SIZE_MAX (256)
#define IWL_NUM_SCAN_RATES (2)
@@ -287,13 +280,13 @@ static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr)
* that target txpower.
*
*
- * 3) Determine (EEPROM) calibration subband for the target channel, by
- * comparing against first and last channels in each subband
+ * 3) Determine (EEPROM) calibration sub band for the target channel, by
+ * comparing against first and last channels in each sub band
* (see struct iwl4965_eeprom_calib_subband_info).
*
*
* 4) Linearly interpolate (EEPROM) factory calibration measurement sets,
- * referencing the 2 factory-measured (sample) channels within the subband.
+ * referencing the 2 factory-measured (sample) channels within the sub band.
*
* Interpolation is based on difference between target channel's frequency
* and the sample channels' frequencies. Since channel numbers are based
@@ -301,7 +294,7 @@ static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr)
* to interpolating based on channel number differences.
*
* Note that the sample channels may or may not be the channels at the
- * edges of the subband. The target channel may be "outside" of the
+ * edges of the sub band. The target channel may be "outside" of the
* span of the sampled channels.
*
* Driver may choose the pair (for 2 Tx chains) of measurements (see
@@ -345,7 +338,7 @@ static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr)
* "4965 temperature calculation".
*
* If current temperature is higher than factory temperature, driver must
- * increase gain (lower gain table index), and vice versa.
+ * increase gain (lower gain table index), and vice verse.
*
* Temperature affects gain differently for different channels:
*
@@ -815,125 +808,14 @@ enum {
* up to 7 DMA channels (FIFOs). Each Tx queue is supported by a circular array
* in DRAM containing 256 Transmit Frame Descriptors (TFDs).
*/
-#define IWL49_MAX_WIN_SIZE 64
-#define IWL49_QUEUE_SIZE 256
#define IWL49_NUM_FIFOS 7
#define IWL49_CMD_FIFO_NUM 4
#define IWL49_NUM_QUEUES 16
#define IWL49_NUM_AMPDU_QUEUES 8
-/**
- * struct iwl_tfd_frame_data
- *
- * Describes up to 2 buffers containing (contiguous) portions of a Tx frame.
- * Each buffer must be on dword boundary.
- * Up to 10 iwl_tfd_frame_data structures, describing up to 20 buffers,
- * may be filled within a TFD (iwl_tfd_frame).
- *
- * Bit fields in tb1_addr:
- * 31- 0: Tx buffer 1 address bits [31:0]
- *
- * Bit fields in val1:
- * 31-16: Tx buffer 2 address bits [15:0]
- * 15- 4: Tx buffer 1 length (bytes)
- * 3- 0: Tx buffer 1 address bits [32:32]
- *
- * Bit fields in val2:
- * 31-20: Tx buffer 2 length (bytes)
- * 19- 0: Tx buffer 2 address bits [35:16]
- */
-struct iwl_tfd_frame_data {
- __le32 tb1_addr;
-
- __le32 val1;
- /* __le32 ptb1_32_35:4; */
-#define IWL_tb1_addr_hi_POS 0
-#define IWL_tb1_addr_hi_LEN 4
-#define IWL_tb1_addr_hi_SYM val1
- /* __le32 tb_len1:12; */
-#define IWL_tb1_len_POS 4
-#define IWL_tb1_len_LEN 12
-#define IWL_tb1_len_SYM val1
- /* __le32 ptb2_0_15:16; */
-#define IWL_tb2_addr_lo16_POS 16
-#define IWL_tb2_addr_lo16_LEN 16
-#define IWL_tb2_addr_lo16_SYM val1
-
- __le32 val2;
- /* __le32 ptb2_16_35:20; */
-#define IWL_tb2_addr_hi20_POS 0
-#define IWL_tb2_addr_hi20_LEN 20
-#define IWL_tb2_addr_hi20_SYM val2
- /* __le32 tb_len2:12; */
-#define IWL_tb2_len_POS 20
-#define IWL_tb2_len_LEN 12
-#define IWL_tb2_len_SYM val2
-} __attribute__ ((packed));
-
/**
- * struct iwl_tfd_frame
- *
- * Transmit Frame Descriptor (TFD)
- *
- * 4965 supports up to 16 Tx queues resident in host DRAM.
- * Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM.
- * Both driver and device share these circular buffers, each of which must be
- * contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes for 4965.
- *
- * Driver must indicate the physical address of the base of each
- * circular buffer via the 4965's FH_MEM_CBBC_QUEUE registers.
- *
- * Each TFD contains pointer/size information for up to 20 data buffers
- * in host DRAM. These buffers collectively contain the (one) frame described
- * by the TFD. Each buffer must be a single contiguous block of memory within
- * itself, but buffers may be scattered in host DRAM. Each buffer has max size
- * of (4K - 4). The 4965 concatenates all of a TFD's buffers into a single
- * Tx frame, up to 8 KBytes in size.
- *
- * Bit fields in the control dword (val0):
- * 31-30: # dwords (0-3) of padding required at end of frame for 16-byte bound
- * 29: reserved
- * 28-24: # Transmit Buffer Descriptors in TFD
- * 23- 0: reserved
- *
- * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx.
- */
-struct iwl_tfd_frame {
- __le32 val0;
- /* __le32 rsvd1:24; */
- /* __le32 num_tbs:5; */
-#define IWL_num_tbs_POS 24
-#define IWL_num_tbs_LEN 5
-#define IWL_num_tbs_SYM val0
- /* __le32 rsvd2:1; */
- /* __le32 padding:2; */
- struct iwl_tfd_frame_data pa[10];
- __le32 reserved;
-} __attribute__ ((packed));
-
-
-/**
- * struct iwl4965_queue_byte_cnt_entry
- *
- * Byte Count Table Entry
- *
- * Bit fields:
- * 15-12: reserved
- * 11- 0: total to-be-transmitted byte count of frame (does not include command)
- */
-struct iwl4965_queue_byte_cnt_entry {
- __le16 val;
- /* __le16 byte_cnt:12; */
-#define IWL_byte_cnt_POS 0
-#define IWL_byte_cnt_LEN 12
-#define IWL_byte_cnt_SYM val
- /* __le16 rsvd:4; */
-} __attribute__ ((packed));
-
-
-/**
- * struct iwl4965_sched_queue_byte_cnt_tbl
+ * struct iwl4965_schedq_bc_tbl
*
* Byte Count table
*
@@ -947,71 +829,12 @@ struct iwl4965_queue_byte_cnt_entry {
* count table for the chosen Tx queue. If the TFD index is 0-63, the driver
* must duplicate the byte count entry in corresponding index 256-319.
*
- * "dont_care" padding puts each byte count table on a 1024-byte boundary;
+ * padding puts each byte count table on a 1024-byte boundary;
* 4965 assumes tables are separated by 1024 bytes.
*/
-struct iwl4965_sched_queue_byte_cnt_tbl {
- struct iwl4965_queue_byte_cnt_entry tfd_offset[IWL49_QUEUE_SIZE +
- IWL49_MAX_WIN_SIZE];
- u8 dont_care[1024 -
- (IWL49_QUEUE_SIZE + IWL49_MAX_WIN_SIZE) *
- sizeof(__le16)];
-} __attribute__ ((packed));
-
-
-/**
- * struct iwl4965_shared - handshake area for Tx and Rx
- *
- * For convenience in allocating memory, this structure combines 2 areas of
- * DRAM which must be shared between driver and 4965. These do not need to
- * be combined, if better allocation would result from keeping them separate:
- *
- * 1) The Tx byte count tables occupy 1024 bytes each (16 KBytes total for
- * 16 queues). Driver uses SCD_DRAM_BASE_ADDR to tell 4965 where to find
- * the first of these tables. 4965 assumes tables are 1024 bytes apart.
- *
- * 2) The Rx status (val0 and val1) occupies only 8 bytes. Driver uses
- * FH_RSCSR_CHNL0_STTS_WPTR_REG to tell 4965 where to find this area.
- * Driver reads val0 to determine the latest Receive Buffer Descriptor (RBD)
- * that has been filled by the 4965.
- *
- * Bit fields val0:
- * 31-12: Not used
- * 11- 0: Index of last filled Rx buffer descriptor (4965 writes, driver reads)
- *
- * Bit fields val1:
- * 31- 0: Not used
- */
-struct iwl4965_shared {
- struct iwl4965_sched_queue_byte_cnt_tbl
- queues_byte_cnt_tbls[IWL49_NUM_QUEUES];
- __le32 rb_closed;
-
- /* __le32 rb_closed_stts_rb_num:12; */
-#define IWL_rb_closed_stts_rb_num_POS 0
-#define IWL_rb_closed_stts_rb_num_LEN 12
-#define IWL_rb_closed_stts_rb_num_SYM rb_closed
- /* __le32 rsrv1:4; */
- /* __le32 rb_closed_stts_rx_frame_num:12; */
-#define IWL_rb_closed_stts_rx_frame_num_POS 16
-#define IWL_rb_closed_stts_rx_frame_num_LEN 12
-#define IWL_rb_closed_stts_rx_frame_num_SYM rb_closed
- /* __le32 rsrv2:4; */
-
- __le32 frm_finished;
- /* __le32 frame_finished_stts_rb_num:12; */
-#define IWL_frame_finished_stts_rb_num_POS 0
-#define IWL_frame_finished_stts_rb_num_LEN 12
-#define IWL_frame_finished_stts_rb_num_SYM frm_finished
- /* __le32 rsrv3:4; */
- /* __le32 frame_finished_stts_rx_frame_num:12; */
-#define IWL_frame_finished_stts_rx_frame_num_POS 16
-#define IWL_frame_finished_stts_rx_frame_num_LEN 12
-#define IWL_frame_finished_stts_rx_frame_num_SYM frm_finished
- /* __le32 rsrv4:4; */
-
- __le32 padding1; /* so that allocation will be aligned to 16B */
- __le32 padding2;
+struct iwl4965_scd_bc_tbl {
+ __le16 tfd_offset[TFD_QUEUE_BC_SIZE];
+ u8 pad[1024 - (TFD_QUEUE_BC_SIZE) * sizeof(__le16)];
} __attribute__ ((packed));
-#endif /* __iwl4965_4965_hw_h__ */
+#endif /* !__iwl_4965_hw_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 9838de5f4369..5a72bc0377de 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -48,18 +48,21 @@
static int iwl4965_send_tx_power(struct iwl_priv *priv);
static int iwl4965_hw_get_temperature(const struct iwl_priv *priv);
-/* Change firmware file name, using "-" and incrementing number,
- * *only* when uCode interface or architecture changes so that it
- * is not compatible with earlier drivers.
- * This number will also appear in << 8 position of 1st dword of uCode file */
-#define IWL4965_UCODE_API "-2"
+/* Highest firmware API version supported */
+#define IWL4965_UCODE_API_MAX 2
+
+/* Lowest firmware API version supported */
+#define IWL4965_UCODE_API_MIN 2
+
+#define IWL4965_FW_PRE "iwlwifi-4965-"
+#define _IWL4965_MODULE_FIRMWARE(api) IWL4965_FW_PRE #api ".ucode"
+#define IWL4965_MODULE_FIRMWARE(api) _IWL4965_MODULE_FIRMWARE(api)
/* module parameters */
static struct iwl_mod_params iwl4965_mod_params = {
.num_of_queues = IWL49_NUM_QUEUES,
.num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES,
- .enable_qos = 1,
.amsdu_size_8K = 1,
.restart_fw = 1,
/* the rest are 0 by default */
@@ -246,7 +249,7 @@ static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv)
iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
priv->ucode_data.len);
- /* Inst bytecount must be last to set up, bit 31 signals uCode
+ /* Inst byte count must be last to set up, bit 31 signals uCode
* that all new ptr/size info is in place */
iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
priv->ucode_code.len | BSM_DRAM_INST_LOAD);
@@ -318,31 +321,13 @@ static int is_fat_channel(__le32 rxon_flags)
/*
* EEPROM handlers
*/
-
-static int iwl4965_eeprom_check_version(struct iwl_priv *priv)
+static u16 iwl4965_eeprom_calib_version(struct iwl_priv *priv)
{
- u16 eeprom_ver;
- u16 calib_ver;
-
- eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
-
- calib_ver = iwl_eeprom_query16(priv, EEPROM_4965_CALIB_VERSION_OFFSET);
-
- if (eeprom_ver < EEPROM_4965_EEPROM_VERSION ||
- calib_ver < EEPROM_4965_TX_POWER_VERSION)
- goto err;
-
- return 0;
-err:
- IWL_ERROR("Unsuported EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n",
- eeprom_ver, EEPROM_4965_EEPROM_VERSION,
- calib_ver, EEPROM_4965_TX_POWER_VERSION);
- return -EINVAL;
-
+ return iwl_eeprom_query16(priv, EEPROM_4965_CALIB_VERSION_OFFSET);
}
/*
- * Activate/Deactivat Tx DMA/FIFO channels according tx fifos mask
+ * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
* must be called under priv->lock and mac access
*/
static void iwl4965_txq_set_sched(struct iwl_priv *priv, u32 mask)
@@ -366,9 +351,8 @@ static int iwl4965_apm_init(struct iwl_priv *priv)
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
/* wait for clock stabilization */
- ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+ ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
if (ret < 0) {
IWL_DEBUG_INFO("Failed to init the card\n");
goto out;
@@ -414,7 +398,7 @@ static void iwl4965_nic_config(struct iwl_priv *priv)
/* L1 is enabled by BIOS */
if ((link & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN)
- /* diable L0S disabled L1A enabled */
+ /* disable L0S disabled L1A enabled */
iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
else
/* L0S enabled L1A disabled */
@@ -442,7 +426,6 @@ static void iwl4965_nic_config(struct iwl_priv *priv)
static int iwl4965_apm_stop_master(struct iwl_priv *priv)
{
- int ret = 0;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
@@ -450,17 +433,13 @@ static int iwl4965_apm_stop_master(struct iwl_priv *priv)
/* set stop master bit */
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
- ret = iwl_poll_bit(priv, CSR_RESET,
- CSR_RESET_REG_FLAG_MASTER_DISABLED,
- CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
- if (ret < 0)
- goto out;
+ iwl_poll_direct_bit(priv, CSR_RESET,
+ CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
-out:
spin_unlock_irqrestore(&priv->lock, flags);
IWL_DEBUG_INFO("stop master\n");
- return ret;
+ return 0;
}
static void iwl4965_apm_stop(struct iwl_priv *priv)
@@ -496,11 +475,9 @@ static int iwl4965_apm_reset(struct iwl_priv *priv)
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
- ret = iwl_poll_bit(priv, CSR_RESET,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25);
-
- if (ret)
+ ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+ if (ret < 0)
goto out;
udelay(10);
@@ -537,10 +514,10 @@ static void iwl4965_chain_noise_reset(struct iwl_priv *priv)
struct iwl_chain_noise_data *data = &(priv->chain_noise_data);
if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) {
- struct iwl4965_calibration_cmd cmd;
+ struct iwl_calib_diff_gain_cmd cmd;
memset(&cmd, 0, sizeof(cmd));
- cmd.opCode = PHY_CALIBRATE_DIFF_GAIN_CMD;
+ cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD;
cmd.diff_gain_a = 0;
cmd.diff_gain_b = 0;
cmd.diff_gain_c = 0;
@@ -587,11 +564,11 @@ static void iwl4965_gain_computation(struct iwl_priv *priv,
/* Differential gain gets sent to uCode only once */
if (!data->radio_write) {
- struct iwl4965_calibration_cmd cmd;
+ struct iwl_calib_diff_gain_cmd cmd;
data->radio_write = 1;
memset(&cmd, 0, sizeof(cmd));
- cmd.opCode = PHY_CALIBRATE_DIFF_GAIN_CMD;
+ cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD;
cmd.diff_gain_a = data->delta_gain_code[0];
cmd.diff_gain_b = data->delta_gain_code[1];
cmd.diff_gain_c = data->delta_gain_code[2];
@@ -619,10 +596,10 @@ static void iwl4965_gain_computation(struct iwl_priv *priv,
static void iwl4965_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
__le32 *tx_flags)
{
- if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
*tx_flags |= TX_CMD_FLG_RTS_MSK;
*tx_flags &= ~TX_CMD_FLG_CTS_MSK;
- } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
+ } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
*tx_flags |= TX_CMD_FLG_CTS_MSK;
}
@@ -643,7 +620,7 @@ static void iwl4965_bg_txpower_work(struct work_struct *work)
mutex_lock(&priv->mutex);
- /* Regardless of if we are assocaited, we must reconfigure the
+ /* Regardless of if we are associated, we must reconfigure the
* TX power since frames can be sent on non-radar channels while
* not associated */
iwl4965_send_tx_power(priv);
@@ -679,7 +656,7 @@ static void iwl4965_tx_queue_set_status(struct iwl_priv *priv,
int txq_id = txq->q.id;
/* Find out whether to activate Tx queue */
- int active = test_bit(txq_id, &priv->txq_ctx_active_msk)?1:0;
+ int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0;
/* Set up and activate */
iwl_write_prph(priv, IWL49_SCD_QUEUE_STATUS_BITS(txq_id),
@@ -709,9 +686,10 @@ static const u16 default_queue_to_tx_fifo[] = {
static int iwl4965_alive_notify(struct iwl_priv *priv)
{
u32 a;
- int i = 0;
unsigned long flags;
int ret;
+ int i, chan;
+ u32 reg_val;
spin_lock_irqsave(&priv->lock, flags);
@@ -733,8 +711,18 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
/* Tel 4965 where to find Tx byte count tables */
iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR,
- (priv->shared_phys +
- offsetof(struct iwl4965_shared, queues_byte_cnt_tbls)) >> 10);
+ priv->scd_bc_tbls.dma >> 10);
+
+ /* Enable DMA channel */
+ for (chan = 0; chan < FH49_TCSR_CHNL_NUM ; chan++)
+ iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan),
+ FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
+ FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
+
+ /* Update FH chicken bits */
+ reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG);
+ iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG,
+ reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
/* Disable chain mode for all queues */
iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0);
@@ -766,7 +754,7 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
(1 << priv->hw_params.max_txq_num) - 1);
/* Activate all Tx DMA/FIFO channels */
- priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7));
+ priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 6));
iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
@@ -822,7 +810,9 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
}
priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
- priv->hw_params.first_ampdu_q = IWL49_FIRST_AMPDU_QUEUE;
+ priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM;
+ priv->hw_params.scd_bc_tbls_size =
+ IWL49_NUM_QUEUES * sizeof(struct iwl4965_scd_bc_tbl);
priv->hw_params.max_stations = IWL4965_STATION_COUNT;
priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID;
priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE;
@@ -1650,36 +1640,6 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
}
#endif
-static int iwl4965_shared_mem_rx_idx(struct iwl_priv *priv)
-{
- struct iwl4965_shared *s = priv->shared_virt;
- return le32_to_cpu(s->rb_closed) & 0xFFF;
-}
-
-static int iwl4965_alloc_shared_mem(struct iwl_priv *priv)
-{
- priv->shared_virt = pci_alloc_consistent(priv->pci_dev,
- sizeof(struct iwl4965_shared),
- &priv->shared_phys);
- if (!priv->shared_virt)
- return -ENOMEM;
-
- memset(priv->shared_virt, 0, sizeof(struct iwl4965_shared));
-
- priv->rb_closed_offset = offsetof(struct iwl4965_shared, rb_closed);
-
- return 0;
-}
-
-static void iwl4965_free_shared_mem(struct iwl_priv *priv)
-{
- if (priv->shared_virt)
- pci_free_consistent(priv->pci_dev,
- sizeof(struct iwl4965_shared),
- priv->shared_virt,
- priv->shared_phys);
-}
-
/**
* iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
*/
@@ -1687,21 +1647,22 @@ static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
struct iwl_tx_queue *txq,
u16 byte_cnt)
{
- int len;
+ struct iwl4965_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
int txq_id = txq->q.id;
- struct iwl4965_shared *shared_data = priv->shared_virt;
+ int write_ptr = txq->q.write_ptr;
+ int len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
+ __le16 bc_ent;
- len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
+ WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
+ bc_ent = cpu_to_le16(len & 0xFFF);
/* Set up byte count within first 256 entries */
- IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
- tfd_offset[txq->q.write_ptr], byte_cnt, len);
+ scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
/* If within first 64 entries, duplicate at end */
- if (txq->q.write_ptr < IWL49_MAX_WIN_SIZE)
- IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
- tfd_offset[IWL49_QUEUE_SIZE + txq->q.write_ptr],
- byte_cnt, len);
+ if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
+ scd_bc_tbl[txq_id].
+ tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
}
/**
@@ -1956,7 +1917,7 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
ra_tid = BUILD_RAxTID(sta_id, tid);
/* Modify device's station table to Tx this TID */
- iwl_sta_modify_enable_tid_tx(priv, sta_id, tid);
+ iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
spin_lock_irqsave(&priv->lock, flags);
ret = iwl_grab_nic_access(priv);
@@ -2037,7 +1998,7 @@ static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp)
}
/**
- * iwl4965_tx_status_reply_tx - Handle Tx rspnse for frames in aggregation queue
+ * iwl4965_tx_status_reply_tx - Handle Tx response for frames in aggregation queue
*/
static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
struct iwl_ht_agg *agg,
@@ -2059,7 +2020,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
agg->rate_n_flags = rate_n_flags;
agg->bitmap = 0;
- /* # frames attempted by Tx command */
+ /* num frames attempted by Tx command */
if (agg->frame_count == 1) {
/* Only one frame was attempted; no block-ack will arrive */
status = le16_to_cpu(frame_status[0].status);
@@ -2070,9 +2031,9 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
agg->frame_count, agg->start_idx, idx);
info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]);
- info->status.retry_count = tx_resp->failure_frame;
+ info->status.rates[0].count = tx_resp->failure_frame + 1;
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
- info->flags |= iwl_is_tx_success(status)?
+ info->flags |= iwl_is_tx_success(status) ?
IEEE80211_TX_STAT_ACK : 0;
iwl_hwrate_to_tx_control(priv, rate_n_flags, info);
/* FIXME: code repetition end */
@@ -2158,12 +2119,13 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
int txq_id = SEQ_TO_QUEUE(sequence);
int index = SEQ_TO_INDEX(sequence);
struct iwl_tx_queue *txq = &priv->txq[txq_id];
+ struct ieee80211_hdr *hdr;
struct ieee80211_tx_info *info;
struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
u32 status = le32_to_cpu(tx_resp->u.status);
- int tid = MAX_TID_COUNT, sta_id = IWL_INVALID_STATION;
- __le16 fc;
- struct ieee80211_hdr *hdr;
+ int tid = MAX_TID_COUNT;
+ int sta_id;
+ int freed;
u8 *qc = NULL;
if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
@@ -2178,8 +2140,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
memset(&info->status, 0, sizeof(info->status));
hdr = iwl_tx_queue_get_hdr(priv, txq_id, index);
- fc = hdr->frame_control;
- if (ieee80211_is_data_qos(fc)) {
+ if (ieee80211_is_data_qos(hdr->frame_control)) {
qc = ieee80211_get_qos_ctl(hdr);
tid = qc[0] & 0xf;
}
@@ -2194,8 +2155,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
struct iwl_ht_agg *agg = NULL;
- if (!qc)
- return;
+ WARN_ON(!qc);
agg = &priv->stations[sta_id].tid[tid].agg;
@@ -2206,54 +2166,49 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
if (txq->q.read_ptr != (scd_ssn & 0xff)) {
- int freed, ampdu_q;
index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
"%d index %d\n", scd_ssn , index);
freed = iwl_tx_queue_reclaim(priv, txq_id, index);
priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
- if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
- txq_id >= 0 && priv->mac80211_registered &&
- agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) {
- /* calculate mac80211 ampdu sw queue to wake */
- ampdu_q = txq_id - IWL49_FIRST_AMPDU_QUEUE +
- priv->hw->queues;
+ if (priv->mac80211_registered &&
+ (iwl_queue_space(&txq->q) > txq->q.low_mark) &&
+ (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) {
if (agg->state == IWL_AGG_OFF)
ieee80211_wake_queue(priv->hw, txq_id);
else
- ieee80211_wake_queue(priv->hw, ampdu_q);
+ ieee80211_wake_queue(priv->hw,
+ txq->swq_id);
}
- iwl_txq_check_empty(priv, sta_id, tid, txq_id);
}
} else {
- info->status.retry_count = tx_resp->failure_frame;
- info->flags |=
- iwl_is_tx_success(status) ? IEEE80211_TX_STAT_ACK : 0;
+ info->status.rates[0].count = tx_resp->failure_frame + 1;
+ info->flags |= iwl_is_tx_success(status) ?
+ IEEE80211_TX_STAT_ACK : 0;
iwl_hwrate_to_tx_control(priv,
le32_to_cpu(tx_resp->rate_n_flags),
info);
- IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags "
- "0x%x retries %d\n", txq_id,
- iwl_get_tx_fail_reason(status),
- status, le32_to_cpu(tx_resp->rate_n_flags),
- tx_resp->failure_frame);
+ IWL_DEBUG_TX_REPLY("TXQ %d status %s (0x%08x) "
+ "rate_n_flags 0x%x retries %d\n",
+ txq_id,
+ iwl_get_tx_fail_reason(status), status,
+ le32_to_cpu(tx_resp->rate_n_flags),
+ tx_resp->failure_frame);
- IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
-
- if (index != -1) {
- int freed = iwl_tx_queue_reclaim(priv, txq_id, index);
- if (tid != MAX_TID_COUNT)
+ freed = iwl_tx_queue_reclaim(priv, txq_id, index);
+ if (qc && likely(sta_id != IWL_INVALID_STATION))
priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
- if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
- (txq_id >= 0) && priv->mac80211_registered)
+
+ if (priv->mac80211_registered &&
+ (iwl_queue_space(&txq->q) > txq->q.low_mark))
ieee80211_wake_queue(priv->hw, txq_id);
- if (tid != MAX_TID_COUNT)
- iwl_txq_check_empty(priv, sta_id, tid, txq_id);
- }
}
+ if (qc && likely(sta_id != IWL_INVALID_STATION))
+ iwl_txq_check_empty(priv, sta_id, tid, txq_id);
+
if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n");
}
@@ -2328,9 +2283,6 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
static struct iwl_lib_ops iwl4965_lib = {
.set_hw_params = iwl4965_hw_set_hw_params,
- .alloc_shared_mem = iwl4965_alloc_shared_mem,
- .free_shared_mem = iwl4965_free_shared_mem,
- .shared_mem_rx_idx = iwl4965_shared_mem_rx_idx,
.txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl,
.txq_set_sched = iwl4965_txq_set_sched,
.txq_agg_enable = iwl4965_txq_agg_enable,
@@ -2347,7 +2299,7 @@ static struct iwl_lib_ops iwl4965_lib = {
.reset = iwl4965_apm_reset,
.stop = iwl4965_apm_stop,
.config = iwl4965_nic_config,
- .set_pwr_src = iwl4965_set_pwr_src,
+ .set_pwr_src = iwl_set_pwr_src,
},
.eeprom_ops = {
.regulatory_bands = {
@@ -2362,11 +2314,11 @@ static struct iwl_lib_ops iwl4965_lib = {
.verify_signature = iwlcore_eeprom_verify_signature,
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
.release_semaphore = iwlcore_eeprom_release_semaphore,
- .check_version = iwl4965_eeprom_check_version,
+ .calib_version = iwl4965_eeprom_calib_version,
.query_addr = iwlcore_eeprom_query_addr,
},
.send_tx_power = iwl4965_send_tx_power,
- .update_chain_flags = iwl4965_update_chain_flags,
+ .update_chain_flags = iwl_update_chain_flags,
.temperature = iwl4965_temperature_calib,
};
@@ -2378,15 +2330,19 @@ static struct iwl_ops iwl4965_ops = {
struct iwl_cfg iwl4965_agn_cfg = {
.name = "4965AGN",
- .fw_name = "iwlwifi-4965" IWL4965_UCODE_API ".ucode",
+ .fw_name_pre = IWL4965_FW_PRE,
+ .ucode_api_max = IWL4965_UCODE_API_MAX,
+ .ucode_api_min = IWL4965_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.eeprom_size = IWL4965_EEPROM_IMG_SIZE,
+ .eeprom_ver = EEPROM_4965_EEPROM_VERSION,
+ .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION,
.ops = &iwl4965_ops,
.mod_params = &iwl4965_mod_params,
};
/* Module firmware */
-MODULE_FIRMWARE("iwlwifi-4965" IWL4965_UCODE_API ".ucode");
+MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX));
module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444);
MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
@@ -2394,7 +2350,7 @@ module_param_named(disable, iwl4965_mod_params.disable, int, 0444);
MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444);
MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
-module_param_named(debug, iwl4965_mod_params.debug, int, 0444);
+module_param_named(debug, iwl4965_mod_params.debug, uint, 0444);
MODULE_PARM_DESC(debug, "debug output mask");
module_param_named(
disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, 0444);
@@ -2402,9 +2358,6 @@ MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, 0444);
MODULE_PARM_DESC(queues_num, "number of hw queues.");
-/* QoS */
-module_param_named(qos_enable, iwl4965_mod_params.enable_qos, int, 0444);
-MODULE_PARM_DESC(qos_enable, "enable all QoS functionality");
/* 11n */
module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, 0444);
MODULE_PARM_DESC(11n_disable, "disable 11n functionality");
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
index c479ee211c5c..82c3859ce0f8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
@@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@@ -73,69 +73,27 @@
#define IWL50_RTC_INST_SIZE (IWL50_RTC_INST_UPPER_BOUND - RTC_INST_LOWER_BOUND)
#define IWL50_RTC_DATA_SIZE (IWL50_RTC_DATA_UPPER_BOUND - RTC_DATA_LOWER_BOUND)
-/* EERPROM */
+/* EEPROM */
#define IWL_5000_EEPROM_IMG_SIZE 2048
-
-#define IWL50_MAX_WIN_SIZE 64
-#define IWL50_QUEUE_SIZE 256
#define IWL50_CMD_FIFO_NUM 7
#define IWL50_NUM_QUEUES 20
#define IWL50_NUM_AMPDU_QUEUES 10
#define IWL50_FIRST_AMPDU_QUEUE 10
-#define IWL_sta_id_POS 12
-#define IWL_sta_id_LEN 4
-#define IWL_sta_id_SYM val
-
/* Fixed (non-configurable) rx data from phy */
-/* Base physical address of iwl5000_shared is provided to SCD_DRAM_BASE_ADDR
- * and &iwl5000_shared.val0 is provided to FH_RSCSR_CHNL0_STTS_WPTR_REG */
-struct iwl5000_sched_queue_byte_cnt_tbl {
- struct iwl4965_queue_byte_cnt_entry tfd_offset[IWL50_QUEUE_SIZE +
- IWL50_MAX_WIN_SIZE];
-} __attribute__ ((packed));
-
-struct iwl5000_shared {
- struct iwl5000_sched_queue_byte_cnt_tbl
- queues_byte_cnt_tbls[IWL50_NUM_QUEUES];
- __le32 rb_closed;
-
- /* __le32 rb_closed_stts_rb_num:12; */
-#define IWL_rb_closed_stts_rb_num_POS 0
-#define IWL_rb_closed_stts_rb_num_LEN 12
-#define IWL_rb_closed_stts_rb_num_SYM rb_closed
- /* __le32 rsrv1:4; */
- /* __le32 rb_closed_stts_rx_frame_num:12; */
-#define IWL_rb_closed_stts_rx_frame_num_POS 16
-#define IWL_rb_closed_stts_rx_frame_num_LEN 12
-#define IWL_rb_closed_stts_rx_frame_num_SYM rb_closed
- /* __le32 rsrv2:4; */
-
- __le32 frm_finished;
- /* __le32 frame_finished_stts_rb_num:12; */
-#define IWL_frame_finished_stts_rb_num_POS 0
-#define IWL_frame_finished_stts_rb_num_LEN 12
-#define IWL_frame_finished_stts_rb_num_SYM frm_finished
- /* __le32 rsrv3:4; */
- /* __le32 frame_finished_stts_rx_frame_num:12; */
-#define IWL_frame_finished_stts_rx_frame_num_POS 16
-#define IWL_frame_finished_stts_rx_frame_num_LEN 12
-#define IWL_frame_finished_stts_rx_frame_num_SYM frm_finished
- /* __le32 rsrv4:4; */
-
- __le32 padding1; /* so that allocation will be aligned to 16B */
- __le32 padding2;
+/**
+ * struct iwl5000_schedq_bc_tbl scheduler byte count table
+ * base physical address of iwl5000_shared
+ * is provided to SCD_DRAM_BASE_ADDR
+ * @tfd_offset 0-12 - tx command byte count
+ * 12-16 - station index
+ */
+struct iwl5000_scd_bc_tbl {
+ __le16 tfd_offset[TFD_QUEUE_BC_SIZE];
} __attribute__ ((packed));
-/* calibrations defined for 5000 */
-/* defines the order in which results should be sent to the runtime uCode */
-enum iwl5000_calib {
- IWL5000_CALIB_LO,
- IWL5000_CALIB_TX_IQ,
- IWL5000_CALIB_TX_IQ_PERD,
-};
#endif /* __iwl_5000_hw_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 5155b8a760a7..66d053d28a74 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -44,7 +44,21 @@
#include "iwl-helpers.h"
#include "iwl-5000-hw.h"
-#define IWL5000_UCODE_API "-1"
+/* Highest firmware API version supported */
+#define IWL5000_UCODE_API_MAX 1
+#define IWL5150_UCODE_API_MAX 1
+
+/* Lowest firmware API version supported */
+#define IWL5000_UCODE_API_MIN 1
+#define IWL5150_UCODE_API_MIN 1
+
+#define IWL5000_FW_PRE "iwlwifi-5000-"
+#define _IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE #api ".ucode"
+#define IWL5000_MODULE_FIRMWARE(api) _IWL5000_MODULE_FIRMWARE(api)
+
+#define IWL5150_FW_PRE "iwlwifi-5150-"
+#define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode"
+#define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api)
static const u16 iwl5000_default_queue_to_tx_fifo[] = {
IWL_TX_FIFO_AC3,
@@ -59,7 +73,6 @@ static const u16 iwl5000_default_queue_to_tx_fifo[] = {
/* FIXME: same implementation as 4965 */
static int iwl5000_apm_stop_master(struct iwl_priv *priv)
{
- int ret = 0;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags);
@@ -67,17 +80,13 @@ static int iwl5000_apm_stop_master(struct iwl_priv *priv)
/* set stop master bit */
iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
- ret = iwl_poll_bit(priv, CSR_RESET,
- CSR_RESET_REG_FLAG_MASTER_DISABLED,
+ iwl_poll_direct_bit(priv, CSR_RESET,
CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
- if (ret < 0)
- goto out;
-out:
spin_unlock_irqrestore(&priv->lock, flags);
IWL_DEBUG_INFO("stop master\n");
- return ret;
+ return 0;
}
@@ -92,7 +101,7 @@ static int iwl5000_apm_init(struct iwl_priv *priv)
iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS,
CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
- /* Set FH wait treshold to maximum (HW error during stress W/A) */
+ /* Set FH wait threshold to maximum (HW error during stress W/A) */
iwl_set_bit(priv, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL);
/* enable HAP INTA to move device L1a -> L0s */
@@ -106,9 +115,8 @@ static int iwl5000_apm_init(struct iwl_priv *priv)
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
/* wait for clock stabilization */
- ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+ ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
if (ret < 0) {
IWL_DEBUG_INFO("Failed to init the card\n");
return ret;
@@ -132,7 +140,7 @@ static int iwl5000_apm_init(struct iwl_priv *priv)
return ret;
}
-/* FIXME: this is indentical to 4965 */
+/* FIXME: this is identical to 4965 */
static void iwl5000_apm_stop(struct iwl_priv *priv)
{
unsigned long flags;
@@ -175,9 +183,8 @@ static int iwl5000_apm_reset(struct iwl_priv *priv)
iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
/* wait for clock stabilization */
- ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+ ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
if (ret < 0) {
IWL_DEBUG_INFO("Failed to init the card\n");
goto out;
@@ -217,7 +224,7 @@ static void iwl5000_nic_config(struct iwl_priv *priv)
/* L1 is enabled by BIOS */
if ((link & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN)
- /* diable L0S disabled L1A enabled */
+ /* disable L0S disabled L1A enabled */
iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
else
/* L0S enabled L1A disabled */
@@ -291,30 +298,17 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
return (address & ADDRESS_MSK) + (offset << 1);
}
-static int iwl5000_eeprom_check_version(struct iwl_priv *priv)
+static u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv)
{
- u16 eeprom_ver;
struct iwl_eeprom_calib_hdr {
u8 version;
u8 pa_type;
u16 voltage;
} *hdr;
- eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
-
hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv,
EEPROM_5000_CALIB_ALL);
-
- if (eeprom_ver < EEPROM_5000_EEPROM_VERSION ||
- hdr->version < EEPROM_5000_TX_POWER_VERSION)
- goto err;
-
- return 0;
-err:
- IWL_ERROR("Unsuported EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n",
- eeprom_ver, EEPROM_5000_EEPROM_VERSION,
- hdr->version, EEPROM_5000_TX_POWER_VERSION);
- return -EINVAL;
+ return hdr->version;
}
@@ -348,10 +342,14 @@ static void iwl5000_gain_computation(struct iwl_priv *priv,
data->delta_gain_code[1], data->delta_gain_code[2]);
if (!data->radio_write) {
- struct iwl5000_calibration_chain_noise_gain_cmd cmd;
+ struct iwl_calib_chain_noise_gain_cmd cmd;
+
memset(&cmd, 0, sizeof(cmd));
- cmd.op_code = IWL5000_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD;
+ cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD;
+ cmd.hdr.first_group = 0;
+ cmd.hdr.groups_num = 1;
+ cmd.hdr.data_valid = 1;
cmd.delta_gain_1 = data->delta_gain_code[1];
cmd.delta_gain_2 = data->delta_gain_code[2];
iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD,
@@ -373,14 +371,19 @@ static void iwl5000_gain_computation(struct iwl_priv *priv,
static void iwl5000_chain_noise_reset(struct iwl_priv *priv)
{
struct iwl_chain_noise_data *data = &priv->chain_noise_data;
+ int ret;
if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) {
- struct iwl5000_calibration_chain_noise_reset_cmd cmd;
-
+ struct iwl_calib_chain_noise_reset_cmd cmd;
memset(&cmd, 0, sizeof(cmd));
- cmd.op_code = IWL5000_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD;
- if (iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
- sizeof(cmd), &cmd))
+
+ cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD;
+ cmd.hdr.first_group = 0;
+ cmd.hdr.groups_num = 1;
+ cmd.hdr.data_valid = 1;
+ ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
+ sizeof(cmd), &cmd);
+ if (ret)
IWL_ERROR("Could not send REPLY_PHY_CALIBRATION_CMD\n");
data->state = IWL_CHAIN_NOISE_ACCUMULATE;
IWL_DEBUG_CALIB("Run chain_noise_calibrate\n");
@@ -390,8 +393,8 @@ static void iwl5000_chain_noise_reset(struct iwl_priv *priv)
static void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
__le32 *tx_flags)
{
- if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) ||
- (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT))
+ if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) ||
+ (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT))
*tx_flags |= TX_CMD_FLG_RTS_CTS_MSK;
else
*tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK;
@@ -426,31 +429,41 @@ static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
return &priv->eeprom[address];
}
+static s32 iwl5150_get_ct_threshold(struct iwl_priv *priv)
+{
+ const s32 volt2temp_coef = -5;
+ u16 *temp_calib = (u16 *)iwl_eeprom_query_addr(priv,
+ EEPROM_5000_TEMPERATURE);
+ /* offset = temperate - voltage / coef */
+ s32 offset = temp_calib[0] - temp_calib[1] / volt2temp_coef;
+ s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD) - offset;
+ return threshold * volt2temp_coef;
+}
+
/*
* Calibration
*/
-static int iwl5000_send_Xtal_calib(struct iwl_priv *priv)
+static int iwl5000_set_Xtal_calib(struct iwl_priv *priv)
{
+ struct iwl_calib_xtal_freq_cmd cmd;
u16 *xtal_calib = (u16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL);
- struct iwl5000_calibration cal_cmd = {
- .op_code = IWL5000_PHY_CALIBRATE_CRYSTAL_FRQ_CMD,
- .data = {
- (u8)xtal_calib[0],
- (u8)xtal_calib[1],
- }
- };
-
- return iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
- sizeof(cal_cmd), &cal_cmd);
+ cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD;
+ cmd.hdr.first_group = 0;
+ cmd.hdr.groups_num = 1;
+ cmd.hdr.data_valid = 1;
+ cmd.cap_pin1 = (u8)xtal_calib[0];
+ cmd.cap_pin2 = (u8)xtal_calib[1];
+ return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL],
+ (u8 *)&cmd, sizeof(cmd));
}
static int iwl5000_send_calib_cfg(struct iwl_priv *priv)
{
- struct iwl5000_calib_cfg_cmd calib_cfg_cmd;
+ struct iwl_calib_cfg_cmd calib_cfg_cmd;
struct iwl_host_cmd cmd = {
.id = CALIBRATION_CFG_CMD,
- .len = sizeof(struct iwl5000_calib_cfg_cmd),
+ .len = sizeof(struct iwl_calib_cfg_cmd),
.data = &calib_cfg_cmd,
};
@@ -467,7 +480,7 @@ static void iwl5000_rx_calib_result(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
- struct iwl5000_calib_hdr *hdr = (struct iwl5000_calib_hdr *)pkt->u.raw;
+ struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw;
int len = le32_to_cpu(pkt->len) & FH_RSCSR_FRAME_SIZE_MSK;
int index;
@@ -478,14 +491,20 @@ static void iwl5000_rx_calib_result(struct iwl_priv *priv,
* uCode. iwl_send_calib_results sends them in a row according to their
* index. We sort them here */
switch (hdr->op_code) {
- case IWL5000_PHY_CALIBRATE_LO_CMD:
- index = IWL5000_CALIB_LO;
+ case IWL_PHY_CALIBRATE_DC_CMD:
+ index = IWL_CALIB_DC;
+ break;
+ case IWL_PHY_CALIBRATE_LO_CMD:
+ index = IWL_CALIB_LO;
break;
- case IWL5000_PHY_CALIBRATE_TX_IQ_CMD:
- index = IWL5000_CALIB_TX_IQ;
+ case IWL_PHY_CALIBRATE_TX_IQ_CMD:
+ index = IWL_CALIB_TX_IQ;
break;
- case IWL5000_PHY_CALIBRATE_TX_IQ_PERD_CMD:
- index = IWL5000_CALIB_TX_IQ_PERD;
+ case IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD:
+ index = IWL_CALIB_TX_IQ_PERD;
+ break;
+ case IWL_PHY_CALIBRATE_BASE_BAND_CMD:
+ index = IWL_CALIB_BASE_BAND;
break;
default:
IWL_ERROR("Unknown calibration notification %d\n",
@@ -535,7 +554,7 @@ static int iwl5000_load_section(struct iwl_priv *priv,
iwl_write_direct32(priv,
FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL),
- (iwl_get_dma_hi_address(phy_addr)
+ (iwl_get_dma_hi_addr(phy_addr)
<< FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt);
iwl_write_direct32(priv,
@@ -547,7 +566,7 @@ static int iwl5000_load_section(struct iwl_priv *priv,
iwl_write_direct32(priv,
FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
- FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL |
+ FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE |
FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
iwl_release_nic_access(priv);
@@ -561,14 +580,13 @@ static int iwl5000_load_given_ucode(struct iwl_priv *priv,
{
int ret = 0;
- ret = iwl5000_load_section(
- priv, inst_image, RTC_INST_LOWER_BOUND);
+ ret = iwl5000_load_section(priv, inst_image, RTC_INST_LOWER_BOUND);
if (ret)
return ret;
IWL_DEBUG_INFO("INST uCode section being loaded...\n");
ret = wait_event_interruptible_timeout(priv->wait_command_queue,
- priv->ucode_write_complete, 5 * HZ);
+ priv->ucode_write_complete, 5 * HZ);
if (ret == -ERESTARTSYS) {
IWL_ERROR("Could not load the INST uCode section due "
"to interrupt\n");
@@ -682,7 +700,7 @@ static void iwl5000_tx_queue_set_status(struct iwl_priv *priv,
int tx_fifo_id, int scd_retry)
{
int txq_id = txq->q.id;
- int active = test_bit(txq_id, &priv->txq_ctx_active_msk)?1:0;
+ int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0;
iwl_write_prph(priv, IWL50_SCD_QUEUE_STATUS_BITS(txq_id),
(active << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
@@ -710,9 +728,10 @@ static int iwl5000_send_wimax_coex(struct iwl_priv *priv)
static int iwl5000_alive_notify(struct iwl_priv *priv)
{
u32 a;
- int i = 0;
unsigned long flags;
int ret;
+ int i, chan;
+ u32 reg_val;
spin_lock_irqsave(&priv->lock, flags);
@@ -734,11 +753,21 @@ static int iwl5000_alive_notify(struct iwl_priv *priv)
iwl_write_targ_mem(priv, a, 0);
iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR,
- (priv->shared_phys +
- offsetof(struct iwl5000_shared, queues_byte_cnt_tbls)) >> 10);
+ priv->scd_bc_tbls.dma >> 10);
+
+ /* Enable DMA channel */
+ for (chan = 0; chan < FH50_TCSR_CHNL_NUM ; chan++)
+ iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan),
+ FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
+ FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
+
+ /* Update FH chicken bits */
+ reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG);
+ iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG,
+ reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
+
iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL,
- IWL50_SCD_QUEUECHAIN_SEL_ALL(
- priv->hw_params.max_txq_num));
+ IWL50_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num));
iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0);
/* initiate the queues */
@@ -765,6 +794,7 @@ static int iwl5000_alive_notify(struct iwl_priv *priv)
priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7));
iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0);
+
/* map qos queues to fifos one-to-one */
for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) {
int ac = iwl5000_default_queue_to_tx_fifo[i];
@@ -784,10 +814,8 @@ static int iwl5000_alive_notify(struct iwl_priv *priv)
iwl5000_send_wimax_coex(priv);
- iwl5000_send_Xtal_calib(priv);
-
- if (priv->ucode_type == UCODE_RT)
- iwl_send_calib_results(priv);
+ iwl5000_set_Xtal_calib(priv);
+ iwl_send_calib_results(priv);
return 0;
}
@@ -802,7 +830,9 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
}
priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
- priv->hw_params.first_ampdu_q = IWL50_FIRST_AMPDU_QUEUE;
+ priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
+ priv->hw_params.scd_bc_tbls_size =
+ IWL50_NUM_QUEUES * sizeof(struct iwl5000_scd_bc_tbl);
priv->hw_params.max_stations = IWL5000_STATION_COUNT;
priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE;
@@ -814,10 +844,14 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
case CSR_HW_REV_TYPE_5100:
+ priv->hw_params.tx_chains_num = 1;
+ priv->hw_params.rx_chains_num = 2;
+ priv->hw_params.valid_tx_ant = ANT_B;
+ priv->hw_params.valid_rx_ant = ANT_AB;
+ break;
case CSR_HW_REV_TYPE_5150:
priv->hw_params.tx_chains_num = 1;
priv->hw_params.rx_chains_num = 2;
- /* FIXME: move to ANT_A, ANT_B, ANT_C enum */
priv->hw_params.valid_tx_ant = ANT_A;
priv->hw_params.valid_rx_ant = ANT_AB;
break;
@@ -840,43 +874,36 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
case CSR_HW_REV_TYPE_5150:
/* 5150 wants in Kelvin */
priv->hw_params.ct_kill_threshold =
- CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD);
+ iwl5150_get_ct_threshold(priv);
break;
}
- return 0;
-}
-
-static int iwl5000_alloc_shared_mem(struct iwl_priv *priv)
-{
- priv->shared_virt = pci_alloc_consistent(priv->pci_dev,
- sizeof(struct iwl5000_shared),
- &priv->shared_phys);
- if (!priv->shared_virt)
- return -ENOMEM;
+ /* Set initial calibration set */
+ switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
+ case CSR_HW_REV_TYPE_5100:
+ case CSR_HW_REV_TYPE_5300:
+ case CSR_HW_REV_TYPE_5350:
+ priv->hw_params.calib_init_cfg =
+ BIT(IWL_CALIB_XTAL) |
+ BIT(IWL_CALIB_LO) |
+ BIT(IWL_CALIB_TX_IQ) |
+ BIT(IWL_CALIB_TX_IQ_PERD) |
+ BIT(IWL_CALIB_BASE_BAND);
+ break;
+ case CSR_HW_REV_TYPE_5150:
+ priv->hw_params.calib_init_cfg =
+ BIT(IWL_CALIB_DC) |
+ BIT(IWL_CALIB_LO) |
+ BIT(IWL_CALIB_TX_IQ) |
+ BIT(IWL_CALIB_BASE_BAND);
- memset(priv->shared_virt, 0, sizeof(struct iwl5000_shared));
+ break;
+ }
- priv->rb_closed_offset = offsetof(struct iwl5000_shared, rb_closed);
return 0;
}
-static void iwl5000_free_shared_mem(struct iwl_priv *priv)
-{
- if (priv->shared_virt)
- pci_free_consistent(priv->pci_dev,
- sizeof(struct iwl5000_shared),
- priv->shared_virt,
- priv->shared_phys);
-}
-
-static int iwl5000_shared_mem_rx_idx(struct iwl_priv *priv)
-{
- struct iwl5000_shared *s = priv->shared_virt;
- return le32_to_cpu(s->rb_closed) & 0xFFF;
-}
-
/**
* iwl5000_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
*/
@@ -884,16 +911,18 @@ static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
struct iwl_tx_queue *txq,
u16 byte_cnt)
{
- struct iwl5000_shared *shared_data = priv->shared_virt;
+ struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
+ int write_ptr = txq->q.write_ptr;
int txq_id = txq->q.id;
u8 sec_ctl = 0;
- u8 sta = 0;
- int len;
+ u8 sta_id = 0;
+ u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
+ __le16 bc_ent;
- len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
+ WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
if (txq_id != IWL_CMD_QUEUE_NUM) {
- sta = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
+ sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id;
sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl;
switch (sec_ctl & TX_CMD_SEC_MSK) {
@@ -909,40 +938,35 @@ static void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
}
}
- IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
- tfd_offset[txq->q.write_ptr], byte_cnt, len);
+ bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12));
- IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
- tfd_offset[txq->q.write_ptr], sta_id, sta);
+ scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
- if (txq->q.write_ptr < IWL50_MAX_WIN_SIZE) {
- IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
- tfd_offset[IWL50_QUEUE_SIZE + txq->q.write_ptr],
- byte_cnt, len);
- IWL_SET_BITS16(shared_data->queues_byte_cnt_tbls[txq_id].
- tfd_offset[IWL50_QUEUE_SIZE + txq->q.write_ptr],
- sta_id, sta);
- }
+ if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP)
+ scd_bc_tbl[txq_id].
+ tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
}
static void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv,
struct iwl_tx_queue *txq)
{
+ struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
int txq_id = txq->q.id;
- struct iwl5000_shared *shared_data = priv->shared_virt;
- u8 sta = 0;
+ int read_ptr = txq->q.read_ptr;
+ u8 sta_id = 0;
+ __le16 bc_ent;
+
+ WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX);
if (txq_id != IWL_CMD_QUEUE_NUM)
- sta = txq->cmd[txq->q.read_ptr]->cmd.tx.sta_id;
+ sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id;
- shared_data->queues_byte_cnt_tbls[txq_id].tfd_offset[txq->q.read_ptr].
- val = cpu_to_le16(1 | (sta << 12));
+ bc_ent = cpu_to_le16(1 | (sta_id << 12));
+ scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent;
- if (txq->q.write_ptr < IWL50_MAX_WIN_SIZE) {
- shared_data->queues_byte_cnt_tbls[txq_id].
- tfd_offset[IWL50_QUEUE_SIZE + txq->q.read_ptr].
- val = cpu_to_le16(1 | (sta << 12));
- }
+ if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP)
+ scd_bc_tbl[txq_id].
+ tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent;
}
static int iwl5000_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
@@ -996,7 +1020,7 @@ static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
ra_tid = BUILD_RAxTID(sta_id, tid);
/* Modify device's station table to Tx this TID */
- iwl_sta_modify_enable_tid_tx(priv, sta_id, tid);
+ iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
spin_lock_irqsave(&priv->lock, flags);
ret = iwl_grab_nic_access(priv);
@@ -1089,7 +1113,7 @@ static u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
/*
- * Activate/Deactivat Tx DMA/FIFO channels according tx fifos mask
+ * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
* must be called under priv->lock and mac access
*/
static void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask)
@@ -1136,10 +1160,10 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv,
agg->frame_count, agg->start_idx, idx);
info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]);
- info->status.retry_count = tx_resp->failure_frame;
+ info->status.rates[0].count = tx_resp->failure_frame + 1;
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
- info->flags |= iwl_is_tx_success(status)?
- IEEE80211_TX_STAT_ACK : 0;
+ info->flags |= iwl_is_tx_success(status) ?
+ IEEE80211_TX_STAT_ACK : 0;
iwl_hwrate_to_tx_control(priv, rate_n_flags, info);
/* FIXME: code repetition end */
@@ -1225,9 +1249,9 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv,
struct ieee80211_tx_info *info;
struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
u32 status = le16_to_cpu(tx_resp->status.status);
- int tid = MAX_TID_COUNT, sta_id = IWL_INVALID_STATION;
- struct ieee80211_hdr *hdr;
- u8 *qc = NULL;
+ int tid;
+ int sta_id;
+ int freed;
if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
@@ -1240,25 +1264,13 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv,
info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]);
memset(&info->status, 0, sizeof(info->status));
- hdr = iwl_tx_queue_get_hdr(priv, txq_id, index);
- if (ieee80211_is_data_qos(hdr->frame_control)) {
- qc = ieee80211_get_qos_ctl(hdr);
- tid = qc[0] & 0xf;
- }
-
- sta_id = iwl_get_ra_sta_id(priv, hdr);
- if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) {
- IWL_ERROR("Station not known\n");
- return;
- }
+ tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS;
+ sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS;
if (txq->sched_retry) {
const u32 scd_ssn = iwl5000_get_scd_ssn(tx_resp);
struct iwl_ht_agg *agg = NULL;
- if (!qc)
- return;
-
agg = &priv->stations[sta_id].tid[tid].agg;
iwl5000_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index);
@@ -1268,58 +1280,58 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv,
info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
if (txq->q.read_ptr != (scd_ssn & 0xff)) {
- int freed, ampdu_q;
index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
- IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
- "%d index %d\n", scd_ssn , index);
+ IWL_DEBUG_TX_REPLY("Retry scheduler reclaim "
+ "scd_ssn=%d idx=%d txq=%d swq=%d\n",
+ scd_ssn , index, txq_id, txq->swq_id);
+
freed = iwl_tx_queue_reclaim(priv, txq_id, index);
priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
- if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
- txq_id >= 0 && priv->mac80211_registered &&
- agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) {
- /* calculate mac80211 ampdu sw queue to wake */
- ampdu_q = txq_id - IWL50_FIRST_AMPDU_QUEUE +
- priv->hw->queues;
+ if (priv->mac80211_registered &&
+ (iwl_queue_space(&txq->q) > txq->q.low_mark) &&
+ (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) {
if (agg->state == IWL_AGG_OFF)
ieee80211_wake_queue(priv->hw, txq_id);
else
- ieee80211_wake_queue(priv->hw, ampdu_q);
+ ieee80211_wake_queue(priv->hw,
+ txq->swq_id);
}
- iwl_txq_check_empty(priv, sta_id, tid, txq_id);
}
} else {
- info->status.retry_count = tx_resp->failure_frame;
- info->flags =
- iwl_is_tx_success(status) ? IEEE80211_TX_STAT_ACK : 0;
+ BUG_ON(txq_id != txq->swq_id);
+
+ info->status.rates[0].count = tx_resp->failure_frame + 1;
+ info->flags |= iwl_is_tx_success(status) ?
+ IEEE80211_TX_STAT_ACK : 0;
iwl_hwrate_to_tx_control(priv,
le32_to_cpu(tx_resp->rate_n_flags),
info);
- IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags "
- "0x%x retries %d\n", txq_id,
- iwl_get_tx_fail_reason(status),
- status, le32_to_cpu(tx_resp->rate_n_flags),
- tx_resp->failure_frame);
+ IWL_DEBUG_TX_REPLY("TXQ %d status %s (0x%08x) rate_n_flags "
+ "0x%x retries %d\n",
+ txq_id,
+ iwl_get_tx_fail_reason(status), status,
+ le32_to_cpu(tx_resp->rate_n_flags),
+ tx_resp->failure_frame);
- IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
- if (index != -1) {
- int freed = iwl_tx_queue_reclaim(priv, txq_id, index);
- if (tid != MAX_TID_COUNT)
+ freed = iwl_tx_queue_reclaim(priv, txq_id, index);
+ if (ieee80211_is_data_qos(tx_resp->frame_ctrl))
priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
- if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
- (txq_id >= 0) && priv->mac80211_registered)
+
+ if (priv->mac80211_registered &&
+ (iwl_queue_space(&txq->q) > txq->q.low_mark))
ieee80211_wake_queue(priv->hw, txq_id);
- if (tid != MAX_TID_COUNT)
- iwl_txq_check_empty(priv, sta_id, tid, txq_id);
- }
}
+ if (ieee80211_is_data_qos(tx_resp->frame_ctrl))
+ iwl_txq_check_empty(priv, sta_id, tid, txq_id);
+
if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n");
}
-/* Currently 5000 is the supperset of everything */
+/* Currently 5000 is the superset of everything */
static u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len)
{
return len;
@@ -1466,9 +1478,6 @@ static struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = {
static struct iwl_lib_ops iwl5000_lib = {
.set_hw_params = iwl5000_hw_set_hw_params,
- .alloc_shared_mem = iwl5000_alloc_shared_mem,
- .free_shared_mem = iwl5000_free_shared_mem,
- .shared_mem_rx_idx = iwl5000_shared_mem_rx_idx,
.txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
.txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl,
.txq_set_sched = iwl5000_txq_set_sched,
@@ -1482,13 +1491,13 @@ static struct iwl_lib_ops iwl5000_lib = {
.alive_notify = iwl5000_alive_notify,
.send_tx_power = iwl5000_send_tx_power,
.temperature = iwl5000_temperature,
- .update_chain_flags = iwl4965_update_chain_flags,
+ .update_chain_flags = iwl_update_chain_flags,
.apm_ops = {
.init = iwl5000_apm_init,
.reset = iwl5000_apm_reset,
.stop = iwl5000_apm_stop,
.config = iwl5000_nic_config,
- .set_pwr_src = iwl4965_set_pwr_src,
+ .set_pwr_src = iwl_set_pwr_src,
},
.eeprom_ops = {
.regulatory_bands = {
@@ -1503,7 +1512,7 @@ static struct iwl_lib_ops iwl5000_lib = {
.verify_signature = iwlcore_eeprom_verify_signature,
.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
.release_semaphore = iwlcore_eeprom_release_semaphore,
- .check_version = iwl5000_eeprom_check_version,
+ .calib_version = iwl5000_eeprom_calib_version,
.query_addr = iwl5000_eeprom_query_addr,
},
};
@@ -1517,7 +1526,6 @@ static struct iwl_ops iwl5000_ops = {
static struct iwl_mod_params iwl50_mod_params = {
.num_of_queues = IWL50_NUM_QUEUES,
.num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
- .enable_qos = 1,
.amsdu_size_8K = 1,
.restart_fw = 1,
/* the rest are 0 by default */
@@ -1526,50 +1534,84 @@ static struct iwl_mod_params iwl50_mod_params = {
struct iwl_cfg iwl5300_agn_cfg = {
.name = "5300AGN",
- .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode",
+ .fw_name_pre = IWL5000_FW_PRE,
+ .ucode_api_max = IWL5000_UCODE_API_MAX,
+ .ucode_api_min = IWL5000_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.ops = &iwl5000_ops,
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+ .eeprom_ver = EEPROM_5000_EEPROM_VERSION,
+ .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
};
struct iwl_cfg iwl5100_bg_cfg = {
.name = "5100BG",
- .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode",
+ .fw_name_pre = IWL5000_FW_PRE,
+ .ucode_api_max = IWL5000_UCODE_API_MAX,
+ .ucode_api_min = IWL5000_UCODE_API_MIN,
.sku = IWL_SKU_G,
.ops = &iwl5000_ops,
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+ .eeprom_ver = EEPROM_5000_EEPROM_VERSION,
+ .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
};
struct iwl_cfg iwl5100_abg_cfg = {
.name = "5100ABG",
- .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode",
+ .fw_name_pre = IWL5000_FW_PRE,
+ .ucode_api_max = IWL5000_UCODE_API_MAX,
+ .ucode_api_min = IWL5000_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G,
.ops = &iwl5000_ops,
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+ .eeprom_ver = EEPROM_5000_EEPROM_VERSION,
+ .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
};
struct iwl_cfg iwl5100_agn_cfg = {
.name = "5100AGN",
- .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode",
+ .fw_name_pre = IWL5000_FW_PRE,
+ .ucode_api_max = IWL5000_UCODE_API_MAX,
+ .ucode_api_min = IWL5000_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.ops = &iwl5000_ops,
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+ .eeprom_ver = EEPROM_5000_EEPROM_VERSION,
+ .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
};
struct iwl_cfg iwl5350_agn_cfg = {
.name = "5350AGN",
- .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode",
+ .fw_name_pre = IWL5000_FW_PRE,
+ .ucode_api_max = IWL5000_UCODE_API_MAX,
+ .ucode_api_min = IWL5000_UCODE_API_MIN,
+ .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
+ .ops = &iwl5000_ops,
+ .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+ .eeprom_ver = EEPROM_5050_EEPROM_VERSION,
+ .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
+ .mod_params = &iwl50_mod_params,
+};
+
+struct iwl_cfg iwl5150_agn_cfg = {
+ .name = "5150AGN",
+ .fw_name_pre = IWL5150_FW_PRE,
+ .ucode_api_max = IWL5150_UCODE_API_MAX,
+ .ucode_api_min = IWL5150_UCODE_API_MIN,
.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
.ops = &iwl5000_ops,
.eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+ .eeprom_ver = EEPROM_5050_EEPROM_VERSION,
+ .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
.mod_params = &iwl50_mod_params,
};
-MODULE_FIRMWARE("iwlwifi-5000" IWL5000_UCODE_API ".ucode");
+MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
+MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX));
module_param_named(disable50, iwl50_mod_params.disable, int, 0444);
MODULE_PARM_DESC(disable50,
@@ -1577,12 +1619,10 @@ MODULE_PARM_DESC(disable50,
module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, 0444);
MODULE_PARM_DESC(swcrypto50,
"using software crypto engine (default 0 [hardware])\n");
-module_param_named(debug50, iwl50_mod_params.debug, int, 0444);
+module_param_named(debug50, iwl50_mod_params.debug, uint, 0444);
MODULE_PARM_DESC(debug50, "50XX debug output mask");
module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, 0444);
MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series");
-module_param_named(qos_enable50, iwl50_mod_params.enable_qos, int, 0444);
-MODULE_PARM_DESC(qos_enable50, "enable all 50XX QoS functionality");
module_param_named(11n_disable50, iwl50_mod_params.disable_11n, int, 0444);
MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality");
module_param_named(amsdu_size_8K50, iwl50_mod_params.amsdu_size_8K, int, 0444);
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c
new file mode 100644
index 000000000000..b8137eeae1db
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd-check.c
@@ -0,0 +1,108 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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,
+ * USA
+ *
+ * The full GNU General Public License is included in this distribution
+ * in the file called LICENSE.GPL.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <net/mac80211.h>
+#include "iwl-dev.h"
+#include "iwl-debug.h"
+#include "iwl-commands.h"
+
+
+/**
+ * iwl_check_rxon_cmd - validate RXON structure is valid
+ *
+ * NOTE: This is really only useful during development and can eventually
+ * be #ifdef'd out once the driver is stable and folks aren't actively
+ * making changes
+ */
+int iwl_agn_check_rxon_cmd(struct iwl_rxon_cmd *rxon)
+{
+ int error = 0;
+ int counter = 1;
+
+ if (rxon->flags & RXON_FLG_BAND_24G_MSK) {
+ error |= le32_to_cpu(rxon->flags &
+ (RXON_FLG_TGJ_NARROW_BAND_MSK |
+ RXON_FLG_RADAR_DETECT_MSK));
+ if (error)
+ IWL_WARNING("check 24G fields %d | %d\n",
+ counter++, error);
+ } else {
+ error |= (rxon->flags & RXON_FLG_SHORT_SLOT_MSK) ?
+ 0 : le32_to_cpu(RXON_FLG_SHORT_SLOT_MSK);
+ if (error)
+ IWL_WARNING("check 52 fields %d | %d\n",
+ counter++, error);
+ error |= le32_to_cpu(rxon->flags & RXON_FLG_CCK_MSK);
+ if (error)
+ IWL_WARNING("check 52 CCK %d | %d\n",
+ counter++, error);
+ }
+ error |= (rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1;
+ if (error)
+ IWL_WARNING("check mac addr %d | %d\n", counter++, error);
+
+ /* make sure basic rates 6Mbps and 1Mbps are supported */
+ error |= (((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0) &&
+ ((rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0));
+ if (error)
+ IWL_WARNING("check basic rate %d | %d\n", counter++, error);
+
+ error |= (le16_to_cpu(rxon->assoc_id) > 2007);
+ if (error)
+ IWL_WARNING("check assoc id %d | %d\n", counter++, error);
+
+ error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK))
+ == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK));
+ if (error)
+ IWL_WARNING("check CCK and short slot %d | %d\n",
+ counter++, error);
+
+ error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK))
+ == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK));
+ if (error)
+ IWL_WARNING("check CCK & auto detect %d | %d\n",
+ counter++, error);
+
+ error |= ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK |
+ RXON_FLG_TGG_PROTECT_MSK)) == RXON_FLG_TGG_PROTECT_MSK);
+ if (error)
+ IWL_WARNING("check TGG and auto detect %d | %d\n",
+ counter++, error);
+
+ if (error)
+ IWL_WARNING("Tuning to channel %d\n",
+ le16_to_cpu(rxon->channel));
+
+ if (error) {
+ IWL_ERROR("Not a valid iwl4965_rxon_assoc_cmd field values\n");
+ return -1;
+ }
+ return 0;
+}
+
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index e2a58e477036..f3f17929ca0b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -38,7 +38,6 @@
#include "iwl-dev.h"
#include "iwl-sta.h"
#include "iwl-core.h"
-#include "iwl-helpers.h"
#define RS_NAME "iwl-agn-rs"
@@ -188,7 +187,7 @@ static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
* 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits
* "G" is the only table that supports CCK (the first 4 rates).
*/
-/*FIXME:RS:need to spearate tables for MIMO2/MIMO3*/
+/*FIXME:RS:need to separate tables for MIMO2/MIMO3*/
static s32 expected_tpt_A[IWL_RATE_COUNT] = {
0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186, 186
};
@@ -281,10 +280,9 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data,
u32 time_diff;
s32 index;
struct iwl_traffic_load *tl = NULL;
- __le16 fc = hdr->frame_control;
u8 tid;
- if (ieee80211_is_data_qos(fc)) {
+ if (ieee80211_is_data_qos(hdr->frame_control)) {
u8 *qc = ieee80211_get_qos_ctl(hdr);
tid = qc[0] & 0xf;
} else
@@ -357,11 +355,9 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
struct iwl_lq_sta *lq_data, u8 tid,
struct ieee80211_sta *sta)
{
- DECLARE_MAC_BUF(mac);
-
if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) {
- IWL_DEBUG_HT("Starting Tx agg: STA: %s tid: %d\n",
- print_mac(mac, sta->addr), tid);
+ IWL_DEBUG_HT("Starting Tx agg: STA: %pM tid: %d\n",
+ sta->addr, tid);
ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid);
}
}
@@ -775,7 +771,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
int status;
u8 retries;
int rs_index, index = 0;
- struct iwl_lq_sta *lq_sta;
+ struct iwl_lq_sta *lq_sta = priv_sta;
struct iwl_link_quality_cmd *table;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct iwl_priv *priv = (struct iwl_priv *)priv_r;
@@ -787,12 +783,12 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
struct iwl_scale_tbl_info tbl_type;
struct iwl_scale_tbl_info *curr_tbl, *search_tbl;
u8 active_index = 0;
- __le16 fc = hdr->frame_control;
s32 tpt = 0;
IWL_DEBUG_RATE_LIMIT("get frame ack response, update rate scale window\n");
- if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1))
+ if (!ieee80211_is_data(hdr->frame_control) ||
+ is_multicast_ether_addr(hdr->addr1))
return;
/* This packet was aggregated but doesn't carry rate scale info */
@@ -800,13 +796,11 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
!(info->flags & IEEE80211_TX_STAT_AMPDU))
return;
- retries = info->status.retry_count;
+ retries = info->status.rates[0].count - 1;
if (retries > 15)
retries = 15;
- lq_sta = (struct iwl_lq_sta *)priv_sta;
-
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
!lq_sta->ibss_sta_added)
goto out;
@@ -832,21 +826,20 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
if (priv->band == IEEE80211_BAND_5GHZ)
rs_index -= IWL_FIRST_OFDM_RATE;
- if ((info->tx_rate_idx < 0) ||
- (tbl_type.is_SGI ^
- !!(info->flags & IEEE80211_TX_CTL_SHORT_GI)) ||
- (tbl_type.is_fat ^
- !!(info->flags & IEEE80211_TX_CTL_40_MHZ_WIDTH)) ||
- (tbl_type.is_dup ^
- !!(info->flags & IEEE80211_TX_CTL_DUP_DATA)) ||
- (tbl_type.ant_type ^ info->antenna_sel_tx) ||
- (!!(tx_rate & RATE_MCS_HT_MSK) ^
- !!(info->flags & IEEE80211_TX_CTL_OFDM_HT)) ||
- (!!(tx_rate & RATE_MCS_GF_MSK) ^
- !!(info->flags & IEEE80211_TX_CTL_GREEN_FIELD)) ||
+ if ((info->status.rates[0].idx < 0) ||
+ (tbl_type.is_SGI != !!(info->status.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)) ||
+ (tbl_type.is_fat != !!(info->status.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) ||
+ (tbl_type.is_dup != !!(info->status.rates[0].flags & IEEE80211_TX_RC_DUP_DATA)) ||
+ (tbl_type.ant_type != info->antenna_sel_tx) ||
+ (!!(tx_rate & RATE_MCS_HT_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) ||
+ (!!(tx_rate & RATE_MCS_GF_MSK) != !!(info->status.rates[0].flags & IEEE80211_TX_RC_GREEN_FIELD)) ||
(hw->wiphy->bands[priv->band]->bitrates[rs_index].bitrate !=
- hw->wiphy->bands[info->band]->bitrates[info->tx_rate_idx].bitrate)) {
+ hw->wiphy->bands[info->band]->bitrates[info->status.rates[0].idx].bitrate)) {
IWL_DEBUG_RATE("initial rate does not match 0x%x\n", tx_rate);
+ /* the last LQ command could failed so the LQ in ucode not
+ * the same in driver sync up
+ */
+ iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC);
goto out;
}
@@ -1135,11 +1128,10 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
s32 rate;
s8 is_green = lq_sta->is_green;
- if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) ||
- !sta->ht_info.ht_supported)
+ if (!conf->ht.enabled || !sta->ht_cap.ht_supported)
return -1;
- if (((sta->ht_info.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
+ if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
== WLAN_HT_CAP_SM_PS_STATIC)
return -1;
@@ -1203,8 +1195,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
u8 is_green = lq_sta->is_green;
s32 rate;
- if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) ||
- !sta->ht_info.ht_supported)
+ if (!conf->ht.enabled || !sta->ht_cap.ht_supported)
return -1;
IWL_DEBUG_RATE("LQ: try to switch to SISO\n");
@@ -1684,7 +1675,6 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
int high_tpt = IWL_INVALID_VALUE;
u32 fail_count;
s8 scale_action = 0;
- __le16 fc;
u16 rate_mask;
u8 update_lq = 0;
struct iwl_scale_tbl_info *tbl, *tbl1;
@@ -1699,13 +1689,12 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
IWL_DEBUG_RATE("rate scale calculate new rate for skb\n");
- fc = hdr->frame_control;
- if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) {
- /* Send management frames and broadcast/multicast data using
- * lowest rate. */
- /* TODO: this could probably be improved.. */
+ /* Send management frames and broadcast/multicast data using
+ * lowest rate. */
+ /* TODO: this could probably be improved.. */
+ if (!ieee80211_is_data(hdr->frame_control) ||
+ is_multicast_ether_addr(hdr->addr1))
return;
- }
if (!sta || !lq_sta)
return;
@@ -2003,9 +1992,8 @@ lq_update:
* stay with best antenna legacy modulation for a while
* before next round of mode comparisons. */
tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]);
- if (is_legacy(tbl1->lq_type) &&
- (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) &&
- (lq_sta->action_counter >= 1)) {
+ if (is_legacy(tbl1->lq_type) && !conf->ht.enabled &&
+ lq_sta->action_counter >= 1) {
lq_sta->action_counter = 0;
IWL_DEBUG_RATE("LQ: STAY in legacy table\n");
rs_set_stay_in_table(priv, 1, lq_sta);
@@ -2081,15 +2069,13 @@ static void rs_initialize_lq(struct iwl_priv *priv,
if ((i < 0) || (i >= IWL_RATE_COUNT))
i = 0;
- /* FIXME:RS: This is also wrong in 4965 */
rate = iwl_rates[i].plcp;
- rate |= RATE_MCS_ANT_B_MSK;
- rate &= ~RATE_MCS_ANT_A_MSK;
+ tbl->ant_type = first_antenna(valid_tx_ant);
+ rate |= tbl->ant_type << RATE_MCS_ANT_POS;
if (i >= IWL_FIRST_CCK_RATE && i <= IWL_LAST_CCK_RATE)
rate |= RATE_MCS_CCK_MSK;
- tbl->ant_type = ANT_B;
rs_get_tbl_info_from_mcs(rate, priv->band, tbl, &rate_idx);
if (!rs_is_valid_ant(valid_tx_ant, tbl->ant_type))
rs_toggle_antenna(valid_tx_ant, &rate, tbl);
@@ -2103,40 +2089,38 @@ static void rs_initialize_lq(struct iwl_priv *priv,
return;
}
-static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
- struct ieee80211_sta *sta, void *priv_sta,
- struct sk_buff *skb, struct rate_selection *sel)
+static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
+ struct ieee80211_tx_rate_control *txrc)
{
- int i;
+ struct sk_buff *skb = txrc->skb;
+ struct ieee80211_supported_band *sband = txrc->sband;
struct iwl_priv *priv = (struct iwl_priv *)priv_r;
struct ieee80211_conf *conf = &priv->hw->conf;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- __le16 fc;
- struct iwl_lq_sta *lq_sta;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ struct iwl_lq_sta *lq_sta = priv_sta;
+ int rate_idx;
IWL_DEBUG_RATE_LIMIT("rate scale calculate new rate for skb\n");
/* Send management frames and broadcast/multicast data using lowest
* rate. */
- fc = hdr->frame_control;
- if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) ||
- !sta || !priv_sta) {
- sel->rate_idx = rate_lowest_index(sband, sta);
+ if (!ieee80211_is_data(hdr->frame_control) ||
+ is_multicast_ether_addr(hdr->addr1) || !sta || !lq_sta) {
+ info->control.rates[0].idx = rate_lowest_index(sband, sta);
return;
}
- lq_sta = (struct iwl_lq_sta *)priv_sta;
- i = lq_sta->last_txrate_idx;
+ rate_idx = lq_sta->last_txrate_idx;
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
!lq_sta->ibss_sta_added) {
u8 sta_id = iwl_find_station(priv, hdr->addr1);
- DECLARE_MAC_BUF(mac);
if (sta_id == IWL_INVALID_STATION) {
- IWL_DEBUG_RATE("LQ: ADD station %s\n",
- print_mac(mac, hdr->addr1));
+ IWL_DEBUG_RATE("LQ: ADD station %pM\n",
+ hdr->addr1);
sta_id = iwl_add_station_flags(priv, hdr->addr1,
0, CMD_ASYNC, NULL);
}
@@ -2148,14 +2132,12 @@ static void rs_get_rate(void *priv_r, struct ieee80211_supported_band *sband,
}
}
- if ((i < 0) || (i > IWL_RATE_COUNT)) {
- sel->rate_idx = rate_lowest_index(sband, sta);
- return;
- }
+ if (rate_idx < 0 || rate_idx > IWL_RATE_COUNT)
+ rate_idx = rate_lowest_index(sband, sta);
+ else if (sband->band == IEEE80211_BAND_5GHZ)
+ rate_idx -= IWL_FIRST_OFDM_RATE;
- if (sband->band == IEEE80211_BAND_5GHZ)
- i -= IWL_FIRST_OFDM_RATE;
- sel->rate_idx = i;
+ info->control.rates[0].idx = rate_idx;
}
static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta,
@@ -2189,6 +2171,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
struct iwl_priv *priv = (struct iwl_priv *)priv_r;
struct ieee80211_conf *conf = &priv->hw->conf;
struct iwl_lq_sta *lq_sta = priv_sta;
+ u16 mask_bit = 0;
lq_sta->flush_timer = 0;
lq_sta->supp_rates = sta->supp_rates[sband->band];
@@ -2205,15 +2188,12 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
lq_sta->ibss_sta_added = 0;
if (priv->iw_mode == NL80211_IFTYPE_AP) {
u8 sta_id = iwl_find_station(priv, sta->addr);
- DECLARE_MAC_BUF(mac);
/* for IBSS the call are from tasklet */
- IWL_DEBUG_RATE("LQ: ADD station %s\n",
- print_mac(mac, sta->addr));
+ IWL_DEBUG_RATE("LQ: ADD station %pM\n", sta->addr);
if (sta_id == IWL_INVALID_STATION) {
- IWL_DEBUG_RATE("LQ: ADD station %s\n",
- print_mac(mac, sta->addr));
+ IWL_DEBUG_RATE("LQ: ADD station %pM\n", sta->addr);
sta_id = iwl_add_station_flags(priv, sta->addr,
0, CMD_ASYNC, NULL);
}
@@ -2225,16 +2205,6 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
priv->assoc_station_added = 1;
}
- /* Find highest tx rate supported by hardware and destination station */
- lq_sta->last_txrate_idx = 3;
- for (i = 0; i < sband->n_bitrates; i++)
- if (sta->supp_rates[sband->band] & BIT(i))
- lq_sta->last_txrate_idx = i;
-
- /* For MODE_IEEE80211A, skip over cck rates in global rate table */
- if (sband->band == IEEE80211_BAND_5GHZ)
- lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
-
lq_sta->is_dup = 0;
lq_sta->is_green = rs_use_green(priv, conf);
lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000);
@@ -2244,19 +2214,19 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
* active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
* supp_rates[] does not; shift to convert format, force 9 MBits off.
*/
- lq_sta->active_siso_rate = conf->ht_conf.supp_mcs_set[0] << 1;
- lq_sta->active_siso_rate |= conf->ht_conf.supp_mcs_set[0] & 0x1;
+ lq_sta->active_siso_rate = sta->ht_cap.mcs.rx_mask[0] << 1;
+ lq_sta->active_siso_rate |= sta->ht_cap.mcs.rx_mask[0] & 0x1;
lq_sta->active_siso_rate &= ~((u16)0x2);
lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE;
/* Same here */
- lq_sta->active_mimo2_rate = conf->ht_conf.supp_mcs_set[1] << 1;
- lq_sta->active_mimo2_rate |= conf->ht_conf.supp_mcs_set[1] & 0x1;
+ lq_sta->active_mimo2_rate = sta->ht_cap.mcs.rx_mask[1] << 1;
+ lq_sta->active_mimo2_rate |= sta->ht_cap.mcs.rx_mask[1] & 0x1;
lq_sta->active_mimo2_rate &= ~((u16)0x2);
lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE;
- lq_sta->active_mimo3_rate = conf->ht_conf.supp_mcs_set[2] << 1;
- lq_sta->active_mimo3_rate |= conf->ht_conf.supp_mcs_set[2] & 0x1;
+ lq_sta->active_mimo3_rate = sta->ht_cap.mcs.rx_mask[2] << 1;
+ lq_sta->active_mimo3_rate |= sta->ht_cap.mcs.rx_mask[2] & 0x1;
lq_sta->active_mimo3_rate &= ~((u16)0x2);
lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE;
@@ -2265,7 +2235,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
lq_sta->active_mimo2_rate,
lq_sta->active_mimo3_rate);
- /* These values will be overriden later */
+ /* These values will be overridden later */
lq_sta->lq.general_params.single_stream_ant_msk = ANT_A;
lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB;
@@ -2273,6 +2243,17 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID;
lq_sta->drv = priv;
+ /* Find highest tx rate supported by hardware and destination station */
+ mask_bit = sta->supp_rates[sband->band] & lq_sta->active_legacy_rate;
+ lq_sta->last_txrate_idx = 3;
+ for (i = 0; i < sband->n_bitrates; i++)
+ if (mask_bit & BIT(i))
+ lq_sta->last_txrate_idx = i;
+
+ /* For MODE_IEEE80211A, skip over cck rates in global rate table */
+ if (sband->band == IEEE80211_BAND_5GHZ)
+ lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
+
rs_initialize_lq(priv, conf, sta, lq_sta);
}
@@ -2405,19 +2386,6 @@ static void rs_free(void *priv_rate)
return;
}
-static void rs_clear(void *priv_rate)
-{
-#ifdef CONFIG_IWLWIFI_DEBUG
- struct iwl_priv *priv = (struct iwl_priv *) priv_rate;
-
- IWL_DEBUG_RATE("enter\n");
-
- /* TODO - add rate scale state reset */
-
- IWL_DEBUG_RATE("leave\n");
-#endif /* CONFIG_IWLWIFI_DEBUG */
-}
-
static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta,
void *priv_sta)
{
@@ -2552,7 +2520,7 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
for (i = 0; i < LQ_SIZE; i++) {
desc += sprintf(buff+desc, "%s type=%d SGI=%d FAT=%d DUP=%d\n"
"rate=0x%X\n",
- lq_sta->active_tbl == i?"*":"x",
+ lq_sta->active_tbl == i ? "*" : "x",
lq_sta->lq_info[i].lq_type,
lq_sta->lq_info[i].is_SGI,
lq_sta->lq_info[i].is_fat,
@@ -2605,7 +2573,6 @@ static struct rate_control_ops rs_ops = {
.tx_status = rs_tx_status,
.get_rate = rs_get_rate,
.rate_init = rs_rate_init,
- .clear = rs_clear,
.alloc = rs_alloc,
.free = rs_free,
.alloc_sta = rs_alloc_sta,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
index d148d73635eb..78ee83adf742 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
@@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -229,7 +229,7 @@ enum {
#define IWL_MIMO2_SWITCH_SISO_C 4
#define IWL_MIMO2_SWITCH_GI 5
-/*FIXME:RS:add posible acctions for MIMO3*/
+/*FIXME:RS:add possible actions for MIMO3*/
#define IWL_ACTION_LIMIT 3 /* # possible actions */
@@ -284,7 +284,17 @@ static inline u8 num_of_ant(u8 mask)
!!((mask) & ANT_C);
}
-static inline u8 iwl4965_get_prev_ieee_rate(u8 rate_index)
+static inline u8 first_antenna(u8 mask)
+{
+ if (mask & ANT_A)
+ return ANT_A;
+ if (mask & ANT_B)
+ return ANT_B;
+ return ANT_C;
+}
+
+
+static inline u8 iwl_get_prev_ieee_rate(u8 rate_index)
{
u8 rate = iwl_rates[rate_index].prev_ieee;
@@ -294,11 +304,11 @@ static inline u8 iwl4965_get_prev_ieee_rate(u8 rate_index)
}
/**
- * iwl4965_rate_control_register - Register the rate control algorithm callbacks
+ * iwl_rate_control_register - Register the rate control algorithm callbacks
*
* Since the rate control algorithm is hardware specific, there is no need
* or reason to place it as a stand alone module. The driver can call
- * iwl4965_rate_control_register in order to register the rate control callbacks
+ * iwl_rate_control_register in order to register the rate control callbacks
* with the mac80211 subsystem. This should be performed prior to calling
* ieee80211_register_hw
*
@@ -306,7 +316,7 @@ static inline u8 iwl4965_get_prev_ieee_rate(u8 rate_index)
extern int iwlagn_rate_control_register(void);
/**
- * iwl4965_rate_control_unregister - Unregister the rate control callbacks
+ * iwl_rate_control_unregister - Unregister the rate control callbacks
*
* This should be called after calling ieee80211_unregister_hw, but before
* the driver is unloaded.
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index c4c0371c763b..5da6b35cd26d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -83,7 +83,7 @@
MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERSION);
-MODULE_AUTHOR(DRV_COPYRIGHT);
+MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");
MODULE_ALIAS("iwl4965");
@@ -96,7 +96,7 @@ MODULE_ALIAS("iwl4965");
-static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
+static void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
{
struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
@@ -108,79 +108,6 @@ static void iwl4965_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt)
}
/**
- * iwl4965_check_rxon_cmd - validate RXON structure is valid
- *
- * NOTE: This is really only useful during development and can eventually
- * be #ifdef'd out once the driver is stable and folks aren't actively
- * making changes
- */
-static int iwl4965_check_rxon_cmd(struct iwl_rxon_cmd *rxon)
-{
- int error = 0;
- int counter = 1;
-
- if (rxon->flags & RXON_FLG_BAND_24G_MSK) {
- error |= le32_to_cpu(rxon->flags &
- (RXON_FLG_TGJ_NARROW_BAND_MSK |
- RXON_FLG_RADAR_DETECT_MSK));
- if (error)
- IWL_WARNING("check 24G fields %d | %d\n",
- counter++, error);
- } else {
- error |= (rxon->flags & RXON_FLG_SHORT_SLOT_MSK) ?
- 0 : le32_to_cpu(RXON_FLG_SHORT_SLOT_MSK);
- if (error)
- IWL_WARNING("check 52 fields %d | %d\n",
- counter++, error);
- error |= le32_to_cpu(rxon->flags & RXON_FLG_CCK_MSK);
- if (error)
- IWL_WARNING("check 52 CCK %d | %d\n",
- counter++, error);
- }
- error |= (rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1;
- if (error)
- IWL_WARNING("check mac addr %d | %d\n", counter++, error);
-
- /* make sure basic rates 6Mbps and 1Mbps are supported */
- error |= (((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0) &&
- ((rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0));
- if (error)
- IWL_WARNING("check basic rate %d | %d\n", counter++, error);
-
- error |= (le16_to_cpu(rxon->assoc_id) > 2007);
- if (error)
- IWL_WARNING("check assoc id %d | %d\n", counter++, error);
-
- error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK))
- == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK));
- if (error)
- IWL_WARNING("check CCK and short slot %d | %d\n",
- counter++, error);
-
- error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK))
- == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK));
- if (error)
- IWL_WARNING("check CCK & auto detect %d | %d\n",
- counter++, error);
-
- error |= ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK |
- RXON_FLG_TGG_PROTECT_MSK)) == RXON_FLG_TGG_PROTECT_MSK);
- if (error)
- IWL_WARNING("check TGG and auto detect %d | %d\n",
- counter++, error);
-
- if (error)
- IWL_WARNING("Tuning to channel %d\n",
- le16_to_cpu(rxon->channel));
-
- if (error) {
- IWL_ERROR("Not a valid iwl4965_rxon_assoc_cmd field values\n");
- return -1;
- }
- return 0;
-}
-
-/**
* iwl_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
* @priv: staging_rxon is compared to active_rxon
*
@@ -228,18 +155,17 @@ static int iwl_full_rxon_required(struct iwl_priv *priv)
}
/**
- * iwl4965_commit_rxon - commit staging_rxon to hardware
+ * iwl_commit_rxon - commit staging_rxon to hardware
*
* The RXON command in staging_rxon is committed to the hardware and
* the active_rxon structure is updated with the new data. This
* function correctly transitions out of the RXON_ASSOC_MSK state if
* a HW tune is required based on the RXON structure changes.
*/
-static int iwl4965_commit_rxon(struct iwl_priv *priv)
+static int iwl_commit_rxon(struct iwl_priv *priv)
{
/* cast away the const for active_rxon in this function */
struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
- DECLARE_MAC_BUF(mac);
int ret;
bool new_assoc =
!!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK);
@@ -253,14 +179,14 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
* 5000, but will not damage 4965 */
priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN;
- ret = iwl4965_check_rxon_cmd(&priv->staging_rxon);
+ ret = iwl_agn_check_rxon_cmd(&priv->staging_rxon);
if (ret) {
IWL_ERROR("Invalid RXON configuration. Not committing.\n");
return -EINVAL;
}
/* If we don't need to send a full RXON, we can use
- * iwl4965_rxon_assoc_cmd which is used to reconfigure filter
+ * iwl_rxon_assoc_cmd which is used to reconfigure filter
* and other flags for the current radio configuration. */
if (!iwl_full_rxon_required(priv)) {
ret = iwl_send_rxon_assoc(priv);
@@ -300,12 +226,12 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
IWL_DEBUG_INFO("Sending RXON\n"
"* with%s RXON_FILTER_ASSOC_MSK\n"
"* channel = %d\n"
- "* bssid = %s\n",
+ "* bssid = %pM\n",
(new_assoc ? "" : "out"),
le16_to_cpu(priv->staging_rxon.channel),
- print_mac(mac, priv->staging_rxon.bssid_addr));
+ priv->staging_rxon.bssid_addr);
- iwl4965_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
+ iwl_set_rxon_hwcrypto(priv, !priv->hw_params.sw_crypto);
/* Apply the new configuration
* RXON unassoc clears the station table in uCode, send it before
@@ -375,16 +301,16 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
return 0;
}
-void iwl4965_update_chain_flags(struct iwl_priv *priv)
+void iwl_update_chain_flags(struct iwl_priv *priv)
{
iwl_set_rxon_chain(priv);
- iwl4965_commit_rxon(priv);
+ iwl_commit_rxon(priv);
}
-static int iwl4965_send_bt_config(struct iwl_priv *priv)
+static int iwl_send_bt_config(struct iwl_priv *priv)
{
- struct iwl4965_bt_cmd bt_cmd = {
+ struct iwl_bt_cmd bt_cmd = {
.flags = 3,
.lead_time = 0xAA,
.max_kill = 1,
@@ -393,7 +319,7 @@ static int iwl4965_send_bt_config(struct iwl_priv *priv)
};
return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
- sizeof(struct iwl4965_bt_cmd), &bt_cmd);
+ sizeof(struct iwl_bt_cmd), &bt_cmd);
}
static void iwl_clear_free_frames(struct iwl_priv *priv)
@@ -445,7 +371,7 @@ static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv,
struct ieee80211_hdr *hdr,
- const u8 *dest, int left)
+ int left)
{
if (!iwl_is_associated(priv) || !priv->ibss_beacon ||
((priv->iw_mode != NL80211_IFTYPE_ADHOC) &&
@@ -460,16 +386,16 @@ static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv,
return priv->ibss_beacon->len;
}
-static u8 iwl4965_rate_get_lowest_plcp(struct iwl_priv *priv)
+static u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv)
{
int i;
int rate_mask;
/* Set rate mask*/
if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
- rate_mask = priv->active_rate_basic & 0xF;
+ rate_mask = priv->active_rate_basic & IWL_CCK_RATES_MASK;
else
- rate_mask = priv->active_rate_basic & 0xFF0;
+ rate_mask = priv->active_rate_basic & IWL_OFDM_RATES_MASK;
/* Find lowest valid rate */
for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
@@ -485,7 +411,7 @@ static u8 iwl4965_rate_get_lowest_plcp(struct iwl_priv *priv)
return IWL_RATE_6M_PLCP;
}
-static unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
+static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv,
struct iwl_frame *frame, u8 rate)
{
struct iwl_tx_beacon_cmd *tx_beacon_cmd;
@@ -498,7 +424,6 @@ static unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
frame_size = iwl_fill_beacon_frame(priv, tx_beacon_cmd->frame,
- iwl_bcast_addr,
sizeof(frame->u) - sizeof(*tx_beacon_cmd));
BUG_ON(frame_size > MAX_MPDU_SIZE);
@@ -517,7 +442,7 @@ static unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
return sizeof(*tx_beacon_cmd) + frame_size;
}
-static int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
+static int iwl_send_beacon_cmd(struct iwl_priv *priv)
{
struct iwl_frame *frame;
unsigned int frame_size;
@@ -532,9 +457,9 @@ static int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
return -ENOMEM;
}
- rate = iwl4965_rate_get_lowest_plcp(priv);
+ rate = iwl_rate_get_lowest_plcp(priv);
- frame_size = iwl4965_hw_get_beacon_cmd(priv, frame, rate);
+ frame_size = iwl_hw_get_beacon_cmd(priv, frame, rate);
rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
&frame->u.cmd[0]);
@@ -550,20 +475,33 @@ static int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
*
******************************************************************************/
-static void iwl4965_ht_conf(struct iwl_priv *priv,
+static void iwl_ht_conf(struct iwl_priv *priv,
struct ieee80211_bss_conf *bss_conf)
{
- struct ieee80211_ht_info *ht_conf = bss_conf->ht_conf;
- struct ieee80211_ht_bss_info *ht_bss_conf = bss_conf->ht_bss_conf;
+ struct ieee80211_sta_ht_cap *ht_conf;
struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
+ struct ieee80211_sta *sta;
IWL_DEBUG_MAC80211("enter: \n");
- iwl_conf->is_ht = bss_conf->assoc_ht;
-
if (!iwl_conf->is_ht)
return;
+
+ /*
+ * It is totally wrong to base global information on something
+ * that is valid only when associated, alas, this driver works
+ * that way and I don't know how to fix it.
+ */
+
+ rcu_read_lock();
+ sta = ieee80211_find_sta(priv->hw, priv->bssid);
+ if (!sta) {
+ rcu_read_unlock();
+ return;
+ }
+ ht_conf = &sta->ht_cap;
+
if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
iwl_conf->sgf |= HT_SHORT_GI_20MHZ;
if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
@@ -574,29 +512,36 @@ static void iwl4965_ht_conf(struct iwl_priv *priv,
!!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU);
iwl_conf->supported_chan_width =
- !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH);
- iwl_conf->extension_chan_offset =
- ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_SEC_OFFSET;
+ !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40);
+
+ /*
+ * XXX: The HT configuration needs to be moved into iwl_mac_config()
+ * to be done there correctly.
+ */
+
+ iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
+ if (priv->hw->conf.ht.channel_type == NL80211_CHAN_HT40MINUS)
+ iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+ else if(priv->hw->conf.ht.channel_type == NL80211_CHAN_HT40PLUS)
+ iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+
/* If no above or below channel supplied disable FAT channel */
- if (iwl_conf->extension_chan_offset != IEEE80211_HT_IE_CHA_SEC_ABOVE &&
- iwl_conf->extension_chan_offset != IEEE80211_HT_IE_CHA_SEC_BELOW) {
- iwl_conf->extension_chan_offset = IEEE80211_HT_IE_CHA_SEC_NONE;
+ if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE &&
+ iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW)
iwl_conf->supported_chan_width = 0;
- }
iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2);
- memcpy(iwl_conf->supp_mcs_set, ht_conf->supp_mcs_set, 16);
+ memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16);
- iwl_conf->control_channel = ht_bss_conf->primary_channel;
- iwl_conf->tx_chan_width =
- !!(ht_bss_conf->bss_cap & IEEE80211_HT_IE_CHA_WIDTH);
+ iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0;
iwl_conf->ht_protection =
- ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_HT_PROTECTION;
+ bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
iwl_conf->non_GF_STA_present =
- !!(ht_bss_conf->bss_op_mode & IEEE80211_HT_IE_NON_GF_STA_PRSNT);
+ !!(bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+
+ rcu_read_unlock();
- IWL_DEBUG_MAC80211("control channel %d\n", iwl_conf->control_channel);
IWL_DEBUG_MAC80211("leave\n");
}
@@ -608,9 +553,6 @@ static void iwl_activate_qos(struct iwl_priv *priv, u8 force)
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- if (!priv->qos_data.qos_enable)
- return;
-
priv->qos_data.def_qos_parm.qos_flags = 0;
if (priv->qos_data.qos_cap.q_AP.queue_request &&
@@ -637,23 +579,22 @@ static void iwl_activate_qos(struct iwl_priv *priv, u8 force)
#define MAX_UCODE_BEACON_INTERVAL 4096
-static __le16 iwl4965_adjust_beacon_interval(u16 beacon_val)
+static u16 iwl_adjust_beacon_interval(u16 beacon_val)
{
u16 new_val = 0;
u16 beacon_factor = 0;
- beacon_factor =
- (beacon_val + MAX_UCODE_BEACON_INTERVAL)
- / MAX_UCODE_BEACON_INTERVAL;
+ beacon_factor = (beacon_val + MAX_UCODE_BEACON_INTERVAL)
+ / MAX_UCODE_BEACON_INTERVAL;
new_val = beacon_val / beacon_factor;
- return cpu_to_le16(new_val);
+ return new_val;
}
-static void iwl4965_setup_rxon_timing(struct iwl_priv *priv)
+static void iwl_setup_rxon_timing(struct iwl_priv *priv)
{
- u64 interval_tm_unit;
- u64 tsf, result;
+ u64 tsf;
+ s32 interval_tm, rem;
unsigned long flags;
struct ieee80211_conf *conf = NULL;
u16 beacon_int = 0;
@@ -661,49 +602,32 @@ static void iwl4965_setup_rxon_timing(struct iwl_priv *priv)
conf = ieee80211_get_hw_conf(priv->hw);
spin_lock_irqsave(&priv->lock, flags);
- priv->rxon_timing.timestamp.dw[1] = cpu_to_le32(priv->timestamp >> 32);
- priv->rxon_timing.timestamp.dw[0] =
- cpu_to_le32(priv->timestamp & 0xFFFFFFFF);
-
+ priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp);
priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval);
- tsf = priv->timestamp;
-
- beacon_int = priv->beacon_int;
- spin_unlock_irqrestore(&priv->lock, flags);
-
if (priv->iw_mode == NL80211_IFTYPE_STATION) {
- if (beacon_int == 0) {
- priv->rxon_timing.beacon_interval = cpu_to_le16(100);
- priv->rxon_timing.beacon_init_val = cpu_to_le32(102400);
- } else {
- priv->rxon_timing.beacon_interval =
- cpu_to_le16(beacon_int);
- priv->rxon_timing.beacon_interval =
- iwl4965_adjust_beacon_interval(
- le16_to_cpu(priv->rxon_timing.beacon_interval));
- }
-
+ beacon_int = iwl_adjust_beacon_interval(priv->beacon_int);
priv->rxon_timing.atim_window = 0;
} else {
- priv->rxon_timing.beacon_interval =
- iwl4965_adjust_beacon_interval(conf->beacon_int);
+ beacon_int = iwl_adjust_beacon_interval(conf->beacon_int);
+
/* TODO: we need to get atim_window from upper stack
* for now we set to 0 */
priv->rxon_timing.atim_window = 0;
}
- interval_tm_unit =
- (le16_to_cpu(priv->rxon_timing.beacon_interval) * 1024);
- result = do_div(tsf, interval_tm_unit);
- priv->rxon_timing.beacon_init_val =
- cpu_to_le32((u32) ((u64) interval_tm_unit - result));
+ priv->rxon_timing.beacon_interval = cpu_to_le16(beacon_int);
- IWL_DEBUG_ASSOC
- ("beacon interval %d beacon timer %d beacon tim %d\n",
- le16_to_cpu(priv->rxon_timing.beacon_interval),
- le32_to_cpu(priv->rxon_timing.beacon_init_val),
- le16_to_cpu(priv->rxon_timing.atim_window));
+ tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */
+ interval_tm = beacon_int * 1024;
+ rem = do_div(tsf, interval_tm);
+ priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+ IWL_DEBUG_ASSOC("beacon interval %d beacon timer %d beacon tim %d\n",
+ le16_to_cpu(priv->rxon_timing.beacon_interval),
+ le32_to_cpu(priv->rxon_timing.beacon_init_val),
+ le16_to_cpu(priv->rxon_timing.atim_window));
}
static void iwl_set_flags_for_band(struct iwl_priv *priv,
@@ -715,7 +639,7 @@ static void iwl_set_flags_for_band(struct iwl_priv *priv,
| RXON_FLG_CCK_MSK);
priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
} else {
- /* Copied from iwl4965_post_associate() */
+ /* Copied from iwl_post_associate() */
if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)
priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK;
else
@@ -733,13 +657,13 @@ static void iwl_set_flags_for_band(struct iwl_priv *priv,
/*
* initialize rxon structure with default values from eeprom
*/
-static void iwl4965_connection_init_rx_config(struct iwl_priv *priv)
+static void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode)
{
const struct iwl_channel_info *ch_info;
memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
- switch (priv->iw_mode) {
+ switch (mode) {
case NL80211_IFTYPE_AP:
priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP;
break;
@@ -762,7 +686,7 @@ static void iwl4965_connection_init_rx_config(struct iwl_priv *priv)
RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
break;
default:
- IWL_ERROR("Unsupported interface type %d\n", priv->iw_mode);
+ IWL_ERROR("Unsupported interface type %d\n", mode);
break;
}
@@ -808,11 +732,9 @@ static void iwl4965_connection_init_rx_config(struct iwl_priv *priv)
iwl_set_rxon_chain(priv);
}
-static int iwl4965_set_mode(struct iwl_priv *priv, int mode)
+static int iwl_set_mode(struct iwl_priv *priv, int mode)
{
- priv->iw_mode = mode;
-
- iwl4965_connection_init_rx_config(priv);
+ iwl_connection_init_rx_config(priv, mode);
memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
iwl_clear_stations_table(priv);
@@ -828,12 +750,12 @@ static int iwl4965_set_mode(struct iwl_priv *priv, int mode)
return -EAGAIN;
}
- iwl4965_commit_rxon(priv);
+ iwl_commit_rxon(priv);
return 0;
}
-static void iwl4965_set_rate(struct iwl_priv *priv)
+static void iwl_set_rate(struct iwl_priv *priv)
{
const struct ieee80211_supported_band *hw = NULL;
struct ieee80211_rate *rate;
@@ -880,138 +802,6 @@ static void iwl4965_set_rate(struct iwl_priv *priv)
(IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
}
-#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT
-
-#include "iwl-spectrum.h"
-
-#define BEACON_TIME_MASK_LOW 0x00FFFFFF
-#define BEACON_TIME_MASK_HIGH 0xFF000000
-#define TIME_UNIT 1024
-
-/*
- * extended beacon time format
- * time in usec will be changed into a 32-bit value in 8:24 format
- * the high 1 byte is the beacon counts
- * the lower 3 bytes is the time in usec within one beacon interval
- */
-
-static u32 iwl4965_usecs_to_beacons(u32 usec, u32 beacon_interval)
-{
- u32 quot;
- u32 rem;
- u32 interval = beacon_interval * 1024;
-
- if (!interval || !usec)
- return 0;
-
- quot = (usec / interval) & (BEACON_TIME_MASK_HIGH >> 24);
- rem = (usec % interval) & BEACON_TIME_MASK_LOW;
-
- return (quot << 24) + rem;
-}
-
-/* base is usually what we get from ucode with each received frame,
- * the same as HW timer counter counting down
- */
-
-static __le32 iwl4965_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
-{
- u32 base_low = base & BEACON_TIME_MASK_LOW;
- u32 addon_low = addon & BEACON_TIME_MASK_LOW;
- u32 interval = beacon_interval * TIME_UNIT;
- u32 res = (base & BEACON_TIME_MASK_HIGH) +
- (addon & BEACON_TIME_MASK_HIGH);
-
- if (base_low > addon_low)
- res += base_low - addon_low;
- else if (base_low < addon_low) {
- res += interval + base_low - addon_low;
- res += (1 << 24);
- } else
- res += (1 << 24);
-
- return cpu_to_le32(res);
-}
-
-static int iwl4965_get_measurement(struct iwl_priv *priv,
- struct ieee80211_measurement_params *params,
- u8 type)
-{
- struct iwl4965_spectrum_cmd spectrum;
- struct iwl_rx_packet *res;
- struct iwl_host_cmd cmd = {
- .id = REPLY_SPECTRUM_MEASUREMENT_CMD,
- .data = (void *)&spectrum,
- .meta.flags = CMD_WANT_SKB,
- };
- u32 add_time = le64_to_cpu(params->start_time);
- int rc;
- int spectrum_resp_status;
- int duration = le16_to_cpu(params->duration);
-
- if (iwl_is_associated(priv))
- add_time =
- iwl4965_usecs_to_beacons(
- le64_to_cpu(params->start_time) - priv->last_tsf,
- le16_to_cpu(priv->rxon_timing.beacon_interval));
-
- memset(&spectrum, 0, sizeof(spectrum));
-
- spectrum.channel_count = cpu_to_le16(1);
- spectrum.flags =
- RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK;
- spectrum.filter_flags = MEASUREMENT_FILTER_FLAG;
- cmd.len = sizeof(spectrum);
- spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
-
- if (iwl_is_associated(priv))
- spectrum.start_time =
- iwl4965_add_beacon_time(priv->last_beacon_time,
- add_time,
- le16_to_cpu(priv->rxon_timing.beacon_interval));
- else
- spectrum.start_time = 0;
-
- spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT);
- spectrum.channels[0].channel = params->channel;
- spectrum.channels[0].type = type;
- if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK)
- spectrum.flags |= RXON_FLG_BAND_24G_MSK |
- RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
-
- rc = iwl_send_cmd_sync(priv, &cmd);
- if (rc)
- return rc;
-
- res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
- if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
- IWL_ERROR("Bad return from REPLY_RX_ON_ASSOC command\n");
- rc = -EIO;
- }
-
- spectrum_resp_status = le16_to_cpu(res->u.spectrum.status);
- switch (spectrum_resp_status) {
- case 0: /* Command will be handled */
- if (res->u.spectrum.id != 0xff) {
- IWL_DEBUG_INFO
- ("Replaced existing measurement: %d\n",
- res->u.spectrum.id);
- priv->measurement_status &= ~MEASUREMENT_READY;
- }
- priv->measurement_status |= MEASUREMENT_ACTIVE;
- rc = 0;
- break;
-
- case 1: /* Command will not be handled */
- rc = -EAGAIN;
- break;
- }
-
- dev_kfree_skb_any(cmd.meta.u.skb);
-
- return rc;
-}
-#endif
/******************************************************************************
*
@@ -1054,7 +844,7 @@ static void iwl_rx_reply_alive(struct iwl_priv *priv,
IWL_WARNING("uCode did not respond OK.\n");
}
-static void iwl4965_rx_reply_error(struct iwl_priv *priv,
+static void iwl_rx_reply_error(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
@@ -1070,47 +860,29 @@ static void iwl4965_rx_reply_error(struct iwl_priv *priv,
#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
-static void iwl4965_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
- struct iwl4965_csa_notification *csa = &(pkt->u.csa_notif);
+ struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
IWL_DEBUG_11H("CSA notif: channel %d, status %d\n",
le16_to_cpu(csa->channel), le32_to_cpu(csa->status));
rxon->channel = csa->channel;
priv->staging_rxon.channel = csa->channel;
}
-static void iwl4965_rx_spectrum_measure_notif(struct iwl_priv *priv,
- struct iwl_rx_mem_buffer *rxb)
-{
-#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT
- struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
- struct iwl4965_spectrum_notification *report = &(pkt->u.spectrum_notif);
-
- if (!report->state) {
- IWL_DEBUG(IWL_DL_11H,
- "Spectrum Measure Notification: Start\n");
- return;
- }
-
- memcpy(&priv->measure_report, report, sizeof(*report));
- priv->measurement_status |= MEASUREMENT_READY;
-#endif
-}
-
-static void iwl4965_rx_pm_sleep_notif(struct iwl_priv *priv,
+static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
- struct iwl4965_sleep_notification *sleep = &(pkt->u.sleep_notif);
+ struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
IWL_DEBUG_RX("sleep mode: %d, src: %d\n",
sleep->pm_sleep_mode, sleep->pm_wakeup_src);
#endif
}
-static void iwl4965_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
+static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
@@ -1120,7 +892,7 @@ static void iwl4965_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len));
}
-static void iwl4965_bg_beacon_update(struct work_struct *work)
+static void iwl_bg_beacon_update(struct work_struct *work)
{
struct iwl_priv *priv =
container_of(work, struct iwl_priv, beacon_update);
@@ -1142,11 +914,11 @@ static void iwl4965_bg_beacon_update(struct work_struct *work)
priv->ibss_beacon = beacon;
mutex_unlock(&priv->mutex);
- iwl4965_send_beacon_cmd(priv);
+ iwl_send_beacon_cmd(priv);
}
/**
- * iwl4965_bg_statistics_periodic - Timer callback to queue statistics
+ * iwl_bg_statistics_periodic - Timer callback to queue statistics
*
* This callback is provided in order to send a statistics request.
*
@@ -1155,22 +927,27 @@ static void iwl4965_bg_beacon_update(struct work_struct *work)
* was received. We need to ensure we receive the statistics in order
* to update the temperature used for calibrating the TXPOWER.
*/
-static void iwl4965_bg_statistics_periodic(unsigned long data)
+static void iwl_bg_statistics_periodic(unsigned long data)
{
struct iwl_priv *priv = (struct iwl_priv *)data;
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
+ /* dont send host command if rf-kill is on */
+ if (!iwl_is_ready_rf(priv))
+ return;
+
iwl_send_statistics_request(priv, CMD_ASYNC);
}
-static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
+static void iwl_rx_beacon_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
#ifdef CONFIG_IWLWIFI_DEBUG
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
- struct iwl4965_beacon_notif *beacon = &(pkt->u.beacon_status);
+ struct iwl4965_beacon_notif *beacon =
+ (struct iwl4965_beacon_notif *)pkt->u.raw;
u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
IWL_DEBUG_RX("beacon status %x retries %d iss %d "
@@ -1189,7 +966,7 @@ static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
/* Handle notification from uCode that card's power state is changing
* due to software, hardware, or critical temperature RFKILL */
-static void iwl4965_rx_card_state_notif(struct iwl_priv *priv,
+static void iwl_rx_card_state_notif(struct iwl_priv *priv,
struct iwl_rx_mem_buffer *rxb)
{
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
@@ -1258,7 +1035,7 @@ static void iwl4965_rx_card_state_notif(struct iwl_priv *priv,
wake_up_interruptible(&priv->wait_command_queue);
}
-int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
+int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
{
int ret;
unsigned long flags;
@@ -1290,7 +1067,7 @@ err:
}
/**
- * iwl4965_setup_rx_handlers - Initialize Rx handler callbacks
+ * iwl_setup_rx_handlers - Initialize Rx handler callbacks
*
* Setup the RX handlers for each of the reply types sent from the uCode
* to the host.
@@ -1301,14 +1078,12 @@ err:
static void iwl_setup_rx_handlers(struct iwl_priv *priv)
{
priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
- priv->rx_handlers[REPLY_ERROR] = iwl4965_rx_reply_error;
- priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl4965_rx_csa;
- priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
- iwl4965_rx_spectrum_measure_notif;
- priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl4965_rx_pm_sleep_notif;
+ priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
+ priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
+ priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
- iwl4965_rx_pm_debug_statistics_notif;
- priv->rx_handlers[BEACON_NOTIFICATION] = iwl4965_rx_beacon_notif;
+ iwl_rx_pm_debug_statistics_notif;
+ priv->rx_handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif;
/*
* The same handler is used for both the REPLY to a discrete
@@ -1318,10 +1093,11 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv)
priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_rx_statistics;
priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics;
+ iwl_setup_spectrum_handlers(priv);
iwl_setup_rx_scan_handlers(priv);
/* status change handler */
- priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl4965_rx_card_state_notif;
+ priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl_rx_card_state_notif;
priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
iwl_rx_missed_beacon_notif;
@@ -1334,16 +1110,6 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv)
priv->cfg->ops->lib->rx_handler_setup(priv);
}
-/*
- * this should be called while priv->lock is locked
-*/
-static void __iwl_rx_replenish(struct iwl_priv *priv)
-{
- iwl_rx_allocate(priv);
- iwl_rx_queue_restock(priv);
-}
-
-
/**
* iwl_rx_handle - Main entry function for receiving responses from uCode
*
@@ -1364,7 +1130,7 @@ void iwl_rx_handle(struct iwl_priv *priv)
/* uCode's read index (stored in shared DRAM) indicates the last Rx
* buffer that the driver may process (last buffer filled by ucode). */
- r = priv->cfg->ops->lib->shared_mem_rx_idx(priv);
+ r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF;
i = rxq->read;
/* Rx interrupt, but nothing sent from uCode */
@@ -1400,13 +1166,14 @@ void iwl_rx_handle(struct iwl_priv *priv)
reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
(pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
(pkt->hdr.cmd != REPLY_RX) &&
+ (pkt->hdr.cmd != REPLY_RX_MPDU_CMD) &&
(pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
(pkt->hdr.cmd != REPLY_TX);
/* Based on type of command response or notification,
* handle those that need handling via function in
- * rx_handlers table. See iwl4965_setup_rx_handlers() */
+ * rx_handlers table. See iwl_setup_rx_handlers() */
if (priv->rx_handlers[pkt->hdr.cmd]) {
IWL_DEBUG(IWL_DL_RX, "r = %d, i = %d, %s, 0x%02x\n", r,
i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
@@ -1451,7 +1218,7 @@ void iwl_rx_handle(struct iwl_priv *priv)
count++;
if (count >= 8) {
priv->rxq.read = i;
- __iwl_rx_replenish(priv);
+ iwl_rx_queue_restock(priv);
count = 0;
}
}
@@ -1463,10 +1230,9 @@ void iwl_rx_handle(struct iwl_priv *priv)
}
#ifdef CONFIG_IWLWIFI_DEBUG
-static void iwl4965_print_rx_config_cmd(struct iwl_priv *priv)
+static void iwl_print_rx_config_cmd(struct iwl_priv *priv)
{
struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
- DECLARE_MAC_BUF(mac);
IWL_DEBUG_RADIO("RX CONFIG:\n");
iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
@@ -1478,50 +1244,26 @@ static void iwl4965_print_rx_config_cmd(struct iwl_priv *priv)
IWL_DEBUG_RADIO("u8 ofdm_basic_rates: 0x%02x\n",
rxon->ofdm_basic_rates);
IWL_DEBUG_RADIO("u8 cck_basic_rates: 0x%02x\n", rxon->cck_basic_rates);
- IWL_DEBUG_RADIO("u8[6] node_addr: %s\n",
- print_mac(mac, rxon->node_addr));
- IWL_DEBUG_RADIO("u8[6] bssid_addr: %s\n",
- print_mac(mac, rxon->bssid_addr));
+ IWL_DEBUG_RADIO("u8[6] node_addr: %pM\n", rxon->node_addr);
+ IWL_DEBUG_RADIO("u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
IWL_DEBUG_RADIO("u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
}
#endif
-static void iwl4965_enable_interrupts(struct iwl_priv *priv)
-{
- IWL_DEBUG_ISR("Enabling interrupts\n");
- set_bit(STATUS_INT_ENABLED, &priv->status);
- iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
-}
-
/* call this function to flush any scheduled tasklet */
static inline void iwl_synchronize_irq(struct iwl_priv *priv)
{
- /* wait to make sure we flush pedding tasklet*/
+ /* wait to make sure we flush pending tasklet*/
synchronize_irq(priv->pci_dev->irq);
tasklet_kill(&priv->irq_tasklet);
}
-static inline void iwl4965_disable_interrupts(struct iwl_priv *priv)
-{
- clear_bit(STATUS_INT_ENABLED, &priv->status);
-
- /* disable interrupts from uCode/NIC to host */
- iwl_write32(priv, CSR_INT_MASK, 0x00000000);
-
- /* acknowledge/clear/reset any interrupts still pending
- * from uCode or flow handler (Rx/Tx DMA) */
- iwl_write32(priv, CSR_INT, 0xffffffff);
- iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
- IWL_DEBUG_ISR("Disabled interrupts\n");
-}
-
-
/**
- * iwl4965_irq_handle_error - called for HW or SW error interrupt from card
+ * iwl_irq_handle_error - called for HW or SW error interrupt from card
*/
-static void iwl4965_irq_handle_error(struct iwl_priv *priv)
+static void iwl_irq_handle_error(struct iwl_priv *priv)
{
- /* Set the FW error flag -- cleared on iwl4965_down */
+ /* Set the FW error flag -- cleared on iwl_down */
set_bit(STATUS_FW_ERROR, &priv->status);
/* Cancel currently queued command. */
@@ -1531,7 +1273,7 @@ static void iwl4965_irq_handle_error(struct iwl_priv *priv)
if (priv->debug_level & IWL_DL_FW_ERRORS) {
iwl_dump_nic_error_log(priv);
iwl_dump_nic_event_log(priv);
- iwl4965_print_rx_config_cmd(priv);
+ iwl_print_rx_config_cmd(priv);
}
#endif
@@ -1555,14 +1297,14 @@ static void iwl4965_irq_handle_error(struct iwl_priv *priv)
}
}
-static void iwl4965_error_recovery(struct iwl_priv *priv)
+static void iwl_error_recovery(struct iwl_priv *priv)
{
unsigned long flags;
memcpy(&priv->staging_rxon, &priv->recovery_rxon,
sizeof(priv->staging_rxon));
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl4965_commit_rxon(priv);
+ iwl_commit_rxon(priv);
iwl_rxon_add_station(priv, priv->bssid, 1);
@@ -1572,7 +1314,7 @@ static void iwl4965_error_recovery(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
}
-static void iwl4965_irq_tasklet(struct iwl_priv *priv)
+static void iwl_irq_tasklet(struct iwl_priv *priv)
{
u32 inta, handled = 0;
u32 inta_fh;
@@ -1618,9 +1360,9 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
IWL_ERROR("Microcode HW error detected. Restarting.\n");
/* Tell the device to stop sending interrupts */
- iwl4965_disable_interrupts(priv);
+ iwl_disable_interrupts(priv);
- iwl4965_irq_handle_error(priv);
+ iwl_irq_handle_error(priv);
handled |= CSR_INT_BIT_HW_ERR;
@@ -1652,14 +1394,17 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
hw_rf_kill = 1;
IWL_DEBUG(IWL_DL_RF_KILL, "RF_KILL bit toggled to %s.\n",
- hw_rf_kill ? "disable radio":"enable radio");
+ hw_rf_kill ? "disable radio" : "enable radio");
/* driver only loads ucode once setting the interface up.
* the driver as well won't allow loading if RFKILL is set
* therefore no need to restart the driver from this handler
*/
- if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status))
+ if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) {
clear_bit(STATUS_RF_KILL_HW, &priv->status);
+ if (priv->is_open && !iwl_is_rfkill(priv))
+ queue_work(priv->workqueue, &priv->up);
+ }
handled |= CSR_INT_BIT_RF_KILL;
}
@@ -1674,7 +1419,7 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
if (inta & CSR_INT_BIT_SW_ERR) {
IWL_ERROR("Microcode SW error detected. Restarting 0x%X.\n",
inta);
- iwl4965_irq_handle_error(priv);
+ iwl_irq_handle_error(priv);
handled |= CSR_INT_BIT_SW_ERR;
}
@@ -1720,7 +1465,7 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
/* Re-enable all interrupts */
/* only Re-enable if diabled by irq */
if (test_bit(STATUS_INT_ENABLED, &priv->status))
- iwl4965_enable_interrupts(priv);
+ iwl_enable_interrupts(priv);
#ifdef CONFIG_IWLWIFI_DEBUG
if (priv->debug_level & (IWL_DL_ISR)) {
@@ -1734,7 +1479,7 @@ static void iwl4965_irq_tasklet(struct iwl_priv *priv)
spin_unlock_irqrestore(&priv->lock, flags);
}
-static irqreturn_t iwl4965_isr(int irq, void *data)
+static irqreturn_t iwl_isr(int irq, void *data)
{
struct iwl_priv *priv = data;
u32 inta, inta_mask;
@@ -1766,7 +1511,7 @@ static irqreturn_t iwl4965_isr(int irq, void *data)
if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
/* Hardware disappeared. It might have already raised
* an interrupt */
- IWL_WARNING("HARDWARE GONE?? INTA == 0x%080x\n", inta);
+ IWL_WARNING("HARDWARE GONE?? INTA == 0x%08x\n", inta);
goto unplugged;
}
@@ -1775,7 +1520,7 @@ static irqreturn_t iwl4965_isr(int irq, void *data)
inta &= ~CSR_INT_BIT_SCD;
- /* iwl4965_irq_tasklet() will service interrupts and re-enable them */
+ /* iwl_irq_tasklet() will service interrupts and re-enable them */
if (likely(inta || inta_fh))
tasklet_schedule(&priv->irq_tasklet);
@@ -1787,7 +1532,7 @@ static irqreturn_t iwl4965_isr(int irq, void *data)
/* re-enable interrupts here since we don't have anything to service. */
/* only Re-enable if diabled by irq */
if (test_bit(STATUS_INT_ENABLED, &priv->status))
- iwl4965_enable_interrupts(priv);
+ iwl_enable_interrupts(priv);
spin_unlock(&priv->lock);
return IRQ_NONE;
}
@@ -1798,7 +1543,7 @@ static irqreturn_t iwl4965_isr(int irq, void *data)
*
******************************************************************************/
-static void iwl4965_dealloc_ucode_pci(struct iwl_priv *priv)
+static void iwl_dealloc_ucode_pci(struct iwl_priv *priv)
{
iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code);
iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data);
@@ -1808,7 +1553,7 @@ static void iwl4965_dealloc_ucode_pci(struct iwl_priv *priv)
iwl_free_fw_desc(priv->pci_dev, &priv->ucode_boot);
}
-static void iwl4965_nic_start(struct iwl_priv *priv)
+static void iwl_nic_start(struct iwl_priv *priv)
{
/* Remove all resets to allow NIC to operate */
iwl_write32(priv, CSR_RESET, 0);
@@ -1816,31 +1561,47 @@ static void iwl4965_nic_start(struct iwl_priv *priv)
/**
- * iwl4965_read_ucode - Read uCode images from disk file.
+ * iwl_read_ucode - Read uCode images from disk file.
*
* Copy into buffers for card to fetch via bus-mastering
*/
-static int iwl4965_read_ucode(struct iwl_priv *priv)
+static int iwl_read_ucode(struct iwl_priv *priv)
{
struct iwl_ucode *ucode;
- int ret;
+ int ret = -EINVAL, index;
const struct firmware *ucode_raw;
- const char *name = priv->cfg->fw_name;
+ const char *name_pre = priv->cfg->fw_name_pre;
+ const unsigned int api_max = priv->cfg->ucode_api_max;
+ const unsigned int api_min = priv->cfg->ucode_api_min;
+ char buf[25];
u8 *src;
size_t len;
- u32 ver, inst_size, data_size, init_size, init_data_size, boot_size;
+ u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size;
/* Ask kernel firmware_class module to get the boot firmware off disk.
* request_firmware() is synchronous, file is in memory on return. */
- ret = request_firmware(&ucode_raw, name, &priv->pci_dev->dev);
- if (ret < 0) {
- IWL_ERROR("%s firmware file req failed: Reason %d\n",
- name, ret);
- goto error;
+ for (index = api_max; index >= api_min; index--) {
+ sprintf(buf, "%s%d%s", name_pre, index, ".ucode");
+ ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev);
+ if (ret < 0) {
+ IWL_ERROR("%s firmware file req failed: Reason %d\n",
+ buf, ret);
+ if (ret == -ENOENT)
+ continue;
+ else
+ goto error;
+ } else {
+ if (index < api_max)
+ IWL_ERROR("Loaded firmware %s, which is deprecated. Please use API v%u instead.\n",
+ buf, api_max);
+ IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n",
+ buf, ucode_raw->size);
+ break;
+ }
}
- IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n",
- name, ucode_raw->size);
+ if (ret < 0)
+ goto error;
/* Make sure that we got at least our header! */
if (ucode_raw->size < sizeof(*ucode)) {
@@ -1852,14 +1613,40 @@ static int iwl4965_read_ucode(struct iwl_priv *priv)
/* Data from ucode file: header followed by uCode images */
ucode = (void *)ucode_raw->data;
- ver = le32_to_cpu(ucode->ver);
+ priv->ucode_ver = le32_to_cpu(ucode->ver);
+ api_ver = IWL_UCODE_API(priv->ucode_ver);
inst_size = le32_to_cpu(ucode->inst_size);
data_size = le32_to_cpu(ucode->data_size);
init_size = le32_to_cpu(ucode->init_size);
init_data_size = le32_to_cpu(ucode->init_data_size);
boot_size = le32_to_cpu(ucode->boot_size);
- IWL_DEBUG_INFO("f/w package hdr ucode version = 0x%x\n", ver);
+ /* api_ver should match the api version forming part of the
+ * firmware filename ... but we don't check for that and only rely
+ * on the API version read from firware header from here on forward */
+
+ if (api_ver < api_min || api_ver > api_max) {
+ IWL_ERROR("Driver unable to support your firmware API. "
+ "Driver supports v%u, firmware is v%u.\n",
+ api_max, api_ver);
+ priv->ucode_ver = 0;
+ ret = -EINVAL;
+ goto err_release;
+ }
+ if (api_ver != api_max)
+ IWL_ERROR("Firmware has old API version. Expected v%u, "
+ "got v%u. New firmware can be obtained "
+ "from http://www.intellinuxwireless.org.\n",
+ api_max, api_ver);
+
+ printk(KERN_INFO DRV_NAME " loaded firmware version %u.%u.%u.%u\n",
+ IWL_UCODE_MAJOR(priv->ucode_ver),
+ IWL_UCODE_MINOR(priv->ucode_ver),
+ IWL_UCODE_API(priv->ucode_ver),
+ IWL_UCODE_SERIAL(priv->ucode_ver));
+
+ IWL_DEBUG_INFO("f/w package hdr ucode version raw = 0x%x\n",
+ priv->ucode_ver);
IWL_DEBUG_INFO("f/w package hdr runtime inst size = %u\n",
inst_size);
IWL_DEBUG_INFO("f/w package hdr runtime data size = %u\n",
@@ -1964,7 +1751,7 @@ static int iwl4965_read_ucode(struct iwl_priv *priv)
priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
/* Runtime data (2nd block)
- * NOTE: Copy into backup buffer will be done in iwl4965_up() */
+ * NOTE: Copy into backup buffer will be done in iwl_up() */
src = &ucode->data[inst_size];
len = priv->ucode_data.len;
IWL_DEBUG_INFO("Copying (but not loading) uCode data len %Zd\n", len);
@@ -2002,7 +1789,7 @@ static int iwl4965_read_ucode(struct iwl_priv *priv)
err_pci_alloc:
IWL_ERROR("failed to allocate pci memory\n");
ret = -ENOMEM;
- iwl4965_dealloc_ucode_pci(priv);
+ iwl_dealloc_ucode_pci(priv);
err_release:
release_firmware(ucode_raw);
@@ -2011,6 +1798,10 @@ static int iwl4965_read_ucode(struct iwl_priv *priv)
return ret;
}
+/* temporary */
+static int iwl_mac_beacon_update(struct ieee80211_hw *hw,
+ struct sk_buff *skb);
+
/**
* iwl_alive_start - called after REPLY_ALIVE notification received
* from protocol/runtime uCode (initialization uCode's
@@ -2047,7 +1838,7 @@ static void iwl_alive_start(struct iwl_priv *priv)
goto restart;
}
- /* After the ALIVE response, we can send host commands to 4965 uCode */
+ /* After the ALIVE response, we can send host commands to the uCode */
set_bit(STATUS_ALIVE, &priv->status);
if (iwl_is_rfkill(priv))
@@ -2067,17 +1858,17 @@ static void iwl_alive_start(struct iwl_priv *priv)
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
} else {
/* Initialize our rx_config data */
- iwl4965_connection_init_rx_config(priv);
+ iwl_connection_init_rx_config(priv, priv->iw_mode);
memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
}
/* Configure Bluetooth device coexistence support */
- iwl4965_send_bt_config(priv);
+ iwl_send_bt_config(priv);
iwl_reset_run_time_calib(priv);
/* Configure the adapter for unassociated operation */
- iwl4965_commit_rxon(priv);
+ iwl_commit_rxon(priv);
/* At this point, the NIC is initialized and operational */
iwl_rf_kill_ct_config(priv);
@@ -2089,12 +1880,21 @@ static void iwl_alive_start(struct iwl_priv *priv)
wake_up_interruptible(&priv->wait_command_queue);
if (priv->error_recovering)
- iwl4965_error_recovery(priv);
+ iwl_error_recovery(priv);
iwl_power_update_mode(priv, 1);
+ /* reassociate for ADHOC mode */
+ if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) {
+ struct sk_buff *beacon = ieee80211_beacon_get(priv->hw,
+ priv->vif);
+ if (beacon)
+ iwl_mac_beacon_update(priv->hw, beacon);
+ }
+
+
if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status))
- iwl4965_set_mode(priv, priv->iw_mode);
+ iwl_set_mode(priv, priv->iw_mode);
return;
@@ -2104,7 +1904,7 @@ static void iwl_alive_start(struct iwl_priv *priv)
static void iwl_cancel_deferred_work(struct iwl_priv *priv);
-static void __iwl4965_down(struct iwl_priv *priv)
+static void __iwl_down(struct iwl_priv *priv)
{
unsigned long flags;
int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
@@ -2131,14 +1931,14 @@ static void __iwl4965_down(struct iwl_priv *priv)
/* tell the device to stop sending interrupts */
spin_lock_irqsave(&priv->lock, flags);
- iwl4965_disable_interrupts(priv);
+ iwl_disable_interrupts(priv);
spin_unlock_irqrestore(&priv->lock, flags);
iwl_synchronize_irq(priv);
if (priv->mac80211_registered)
ieee80211_stop_queues(priv->hw);
- /* If we have not previously called iwl4965_init() then
+ /* If we have not previously called iwl_init() then
* clear all bits but the RF Kill and SUSPEND bits and return */
if (!iwl_is_init(priv)) {
priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
@@ -2192,8 +1992,6 @@ static void __iwl4965_down(struct iwl_priv *priv)
priv->cfg->ops->lib->apm_ops.stop(priv);
else
priv->cfg->ops->lib->apm_ops.reset(priv);
- priv->cfg->ops->lib->free_shared_mem(priv);
-
exit:
memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
@@ -2205,10 +2003,10 @@ static void __iwl4965_down(struct iwl_priv *priv)
iwl_clear_free_frames(priv);
}
-static void iwl4965_down(struct iwl_priv *priv)
+static void iwl_down(struct iwl_priv *priv)
{
mutex_lock(&priv->mutex);
- __iwl4965_down(priv);
+ __iwl_down(priv);
mutex_unlock(&priv->mutex);
iwl_cancel_deferred_work(priv);
@@ -2216,7 +2014,7 @@ static void iwl4965_down(struct iwl_priv *priv)
#define MAX_HW_RESTARTS 5
-static int __iwl4965_up(struct iwl_priv *priv)
+static int __iwl_up(struct iwl_priv *priv)
{
int i;
int ret;
@@ -2238,7 +2036,7 @@ static int __iwl4965_up(struct iwl_priv *priv)
set_bit(STATUS_RF_KILL_HW, &priv->status);
if (iwl_is_rfkill(priv)) {
- iwl4965_enable_interrupts(priv);
+ iwl_enable_interrupts(priv);
IWL_WARNING("Radio disabled by %s RF Kill switch\n",
test_bit(STATUS_RF_KILL_HW, &priv->status) ? "HW" : "SW");
return 0;
@@ -2246,12 +2044,6 @@ static int __iwl4965_up(struct iwl_priv *priv)
iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
- ret = priv->cfg->ops->lib->alloc_shared_mem(priv);
- if (ret) {
- IWL_ERROR("Unable to allocate shared memory\n");
- return ret;
- }
-
ret = iwl_hw_nic_init(priv);
if (ret) {
IWL_ERROR("Unable to init nic\n");
@@ -2265,7 +2057,7 @@ static int __iwl4965_up(struct iwl_priv *priv)
/* clear (again), then enable host interrupts */
iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
- iwl4965_enable_interrupts(priv);
+ iwl_enable_interrupts(priv);
/* really make sure rfkill handshake bits are cleared */
iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
@@ -2295,7 +2087,7 @@ static int __iwl4965_up(struct iwl_priv *priv)
clear_bit(STATUS_FW_ERROR, &priv->status);
/* start card; "initialize" will load runtime ucode */
- iwl4965_nic_start(priv);
+ iwl_nic_start(priv);
IWL_DEBUG_INFO(DRV_NAME " is coming up\n");
@@ -2303,7 +2095,7 @@ static int __iwl4965_up(struct iwl_priv *priv)
}
set_bit(STATUS_EXIT_PENDING, &priv->status);
- __iwl4965_down(priv);
+ __iwl_down(priv);
clear_bit(STATUS_EXIT_PENDING, &priv->status);
/* tried to restart and config the device for as long as our
@@ -2345,7 +2137,7 @@ static void iwl_bg_alive_start(struct work_struct *data)
mutex_unlock(&priv->mutex);
}
-static void iwl4965_bg_rf_kill(struct work_struct *work)
+static void iwl_bg_rf_kill(struct work_struct *work)
{
struct iwl_priv *priv = container_of(work, struct iwl_priv, rf_kill);
@@ -2379,28 +2171,6 @@ static void iwl4965_bg_rf_kill(struct work_struct *work)
iwl_rfkill_set_hw_state(priv);
}
-static void iwl4965_bg_set_monitor(struct work_struct *work)
-{
- struct iwl_priv *priv = container_of(work,
- struct iwl_priv, set_monitor);
- int ret;
-
- IWL_DEBUG(IWL_DL_STATE, "setting monitor mode\n");
-
- mutex_lock(&priv->mutex);
-
- ret = iwl4965_set_mode(priv, NL80211_IFTYPE_MONITOR);
-
- if (ret) {
- if (ret == -EAGAIN)
- IWL_DEBUG(IWL_DL_STATE, "leave - not ready\n");
- else
- IWL_ERROR("iwl4965_set_mode() failed ret = %d\n", ret);
- }
-
- mutex_unlock(&priv->mutex);
-}
-
static void iwl_bg_run_time_calib_work(struct work_struct *work)
{
struct iwl_priv *priv = container_of(work, struct iwl_priv,
@@ -2424,7 +2194,7 @@ static void iwl_bg_run_time_calib_work(struct work_struct *work)
return;
}
-static void iwl4965_bg_up(struct work_struct *data)
+static void iwl_bg_up(struct work_struct *data)
{
struct iwl_priv *priv = container_of(data, struct iwl_priv, up);
@@ -2432,23 +2202,23 @@ static void iwl4965_bg_up(struct work_struct *data)
return;
mutex_lock(&priv->mutex);
- __iwl4965_up(priv);
+ __iwl_up(priv);
mutex_unlock(&priv->mutex);
iwl_rfkill_set_hw_state(priv);
}
-static void iwl4965_bg_restart(struct work_struct *data)
+static void iwl_bg_restart(struct work_struct *data)
{
struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- iwl4965_down(priv);
+ iwl_down(priv);
queue_work(priv->workqueue, &priv->up);
}
-static void iwl4965_bg_rx_replenish(struct work_struct *data)
+static void iwl_bg_rx_replenish(struct work_struct *data)
{
struct iwl_priv *priv =
container_of(data, struct iwl_priv, rx_replenish);
@@ -2463,11 +2233,10 @@ static void iwl4965_bg_rx_replenish(struct work_struct *data)
#define IWL_DELAY_NEXT_SCAN (HZ*2)
-static void iwl4965_post_associate(struct iwl_priv *priv)
+static void iwl_post_associate(struct iwl_priv *priv)
{
struct ieee80211_conf *conf = NULL;
int ret = 0;
- DECLARE_MAC_BUF(mac);
unsigned long flags;
if (priv->iw_mode == NL80211_IFTYPE_AP) {
@@ -2475,9 +2244,8 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
return;
}
- IWL_DEBUG_ASSOC("Associated as %d to: %s\n",
- priv->assoc_id,
- print_mac(mac, priv->active_rxon.bssid_addr));
+ IWL_DEBUG_ASSOC("Associated as %d to: %pM\n",
+ priv->assoc_id, priv->active_rxon.bssid_addr);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
@@ -2493,10 +2261,9 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
conf = ieee80211_get_hw_conf(priv->hw);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl4965_commit_rxon(priv);
+ iwl_commit_rxon(priv);
- memset(&priv->rxon_timing, 0, sizeof(struct iwl4965_rxon_time_cmd));
- iwl4965_setup_rxon_timing(priv);
+ iwl_setup_rxon_timing(priv);
ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
sizeof(priv->rxon_timing), &priv->rxon_timing);
if (ret)
@@ -2529,7 +2296,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
}
- iwl4965_commit_rxon(priv);
+ iwl_commit_rxon(priv);
switch (priv->iw_mode) {
case NL80211_IFTYPE_STATION:
@@ -2541,7 +2308,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
priv->assoc_id = 1;
iwl_rxon_add_station(priv, priv->bssid, 0);
- iwl4965_send_beacon_cmd(priv);
+ iwl_send_beacon_cmd(priv);
break;
@@ -2578,7 +2345,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
#define UCODE_READY_TIMEOUT (4 * HZ)
-static int iwl4965_mac_start(struct ieee80211_hw *hw)
+static int iwl_mac_start(struct ieee80211_hw *hw)
{
struct iwl_priv *priv = hw->priv;
int ret;
@@ -2600,7 +2367,7 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw)
pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
}
- ret = request_irq(priv->pci_dev->irq, iwl4965_isr, IRQF_SHARED,
+ ret = request_irq(priv->pci_dev->irq, iwl_isr, IRQF_SHARED,
DRV_NAME, priv);
if (ret) {
IWL_ERROR("Error allocating IRQ %d\n", priv->pci_dev->irq);
@@ -2615,7 +2382,7 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw)
* ucode filename and max sizes are card-specific. */
if (!priv->ucode_code.len) {
- ret = iwl4965_read_ucode(priv);
+ ret = iwl_read_ucode(priv);
if (ret) {
IWL_ERROR("Could not read microcode: %d\n", ret);
mutex_unlock(&priv->mutex);
@@ -2623,7 +2390,7 @@ static int iwl4965_mac_start(struct ieee80211_hw *hw)
}
}
- ret = __iwl4965_up(priv);
+ ret = __iwl_up(priv);
mutex_unlock(&priv->mutex);
@@ -2669,7 +2436,7 @@ out_disable_msi:
return ret;
}
-static void iwl4965_mac_stop(struct ieee80211_hw *hw)
+static void iwl_mac_stop(struct ieee80211_hw *hw)
{
struct iwl_priv *priv = hw->priv;
@@ -2691,7 +2458,7 @@ static void iwl4965_mac_stop(struct ieee80211_hw *hw)
mutex_unlock(&priv->mutex);
}
- iwl4965_down(priv);
+ iwl_down(priv);
flush_workqueue(priv->workqueue);
free_irq(priv->pci_dev->irq, priv);
@@ -2702,7 +2469,7 @@ static void iwl4965_mac_stop(struct ieee80211_hw *hw)
IWL_DEBUG_MAC80211("leave\n");
}
-static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct iwl_priv *priv = hw->priv;
@@ -2718,12 +2485,11 @@ static int iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
return 0;
}
-static int iwl4965_mac_add_interface(struct ieee80211_hw *hw,
+static int iwl_mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
{
struct iwl_priv *priv = hw->priv;
unsigned long flags;
- DECLARE_MAC_BUF(mac);
IWL_DEBUG_MAC80211("enter: type %d\n", conf->type);
@@ -2734,17 +2500,18 @@ static int iwl4965_mac_add_interface(struct ieee80211_hw *hw,
spin_lock_irqsave(&priv->lock, flags);
priv->vif = conf->vif;
+ priv->iw_mode = conf->type;
spin_unlock_irqrestore(&priv->lock, flags);
mutex_lock(&priv->mutex);
if (conf->mac_addr) {
- IWL_DEBUG_MAC80211("Set %s\n", print_mac(mac, conf->mac_addr));
+ IWL_DEBUG_MAC80211("Set %pM\n", conf->mac_addr);
memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
}
- if (iwl4965_set_mode(priv, conf->type) == -EAGAIN)
+ if (iwl_set_mode(priv, conf->type) == -EAGAIN)
/* we are not ready, will run again when ready */
set_bit(STATUS_MODE_PENDING, &priv->status);
@@ -2755,16 +2522,17 @@ static int iwl4965_mac_add_interface(struct ieee80211_hw *hw,
}
/**
- * iwl4965_mac_config - mac80211 config callback
+ * iwl_mac_config - mac80211 config callback
*
* We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to
* be set inappropriately and the driver currently sets the hardware up to
* use it whenever needed.
*/
-static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+static int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
{
struct iwl_priv *priv = hw->priv;
const struct iwl_channel_info *ch_info;
+ struct ieee80211_conf *conf = &hw->conf;
unsigned long flags;
int ret = 0;
u16 channel;
@@ -2772,6 +2540,8 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value);
+ priv->current_ht_config.is_ht = conf->ht.enabled;
+
if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) {
IWL_DEBUG_MAC80211("leave - RF-KILL - waiting for uCode\n");
goto out;
@@ -2829,13 +2599,13 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
/* The list of supported rates and rate mask can be different
* for each band; since the band may have changed, reset
* the rate mask to what mac80211 lists */
- iwl4965_set_rate(priv);
+ iwl_set_rate(priv);
spin_unlock_irqrestore(&priv->lock, flags);
#ifdef IEEE80211_CONF_CHANNEL_SWITCH
if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) {
- iwl4965_hw_channel_switch(priv, conf->channel);
+ iwl_hw_channel_switch(priv, conf->channel);
goto out;
}
#endif
@@ -2863,11 +2633,11 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
iwl_set_tx_power(priv, conf->power_level, false);
- iwl4965_set_rate(priv);
+ iwl_set_rate(priv);
if (memcmp(&priv->active_rxon,
&priv->staging_rxon, sizeof(priv->staging_rxon)))
- iwl4965_commit_rxon(priv);
+ iwl_commit_rxon(priv);
else
IWL_DEBUG_INFO("No re-sending same RXON configuration.\n");
@@ -2878,7 +2648,7 @@ out:
return ret;
}
-static void iwl4965_config_ap(struct iwl_priv *priv)
+static void iwl_config_ap(struct iwl_priv *priv)
{
int ret = 0;
unsigned long flags;
@@ -2887,15 +2657,14 @@ static void iwl4965_config_ap(struct iwl_priv *priv)
return;
/* The following should be done only at AP bring up */
- if (!(iwl_is_associated(priv))) {
+ if (!iwl_is_associated(priv)) {
/* RXON - unassoc (to set timing command) */
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl4965_commit_rxon(priv);
+ iwl_commit_rxon(priv);
/* RXON Timing */
- memset(&priv->rxon_timing, 0, sizeof(struct iwl4965_rxon_time_cmd));
- iwl4965_setup_rxon_timing(priv);
+ iwl_setup_rxon_timing(priv);
ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING,
sizeof(priv->rxon_timing), &priv->rxon_timing);
if (ret)
@@ -2928,29 +2697,25 @@ static void iwl4965_config_ap(struct iwl_priv *priv)
}
/* restore RXON assoc */
priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
- iwl4965_commit_rxon(priv);
+ iwl_commit_rxon(priv);
spin_lock_irqsave(&priv->lock, flags);
iwl_activate_qos(priv, 1);
spin_unlock_irqrestore(&priv->lock, flags);
iwl_rxon_add_station(priv, iwl_bcast_addr, 0);
}
- iwl4965_send_beacon_cmd(priv);
+ iwl_send_beacon_cmd(priv);
/* FIXME - we need to add code here to detect a totally new
* configuration, reset the AP, unassoc, rxon timing, assoc,
* clear sta table, add BCAST sta... */
}
-/* temporary */
-static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb);
-static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
+static int iwl_mac_config_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_if_conf *conf)
{
struct iwl_priv *priv = hw->priv;
- DECLARE_MAC_BUF(mac);
- unsigned long flags;
int rc;
if (conf == NULL)
@@ -2966,26 +2731,20 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
if (!beacon)
return -ENOMEM;
- rc = iwl4965_mac_beacon_update(hw, beacon);
+ mutex_lock(&priv->mutex);
+ rc = iwl_mac_beacon_update(hw, beacon);
+ mutex_unlock(&priv->mutex);
if (rc)
return rc;
}
- if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
- (!conf->ssid_len)) {
- IWL_DEBUG_MAC80211
- ("Leaving in AP mode because HostAPD is not ready.\n");
- return 0;
- }
-
if (!iwl_is_alive(priv))
return -EAGAIN;
mutex_lock(&priv->mutex);
if (conf->bssid)
- IWL_DEBUG_MAC80211("bssid: %s\n",
- print_mac(mac, conf->bssid));
+ IWL_DEBUG_MAC80211("bssid: %pM\n", conf->bssid);
/*
* very dubious code was here; the probe filtering flag is never set:
@@ -2998,8 +2757,8 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
if (!conf->bssid) {
conf->bssid = priv->mac_addr;
memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
- IWL_DEBUG_MAC80211("bssid was set to: %s\n",
- print_mac(mac, conf->bssid));
+ IWL_DEBUG_MAC80211("bssid was set to: %pM\n",
+ conf->bssid);
}
if (priv->ibss_beacon)
dev_kfree_skb(priv->ibss_beacon);
@@ -3030,9 +2789,9 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
memcpy(priv->bssid, conf->bssid, ETH_ALEN);
if (priv->iw_mode == NL80211_IFTYPE_AP)
- iwl4965_config_ap(priv);
+ iwl_config_ap(priv);
else {
- rc = iwl4965_commit_rxon(priv);
+ rc = iwl_commit_rxon(priv);
if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc)
iwl_rxon_add_station(
priv, priv->active_rxon.bssid_addr, 1);
@@ -3041,45 +2800,63 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
} else {
iwl_scan_cancel_timeout(priv, 100);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl4965_commit_rxon(priv);
+ iwl_commit_rxon(priv);
}
done:
- spin_lock_irqsave(&priv->lock, flags);
- if (!conf->ssid_len)
- memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
- else
- memcpy(priv->essid, conf->ssid, conf->ssid_len);
-
- priv->essid_len = conf->ssid_len;
- spin_unlock_irqrestore(&priv->lock, flags);
-
IWL_DEBUG_MAC80211("leave\n");
mutex_unlock(&priv->mutex);
return 0;
}
-static void iwl4965_configure_filter(struct ieee80211_hw *hw,
+static void iwl_configure_filter(struct ieee80211_hw *hw,
unsigned int changed_flags,
unsigned int *total_flags,
int mc_count, struct dev_addr_list *mc_list)
{
struct iwl_priv *priv = hw->priv;
+ __le32 *filter_flags = &priv->staging_rxon.filter_flags;
- if (changed_flags & (*total_flags) & FIF_OTHER_BSS) {
- IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
- NL80211_IFTYPE_MONITOR,
- changed_flags, *total_flags);
- /* queue work 'cuz mac80211 is holding a lock which
- * prevents us from issuing (synchronous) f/w cmds */
- queue_work(priv->workqueue, &priv->set_monitor);
+ IWL_DEBUG_MAC80211("Enter: changed: 0x%x, total: 0x%x\n",
+ changed_flags, *total_flags);
+
+ if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) {
+ if (*total_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS))
+ *filter_flags |= RXON_FILTER_PROMISC_MSK;
+ else
+ *filter_flags &= ~RXON_FILTER_PROMISC_MSK;
+ }
+ if (changed_flags & FIF_ALLMULTI) {
+ if (*total_flags & FIF_ALLMULTI)
+ *filter_flags |= RXON_FILTER_ACCEPT_GRP_MSK;
+ else
+ *filter_flags &= ~RXON_FILTER_ACCEPT_GRP_MSK;
+ }
+ if (changed_flags & FIF_CONTROL) {
+ if (*total_flags & FIF_CONTROL)
+ *filter_flags |= RXON_FILTER_CTL2HOST_MSK;
+ else
+ *filter_flags &= ~RXON_FILTER_CTL2HOST_MSK;
}
- *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI |
+ if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
+ if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
+ *filter_flags |= RXON_FILTER_BCON_AWARE_MSK;
+ else
+ *filter_flags &= ~RXON_FILTER_BCON_AWARE_MSK;
+ }
+
+ /* We avoid iwl_commit_rxon here to commit the new filter flags
+ * since mac80211 will call ieee80211_hw_config immediately.
+ * (mc_list is not supported at this time). Otherwise, we need to
+ * queue a background iwl_commit_rxon work.
+ */
+
+ *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
}
-static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw,
+static void iwl_mac_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
{
struct iwl_priv *priv = hw->priv;
@@ -3091,13 +2868,11 @@ static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw,
if (iwl_is_ready_rf(priv)) {
iwl_scan_cancel_timeout(priv, 100);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl4965_commit_rxon(priv);
+ iwl_commit_rxon(priv);
}
if (priv->vif == conf->vif) {
priv->vif = NULL;
memset(priv->bssid, 0, ETH_ALEN);
- memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
- priv->essid_len = 0;
}
mutex_unlock(&priv->mutex);
@@ -3106,7 +2881,7 @@ static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw,
}
#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
-static void iwl4965_bss_info_changed(struct ieee80211_hw *hw,
+static void iwl_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
u32 changes)
@@ -3133,8 +2908,7 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw,
}
if (changes & BSS_CHANGED_HT) {
- IWL_DEBUG_MAC80211("HT %d\n", bss_conf->assoc_ht);
- iwl4965_ht_conf(priv, bss_conf);
+ iwl_ht_conf(priv, bss_conf);
iwl_set_rxon_chain(priv);
}
@@ -3157,7 +2931,7 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw,
priv->next_scan_jiffies = jiffies +
IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
mutex_lock(&priv->mutex);
- iwl4965_post_associate(priv);
+ iwl_post_associate(priv);
mutex_unlock(&priv->mutex);
} else {
priv->assoc_id = 0;
@@ -3187,12 +2961,6 @@ static int iwl_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t ssid_len)
goto out_unlock;
}
- if (priv->iw_mode == NL80211_IFTYPE_AP) { /* APs don't scan */
- ret = -EIO;
- IWL_ERROR("ERROR: APs don't scan\n");
- goto out_unlock;
- }
-
/* We don't schedule scan within next_scan_jiffies period.
* Avoid scanning during possible EAPOL exchange, return
* success immediately.
@@ -3233,64 +3001,24 @@ out_unlock:
return ret;
}
-static void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw,
+static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw,
struct ieee80211_key_conf *keyconf, const u8 *addr,
u32 iv32, u16 *phase1key)
{
- struct iwl_priv *priv = hw->priv;
- u8 sta_id = IWL_INVALID_STATION;
- unsigned long flags;
- __le16 key_flags = 0;
- int i;
- DECLARE_MAC_BUF(mac);
+ struct iwl_priv *priv = hw->priv;
IWL_DEBUG_MAC80211("enter\n");
- sta_id = iwl_find_station(priv, addr);
- if (sta_id == IWL_INVALID_STATION) {
- IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
- print_mac(mac, addr));
- return;
- }
-
- if (iwl_scan_cancel(priv)) {
- /* cancel scan failed, just live w/ bad key and rely
- briefly on SW decryption */
- return;
- }
-
- key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
- key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
- key_flags &= ~STA_KEY_FLG_INVALID;
-
- if (sta_id == priv->hw_params.bcast_sta_id)
- key_flags |= STA_KEY_MULTICAST_MSK;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
-
- priv->stations[sta_id].sta.key.key_flags = key_flags;
- priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
-
- for (i = 0; i < 5; i++)
- priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
- cpu_to_le16(phase1key[i]);
-
- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
-
- iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
-
- spin_unlock_irqrestore(&priv->sta_lock, flags);
+ iwl_update_tkip_key(priv, keyconf, addr, iv32, phase1key);
IWL_DEBUG_MAC80211("leave\n");
}
-static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
const u8 *local_addr, const u8 *addr,
struct ieee80211_key_conf *key)
{
struct iwl_priv *priv = hw->priv;
- DECLARE_MAC_BUF(mac);
int ret = 0;
u8 sta_id = IWL_INVALID_STATION;
u8 is_default_wep_key = 0;
@@ -3308,8 +3036,8 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
sta_id = iwl_find_station(priv, addr);
if (sta_id == IWL_INVALID_STATION) {
- IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
- print_mac(mac, addr));
+ IWL_DEBUG_MAC80211("leave - %pM not in station map.\n",
+ addr);
return -EINVAL;
}
@@ -3357,7 +3085,7 @@ static int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return ret;
}
-static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
+static int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct iwl_priv *priv = hw->priv;
@@ -3376,11 +3104,6 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
return 0;
}
- if (!priv->qos_data.qos_enable) {
- priv->qos_data.qos_active = 0;
- IWL_DEBUG_MAC80211("leave - qos not enabled\n");
- return 0;
- }
q = AC_NUM - 1 - queue;
spin_lock_irqsave(&priv->lock, flags);
@@ -3405,15 +3128,14 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
return 0;
}
-static int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
+static int iwl_mac_ampdu_action(struct ieee80211_hw *hw,
enum ieee80211_ampdu_mlme_action action,
struct ieee80211_sta *sta, u16 tid, u16 *ssn)
{
struct iwl_priv *priv = hw->priv;
- DECLARE_MAC_BUF(mac);
- IWL_DEBUG_HT("A-MPDU action on addr %s tid %d\n",
- print_mac(mac, sta->addr), tid);
+ IWL_DEBUG_HT("A-MPDU action on addr %pM tid %d\n",
+ sta->addr, tid);
if (!(priv->cfg->sku & IWL_SKU_N))
return -EACCES;
@@ -3421,10 +3143,10 @@ static int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
switch (action) {
case IEEE80211_AMPDU_RX_START:
IWL_DEBUG_HT("start Rx\n");
- return iwl_rx_agg_start(priv, sta->addr, tid, *ssn);
+ return iwl_sta_rx_agg_start(priv, sta->addr, tid, *ssn);
case IEEE80211_AMPDU_RX_STOP:
IWL_DEBUG_HT("stop Rx\n");
- return iwl_rx_agg_stop(priv, sta->addr, tid);
+ return iwl_sta_rx_agg_stop(priv, sta->addr, tid);
case IEEE80211_AMPDU_TX_START:
IWL_DEBUG_HT("start Tx\n");
return iwl_tx_agg_start(priv, sta->addr, tid, ssn);
@@ -3438,7 +3160,8 @@ static int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
}
return 0;
}
-static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw,
+
+static int iwl_mac_get_tx_stats(struct ieee80211_hw *hw,
struct ieee80211_tx_queue_stats *stats)
{
struct iwl_priv *priv = hw->priv;
@@ -3473,7 +3196,7 @@ static int iwl4965_mac_get_tx_stats(struct ieee80211_hw *hw,
return 0;
}
-static int iwl4965_mac_get_stats(struct ieee80211_hw *hw,
+static int iwl_mac_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats)
{
struct iwl_priv *priv = hw->priv;
@@ -3485,7 +3208,7 @@ static int iwl4965_mac_get_stats(struct ieee80211_hw *hw,
return 0;
}
-static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
+static void iwl_mac_reset_tsf(struct ieee80211_hw *hw)
{
struct iwl_priv *priv = hw->priv;
unsigned long flags;
@@ -3529,7 +3252,7 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
if (priv->iw_mode != NL80211_IFTYPE_AP) {
iwl_scan_cancel_timeout(priv, 100);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- iwl4965_commit_rxon(priv);
+ iwl_commit_rxon(priv);
}
iwl_power_update_mode(priv, 0);
@@ -3552,31 +3275,28 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
return;
}
- iwl4965_set_rate(priv);
+ iwl_set_rate(priv);
mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211("leave\n");
}
-static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
+static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct iwl_priv *priv = hw->priv;
unsigned long flags;
__le64 timestamp;
- mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211("enter\n");
if (!iwl_is_ready_rf(priv)) {
IWL_DEBUG_MAC80211("leave - RF not ready\n");
- mutex_unlock(&priv->mutex);
return -EIO;
}
if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
IWL_DEBUG_MAC80211("leave - not IBSS\n");
- mutex_unlock(&priv->mutex);
return -EIO;
}
@@ -3596,9 +3316,8 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
iwl_reset_qos(priv);
- iwl4965_post_associate(priv);
+ iwl_post_associate(priv);
- mutex_unlock(&priv->mutex);
return 0;
}
@@ -3613,7 +3332,7 @@ static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
/*
* The following adds a new attribute to the sysfs representation
- * of this device driver (i.e. a new file in /sys/bus/pci/drivers/iwl/)
+ * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
* used for controlling the debug level.
*
* See the level definitions in iwl for details.
@@ -3699,7 +3418,11 @@ static ssize_t show_tx_power(struct device *d,
struct device_attribute *attr, char *buf)
{
struct iwl_priv *priv = (struct iwl_priv *)d->driver_data;
- return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
+
+ if (!iwl_is_ready_rf(priv))
+ return sprintf(buf, "off\n");
+ else
+ return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
}
static ssize_t store_tx_power(struct device *d,
@@ -3750,7 +3473,7 @@ static ssize_t store_flags(struct device *d,
else {
IWL_DEBUG_INFO("Commit rxon.flags = 0x%04X\n", flags);
priv->staging_rxon.flags = cpu_to_le32(flags);
- iwl4965_commit_rxon(priv);
+ iwl_commit_rxon(priv);
}
}
mutex_unlock(&priv->mutex);
@@ -3791,7 +3514,7 @@ static ssize_t store_filter_flags(struct device *d,
"0x%04X\n", filter_flags);
priv->staging_rxon.filter_flags =
cpu_to_le32(filter_flags);
- iwl4965_commit_rxon(priv);
+ iwl_commit_rxon(priv);
}
}
mutex_unlock(&priv->mutex);
@@ -3802,79 +3525,6 @@ static ssize_t store_filter_flags(struct device *d,
static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
store_filter_flags);
-#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT
-
-static ssize_t show_measurement(struct device *d,
- struct device_attribute *attr, char *buf)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- struct iwl4965_spectrum_notification measure_report;
- u32 size = sizeof(measure_report), len = 0, ofs = 0;
- u8 *data = (u8 *)&measure_report;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
- if (!(priv->measurement_status & MEASUREMENT_READY)) {
- spin_unlock_irqrestore(&priv->lock, flags);
- return 0;
- }
- memcpy(&measure_report, &priv->measure_report, size);
- priv->measurement_status = 0;
- spin_unlock_irqrestore(&priv->lock, flags);
-
- while (size && (PAGE_SIZE - len)) {
- hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
- PAGE_SIZE - len, 1);
- len = strlen(buf);
- if (PAGE_SIZE - len)
- buf[len++] = '\n';
-
- ofs += 16;
- size -= min(size, 16U);
- }
-
- return len;
-}
-
-static ssize_t store_measurement(struct device *d,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct iwl_priv *priv = dev_get_drvdata(d);
- struct ieee80211_measurement_params params = {
- .channel = le16_to_cpu(priv->active_rxon.channel),
- .start_time = cpu_to_le64(priv->last_tsf),
- .duration = cpu_to_le16(1),
- };
- u8 type = IWL_MEASURE_BASIC;
- u8 buffer[32];
- u8 channel;
-
- if (count) {
- char *p = buffer;
- strncpy(buffer, buf, min(sizeof(buffer), count));
- channel = simple_strtoul(p, NULL, 0);
- if (channel)
- params.channel = channel;
-
- p = buffer;
- while (*p && *p != ' ')
- p++;
- if (*p)
- type = simple_strtoul(p + 1, NULL, 0);
- }
-
- IWL_DEBUG_INFO("Invoking measurement of type %d on "
- "channel %d (for '%s')\n", type, params.channel, buf);
- iwl4965_get_measurement(priv, &params, type);
-
- return count;
-}
-
-static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR,
- show_measurement, store_measurement);
-#endif /* CONFIG_IWLAGN_SPECTRUM_MEASUREMENT */
-
static ssize_t store_retry_rate(struct device *d,
struct device_attribute *attr,
const char *buf, size_t count)
@@ -3953,7 +3603,8 @@ static ssize_t show_power_level(struct device *d,
break;
}
- p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO)?"fixed":"auto");
+ p += sprintf(p, "\tMODE:%s", (mode < IWL_POWER_AUTO) ?
+ "fixed" : "auto");
p += sprintf(p, "\tINDEX:%d", level);
p += sprintf(p, "\n");
return p - buf + 1;
@@ -3962,68 +3613,6 @@ static ssize_t show_power_level(struct device *d,
static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
store_power_level);
-static ssize_t show_channels(struct device *d,
- struct device_attribute *attr, char *buf)
-{
-
- struct iwl_priv *priv = dev_get_drvdata(d);
- struct ieee80211_channel *channels = NULL;
- const struct ieee80211_supported_band *supp_band = NULL;
- int len = 0, i;
- int count = 0;
-
- if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
- return -EAGAIN;
-
- supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ);
- channels = supp_band->channels;
- count = supp_band->n_channels;
-
- len += sprintf(&buf[len],
- "Displaying %d channels in 2.4GHz band "
- "(802.11bg):\n", count);
-
- for (i = 0; i < count; i++)
- len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
- ieee80211_frequency_to_channel(
- channels[i].center_freq),
- channels[i].max_power,
- channels[i].flags & IEEE80211_CHAN_RADAR ?
- " (IEEE 802.11h required)" : "",
- (!(channels[i].flags & IEEE80211_CHAN_NO_IBSS)
- || (channels[i].flags &
- IEEE80211_CHAN_RADAR)) ? "" :
- ", IBSS",
- channels[i].flags &
- IEEE80211_CHAN_PASSIVE_SCAN ?
- "passive only" : "active/passive");
-
- supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ);
- channels = supp_band->channels;
- count = supp_band->n_channels;
-
- len += sprintf(&buf[len], "Displaying %d channels in 5.2GHz band "
- "(802.11a):\n", count);
-
- for (i = 0; i < count; i++)
- len += sprintf(&buf[len], "%d: %ddBm: BSS%s%s, %s.\n",
- ieee80211_frequency_to_channel(
- channels[i].center_freq),
- channels[i].max_power,
- channels[i].flags & IEEE80211_CHAN_RADAR ?
- " (IEEE 802.11h required)" : "",
- ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
- || (channels[i].flags &
- IEEE80211_CHAN_RADAR)) ? "" :
- ", IBSS",
- channels[i].flags &
- IEEE80211_CHAN_PASSIVE_SCAN ?
- "passive only" : "active/passive");
-
- return len;
-}
-
-static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
static ssize_t show_statistics(struct device *d,
struct device_attribute *attr, char *buf)
@@ -4086,12 +3675,11 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
init_waitqueue_head(&priv->wait_command_queue);
- INIT_WORK(&priv->up, iwl4965_bg_up);
- INIT_WORK(&priv->restart, iwl4965_bg_restart);
- INIT_WORK(&priv->rx_replenish, iwl4965_bg_rx_replenish);
- INIT_WORK(&priv->rf_kill, iwl4965_bg_rf_kill);
- INIT_WORK(&priv->beacon_update, iwl4965_bg_beacon_update);
- INIT_WORK(&priv->set_monitor, iwl4965_bg_set_monitor);
+ INIT_WORK(&priv->up, iwl_bg_up);
+ INIT_WORK(&priv->restart, iwl_bg_restart);
+ INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish);
+ INIT_WORK(&priv->rf_kill, iwl_bg_rf_kill);
+ INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update);
INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
@@ -4104,10 +3692,10 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
init_timer(&priv->statistics_periodic);
priv->statistics_periodic.data = (unsigned long)priv;
- priv->statistics_periodic.function = iwl4965_bg_statistics_periodic;
+ priv->statistics_periodic.function = iwl_bg_statistics_periodic;
tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
- iwl4965_irq_tasklet, (unsigned long)priv);
+ iwl_irq_tasklet, (unsigned long)priv);
}
static void iwl_cancel_deferred_work(struct iwl_priv *priv)
@@ -4123,13 +3711,9 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
del_timer_sync(&priv->statistics_periodic);
}
-static struct attribute *iwl4965_sysfs_entries[] = {
- &dev_attr_channels.attr,
+static struct attribute *iwl_sysfs_entries[] = {
&dev_attr_flags.attr,
&dev_attr_filter_flags.attr,
-#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT
- &dev_attr_measurement.attr,
-#endif
&dev_attr_power_level.attr,
&dev_attr_retry_rate.attr,
&dev_attr_statistics.attr,
@@ -4144,39 +3728,38 @@ static struct attribute *iwl4965_sysfs_entries[] = {
NULL
};
-static struct attribute_group iwl4965_attribute_group = {
+static struct attribute_group iwl_attribute_group = {
.name = NULL, /* put in device directory */
- .attrs = iwl4965_sysfs_entries,
+ .attrs = iwl_sysfs_entries,
};
-static struct ieee80211_ops iwl4965_hw_ops = {
- .tx = iwl4965_mac_tx,
- .start = iwl4965_mac_start,
- .stop = iwl4965_mac_stop,
- .add_interface = iwl4965_mac_add_interface,
- .remove_interface = iwl4965_mac_remove_interface,
- .config = iwl4965_mac_config,
- .config_interface = iwl4965_mac_config_interface,
- .configure_filter = iwl4965_configure_filter,
- .set_key = iwl4965_mac_set_key,
- .update_tkip_key = iwl4965_mac_update_tkip_key,
- .get_stats = iwl4965_mac_get_stats,
- .get_tx_stats = iwl4965_mac_get_tx_stats,
- .conf_tx = iwl4965_mac_conf_tx,
- .reset_tsf = iwl4965_mac_reset_tsf,
- .bss_info_changed = iwl4965_bss_info_changed,
- .ampdu_action = iwl4965_mac_ampdu_action,
+static struct ieee80211_ops iwl_hw_ops = {
+ .tx = iwl_mac_tx,
+ .start = iwl_mac_start,
+ .stop = iwl_mac_stop,
+ .add_interface = iwl_mac_add_interface,
+ .remove_interface = iwl_mac_remove_interface,
+ .config = iwl_mac_config,
+ .config_interface = iwl_mac_config_interface,
+ .configure_filter = iwl_configure_filter,
+ .set_key = iwl_mac_set_key,
+ .update_tkip_key = iwl_mac_update_tkip_key,
+ .get_stats = iwl_mac_get_stats,
+ .get_tx_stats = iwl_mac_get_tx_stats,
+ .conf_tx = iwl_mac_conf_tx,
+ .reset_tsf = iwl_mac_reset_tsf,
+ .bss_info_changed = iwl_bss_info_changed,
+ .ampdu_action = iwl_mac_ampdu_action,
.hw_scan = iwl_mac_hw_scan
};
-static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
int err = 0;
struct iwl_priv *priv;
struct ieee80211_hw *hw;
struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
unsigned long flags;
- DECLARE_MAC_BUF(mac);
/************************
* 1. Allocating HW data
@@ -4188,10 +3771,10 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
if (cfg->mod_params->debug & IWL_DL_INFO)
dev_printk(KERN_DEBUG, &(pdev->dev),
"Disabling hw_scan\n");
- iwl4965_hw_ops.hw_scan = NULL;
+ iwl_hw_ops.hw_scan = NULL;
}
- hw = iwl_alloc_all(cfg, &iwl4965_hw_ops);
+ hw = iwl_alloc_all(cfg, &iwl_hw_ops);
if (!hw) {
err = -ENOMEM;
goto out;
@@ -4285,7 +3868,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
/* extract MAC Address */
iwl_eeprom_get_mac(priv, priv->mac_addr);
- IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
+ IWL_DEBUG_INFO("MAC address: %pM\n", priv->mac_addr);
SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
/************************
@@ -4319,10 +3902,10 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
* 8. Setup services
********************/
spin_lock_irqsave(&priv->lock, flags);
- iwl4965_disable_interrupts(priv);
+ iwl_disable_interrupts(priv);
spin_unlock_irqrestore(&priv->lock, flags);
- err = sysfs_create_group(&pdev->dev.kobj, &iwl4965_attribute_group);
+ err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group);
if (err) {
IWL_ERROR("failed to create sysfs device attributes\n");
goto out_uninit_drv;
@@ -4358,7 +3941,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
return 0;
out_remove_sysfs:
- sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
+ sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
out_uninit_drv:
iwl_uninit_drv(priv);
out_free_eeprom:
@@ -4376,7 +3959,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
return err;
}
-static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
+static void __devexit iwl_pci_remove(struct pci_dev *pdev)
{
struct iwl_priv *priv = pci_get_drvdata(pdev);
unsigned long flags;
@@ -4387,10 +3970,10 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
IWL_DEBUG_INFO("*** UNLOAD DRIVER ***\n");
iwl_dbgfs_unregister(priv);
- sysfs_remove_group(&pdev->dev.kobj, &iwl4965_attribute_group);
+ sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
- /* ieee80211_unregister_hw call wil cause iwl4965_mac_stop to
- * to be called and iwl4965_down since we are removing the device
+ /* ieee80211_unregister_hw call wil cause iwl_mac_stop to
+ * to be called and iwl_down since we are removing the device
* we need to set STATUS_EXIT_PENDING bit.
*/
set_bit(STATUS_EXIT_PENDING, &priv->status);
@@ -4398,20 +3981,20 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
ieee80211_unregister_hw(priv->hw);
priv->mac80211_registered = 0;
} else {
- iwl4965_down(priv);
+ iwl_down(priv);
}
/* make sure we flush any pending irq or
* tasklet for the driver
*/
spin_lock_irqsave(&priv->lock, flags);
- iwl4965_disable_interrupts(priv);
+ iwl_disable_interrupts(priv);
spin_unlock_irqrestore(&priv->lock, flags);
iwl_synchronize_irq(priv);
iwl_rfkill_unregister(priv);
- iwl4965_dealloc_ucode_pci(priv);
+ iwl_dealloc_ucode_pci(priv);
if (priv->rxq.bd)
iwl_rx_queue_free(priv, &priv->rxq);
@@ -4424,7 +4007,7 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
/*netif_stop_queue(dev); */
flush_workqueue(priv->workqueue);
- /* ieee80211_unregister_hw calls iwl4965_mac_stop, which flushes
+ /* ieee80211_unregister_hw calls iwl_mac_stop, which flushes
* priv->workqueue... so we can't take down the workqueue
* until now... */
destroy_workqueue(priv->workqueue);
@@ -4445,13 +4028,13 @@ static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
#ifdef CONFIG_PM
-static int iwl4965_pci_suspend(struct pci_dev *pdev, pm_message_t state)
+static int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct iwl_priv *priv = pci_get_drvdata(pdev);
if (priv->is_open) {
set_bit(STATUS_IN_SUSPEND, &priv->status);
- iwl4965_mac_stop(priv->hw);
+ iwl_mac_stop(priv->hw);
priv->is_open = 1;
}
@@ -4460,14 +4043,14 @@ static int iwl4965_pci_suspend(struct pci_dev *pdev, pm_message_t state)
return 0;
}
-static int iwl4965_pci_resume(struct pci_dev *pdev)
+static int iwl_pci_resume(struct pci_dev *pdev)
{
struct iwl_priv *priv = pci_get_drvdata(pdev);
pci_set_power_state(pdev, PCI_D0);
if (priv->is_open)
- iwl4965_mac_start(priv->hw);
+ iwl_mac_start(priv->hw);
clear_bit(STATUS_IN_SUSPEND, &priv->status);
return 0;
@@ -4502,7 +4085,11 @@ static struct pci_device_id iwl_hw_card_ids[] = {
{IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)},
{IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)},
{IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)},
+/* 5150 Wifi/WiMax */
+ {IWL_PCI_DEVICE(0x423C, PCI_ANY_ID, iwl5150_agn_cfg)},
+ {IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)},
#endif /* CONFIG_IWL5000 */
+
{0}
};
MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
@@ -4510,15 +4097,15 @@ MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids);
static struct pci_driver iwl_driver = {
.name = DRV_NAME,
.id_table = iwl_hw_card_ids,
- .probe = iwl4965_pci_probe,
- .remove = __devexit_p(iwl4965_pci_remove),
+ .probe = iwl_pci_probe,
+ .remove = __devexit_p(iwl_pci_remove),
#ifdef CONFIG_PM
- .suspend = iwl4965_pci_suspend,
- .resume = iwl4965_pci_resume,
+ .suspend = iwl_pci_suspend,
+ .resume = iwl_pci_resume,
#endif
};
-static int __init iwl4965_init(void)
+static int __init iwl_init(void)
{
int ret;
@@ -4544,11 +4131,11 @@ error_register:
return ret;
}
-static void __exit iwl4965_exit(void)
+static void __exit iwl_exit(void)
{
pci_unregister_driver(&iwl_driver);
iwlagn_rate_control_unregister();
}
-module_exit(iwl4965_exit);
-module_init(iwl4965_init);
+module_exit(iwl_exit);
+module_init(iwl_init);
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c
index 72fbf47229db..f836ecc55758 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.c
@@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
- * Tomas Winkler <tomas.winkler@intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@@ -70,7 +70,16 @@
* INIT calibrations framework
*****************************************************************************/
- int iwl_send_calib_results(struct iwl_priv *priv)
+struct statistics_general_data {
+ u32 beacon_silence_rssi_a;
+ u32 beacon_silence_rssi_b;
+ u32 beacon_silence_rssi_c;
+ u32 beacon_energy_a;
+ u32 beacon_energy_b;
+ u32 beacon_energy_c;
+};
+
+int iwl_send_calib_results(struct iwl_priv *priv)
{
int ret = 0;
int i = 0;
@@ -80,14 +89,16 @@
.meta.flags = CMD_SIZE_HUGE,
};
- for (i = 0; i < IWL_CALIB_MAX; i++)
- if (priv->calib_results[i].buf) {
+ for (i = 0; i < IWL_CALIB_MAX; i++) {
+ if ((BIT(i) & priv->hw_params.calib_init_cfg) &&
+ priv->calib_results[i].buf) {
hcmd.len = priv->calib_results[i].buf_len;
hcmd.data = priv->calib_results[i].buf;
ret = iwl_send_cmd_sync(priv, &hcmd);
if (ret)
goto err;
}
+ }
return 0;
err:
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.h b/drivers/net/wireless/iwlwifi/iwl-calib.h
index 94c8e316382a..1abe84bb74ad 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.h
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.h
@@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
- * Tomas Winkler <tomas.winkler@intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 8d04e966ad48..52966ffbef6e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@@ -66,8 +66,14 @@
* Please use iwl-dev.h for driver implementation definitions.
*/
-#ifndef __iwl4965_commands_h__
-#define __iwl4965_commands_h__
+#ifndef __iwl_commands_h__
+#define __iwl_commands_h__
+
+/* uCode version contains 4 values: Major/Minor/API/Serial */
+#define IWL_UCODE_MAJOR(ver) (((ver) & 0xFF000000) >> 24)
+#define IWL_UCODE_MINOR(ver) (((ver) & 0x00FF0000) >> 16)
+#define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8)
+#define IWL_UCODE_SERIAL(ver) ((ver) & 0x000000FF)
enum {
REPLY_ALIVE = 0x1,
@@ -88,6 +94,7 @@ enum {
REPLY_WEPKEY = 0x20,
/* RX, TX, LEDs */
+ REPLY_3945_RX = 0x1b, /* 3945 only */
REPLY_TX = 0x1c,
REPLY_RATE_SCALE = 0x47, /* 3945 only */
REPLY_LEDS_CMD = 0x48,
@@ -98,6 +105,11 @@ enum {
COEX_MEDIUM_NOTIFICATION = 0x5b,
COEX_EVENT_CMD = 0x5c,
+ /* Calibration */
+ CALIBRATION_CFG_CMD = 0x65,
+ CALIBRATION_RES_NOTIFICATION = 0x66,
+ CALIBRATION_COMPLETE_NOTIFICATION = 0x67,
+
/* 802.11h related */
RADAR_NOTIFICATION = 0x70, /* not used */
REPLY_QUIET_CMD = 0x71, /* not used */
@@ -129,7 +141,7 @@ enum {
REPLY_TX_POWER_DBM_CMD = 0x98,
MEASURE_ABORT_NOTIFICATION = 0x99, /* not used */
- /* Bluetooth device coexistance config command */
+ /* Bluetooth device coexistence config command */
REPLY_BT_CONFIG = 0x9b,
/* Statistics */
@@ -167,8 +179,8 @@ enum {
#define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8)
#define SEQ_TO_INDEX(s) ((s) & 0xff)
#define INDEX_TO_SEQ(i) ((i) & 0xff)
-#define SEQ_HUGE_FRAME __constant_cpu_to_le16(0x4000)
-#define SEQ_RX_FRAME __constant_cpu_to_le16(0x8000)
+#define SEQ_HUGE_FRAME cpu_to_le16(0x4000)
+#define SEQ_RX_FRAME cpu_to_le16(0x8000)
/**
* struct iwl_cmd_header
@@ -180,7 +192,7 @@ struct iwl_cmd_header {
u8 cmd; /* Command ID: REPLY_RXON, etc. */
u8 flags; /* 0:5 reserved, 6 abort, 7 internal */
/*
- * The driver sets up the sequence number to values of its chosing.
+ * The driver sets up the sequence number to values of its choosing.
* uCode does not use this value, but passes it back to the driver
* when sending the response to each driver-originated command, so
* the driver can match the response to the command. Since the values
@@ -208,10 +220,11 @@ struct iwl_cmd_header {
} __attribute__ ((packed));
/**
- * 4965 rate_n_flags bit fields
+ * iwlagn rate_n_flags bit fields
*
- * rate_n_flags format is used in following 4965 commands:
+ * rate_n_flags format is used in following iwlagn commands:
* REPLY_RX (response only)
+ * REPLY_RX_MPDU (response only)
* REPLY_TX (both command and response)
* REPLY_TX_LINK_QUALITY_CMD
*
@@ -225,8 +238,9 @@ struct iwl_cmd_header {
* 6) 54 Mbps
* 7) 60 Mbps
*
- * 3: 0) Single stream (SISO)
+ * 4-3: 0) Single stream (SISO)
* 1) Dual stream (MIMO)
+ * 2) Triple stream (MIMO)
*
* 5: Value of 0x20 in bits 7:0 indicates 6 Mbps FAT duplicate data
*
@@ -247,8 +261,8 @@ struct iwl_cmd_header {
* 110) 11 Mbps
*/
#define RATE_MCS_CODE_MSK 0x7
-#define RATE_MCS_MIMO_POS 3
-#define RATE_MCS_MIMO_MSK 0x8
+#define RATE_MCS_SPATIAL_POS 3
+#define RATE_MCS_SPATIAL_MSK 0x18
#define RATE_MCS_HT_DUP_POS 5
#define RATE_MCS_HT_DUP_MSK 0x20
@@ -278,18 +292,20 @@ struct iwl_cmd_header {
#define RATE_MCS_SGI_MSK 0x2000
/**
- * rate_n_flags Tx antenna masks (4965 has 2 transmitters):
- * bit14:15 01 B inactive, A active
- * 10 B active, A inactive
- * 11 Both active
+ * rate_n_flags Tx antenna masks
+ * 4965 has 2 transmitters
+ * 5100 has 1 transmitter B
+ * 5150 has 1 transmitter A
+ * 5300 has 3 transmitters
+ * 5350 has 3 transmitters
+ * bit14:16
*/
#define RATE_MCS_ANT_POS 14
#define RATE_MCS_ANT_A_MSK 0x04000
#define RATE_MCS_ANT_B_MSK 0x08000
#define RATE_MCS_ANT_C_MSK 0x10000
#define RATE_MCS_ANT_ABC_MSK 0x1C000
-
-#define RATE_MCS_ANT_INIT_IND 1
+#define RATE_ANT_NUM 3
#define POWER_TABLE_NUM_ENTRIES 33
#define POWER_TABLE_NUM_HT_OFDM_ENTRIES 32
@@ -340,7 +356,7 @@ struct iwl4965_tx_power_db {
} __attribute__ ((packed));
/**
- * Commad REPLY_TX_POWER_DBM_CMD = 0x98
+ * Command REPLY_TX_POWER_DBM_CMD = 0x98
* struct iwl5000_tx_power_dbm_cmd
*/
#define IWL50_TX_POWER_AUTO 0x7f
@@ -359,7 +375,7 @@ struct iwl5000_tx_power_dbm_cmd {
*
*****************************************************************************/
-#define UCODE_VALID_OK __constant_cpu_to_le32(0x1)
+#define UCODE_VALID_OK cpu_to_le32(0x1)
#define INITIALIZE_SUBTYPE (9)
/*
@@ -376,7 +392,7 @@ struct iwl5000_tx_power_dbm_cmd {
* calculating txpower settings:
*
* 1) Power supply voltage indication. The voltage sensor outputs higher
- * values for lower voltage, and vice versa.
+ * values for lower voltage, and vice verse.
*
* 2) Temperature measurement parameters, for each of two channel widths
* (20 MHz and 40 MHz) supported by the radios. Temperature sensing
@@ -477,11 +493,6 @@ struct iwl_alive_resp {
} __attribute__ ((packed));
-union tsf {
- u8 byte[8];
- __le16 word[4];
- __le32 dw[2];
-};
/*
* REPLY_ERROR = 0x2 (response only, not a command)
@@ -492,7 +503,7 @@ struct iwl_error_resp {
u8 reserved1;
__le16 bad_cmd_seq_num;
__le32 error_info;
- union tsf timestamp;
+ __le64 timestamp;
} __attribute__ ((packed));
/******************************************************************************
@@ -513,75 +524,75 @@ enum {
};
-#define RXON_RX_CHAIN_DRIVER_FORCE_MSK __constant_cpu_to_le16(0x1 << 0)
-#define RXON_RX_CHAIN_VALID_MSK __constant_cpu_to_le16(0x7 << 1)
+#define RXON_RX_CHAIN_DRIVER_FORCE_MSK cpu_to_le16(0x1 << 0)
+#define RXON_RX_CHAIN_VALID_MSK cpu_to_le16(0x7 << 1)
#define RXON_RX_CHAIN_VALID_POS (1)
-#define RXON_RX_CHAIN_FORCE_SEL_MSK __constant_cpu_to_le16(0x7 << 4)
+#define RXON_RX_CHAIN_FORCE_SEL_MSK cpu_to_le16(0x7 << 4)
#define RXON_RX_CHAIN_FORCE_SEL_POS (4)
-#define RXON_RX_CHAIN_FORCE_MIMO_SEL_MSK __constant_cpu_to_le16(0x7 << 7)
+#define RXON_RX_CHAIN_FORCE_MIMO_SEL_MSK cpu_to_le16(0x7 << 7)
#define RXON_RX_CHAIN_FORCE_MIMO_SEL_POS (7)
-#define RXON_RX_CHAIN_CNT_MSK __constant_cpu_to_le16(0x3 << 10)
+#define RXON_RX_CHAIN_CNT_MSK cpu_to_le16(0x3 << 10)
#define RXON_RX_CHAIN_CNT_POS (10)
-#define RXON_RX_CHAIN_MIMO_CNT_MSK __constant_cpu_to_le16(0x3 << 12)
+#define RXON_RX_CHAIN_MIMO_CNT_MSK cpu_to_le16(0x3 << 12)
#define RXON_RX_CHAIN_MIMO_CNT_POS (12)
-#define RXON_RX_CHAIN_MIMO_FORCE_MSK __constant_cpu_to_le16(0x1 << 14)
+#define RXON_RX_CHAIN_MIMO_FORCE_MSK cpu_to_le16(0x1 << 14)
#define RXON_RX_CHAIN_MIMO_FORCE_POS (14)
/* rx_config flags */
/* band & modulation selection */
-#define RXON_FLG_BAND_24G_MSK __constant_cpu_to_le32(1 << 0)
-#define RXON_FLG_CCK_MSK __constant_cpu_to_le32(1 << 1)
+#define RXON_FLG_BAND_24G_MSK cpu_to_le32(1 << 0)
+#define RXON_FLG_CCK_MSK cpu_to_le32(1 << 1)
/* auto detection enable */
-#define RXON_FLG_AUTO_DETECT_MSK __constant_cpu_to_le32(1 << 2)
+#define RXON_FLG_AUTO_DETECT_MSK cpu_to_le32(1 << 2)
/* TGg protection when tx */
-#define RXON_FLG_TGG_PROTECT_MSK __constant_cpu_to_le32(1 << 3)
+#define RXON_FLG_TGG_PROTECT_MSK cpu_to_le32(1 << 3)
/* cck short slot & preamble */
-#define RXON_FLG_SHORT_SLOT_MSK __constant_cpu_to_le32(1 << 4)
-#define RXON_FLG_SHORT_PREAMBLE_MSK __constant_cpu_to_le32(1 << 5)
+#define RXON_FLG_SHORT_SLOT_MSK cpu_to_le32(1 << 4)
+#define RXON_FLG_SHORT_PREAMBLE_MSK cpu_to_le32(1 << 5)
/* antenna selection */
-#define RXON_FLG_DIS_DIV_MSK __constant_cpu_to_le32(1 << 7)
-#define RXON_FLG_ANT_SEL_MSK __constant_cpu_to_le32(0x0f00)
-#define RXON_FLG_ANT_A_MSK __constant_cpu_to_le32(1 << 8)
-#define RXON_FLG_ANT_B_MSK __constant_cpu_to_le32(1 << 9)
+#define RXON_FLG_DIS_DIV_MSK cpu_to_le32(1 << 7)
+#define RXON_FLG_ANT_SEL_MSK cpu_to_le32(0x0f00)
+#define RXON_FLG_ANT_A_MSK cpu_to_le32(1 << 8)
+#define RXON_FLG_ANT_B_MSK cpu_to_le32(1 << 9)
/* radar detection enable */
-#define RXON_FLG_RADAR_DETECT_MSK __constant_cpu_to_le32(1 << 12)
-#define RXON_FLG_TGJ_NARROW_BAND_MSK __constant_cpu_to_le32(1 << 13)
+#define RXON_FLG_RADAR_DETECT_MSK cpu_to_le32(1 << 12)
+#define RXON_FLG_TGJ_NARROW_BAND_MSK cpu_to_le32(1 << 13)
/* rx response to host with 8-byte TSF
* (according to ON_AIR deassertion) */
-#define RXON_FLG_TSF2HOST_MSK __constant_cpu_to_le32(1 << 15)
+#define RXON_FLG_TSF2HOST_MSK cpu_to_le32(1 << 15)
/* HT flags */
#define RXON_FLG_CTRL_CHANNEL_LOC_POS (22)
-#define RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK __constant_cpu_to_le32(0x1 << 22)
+#define RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK cpu_to_le32(0x1 << 22)
#define RXON_FLG_HT_OPERATING_MODE_POS (23)
-#define RXON_FLG_HT_PROT_MSK __constant_cpu_to_le32(0x1 << 23)
-#define RXON_FLG_FAT_PROT_MSK __constant_cpu_to_le32(0x2 << 23)
+#define RXON_FLG_HT_PROT_MSK cpu_to_le32(0x1 << 23)
+#define RXON_FLG_FAT_PROT_MSK cpu_to_le32(0x2 << 23)
#define RXON_FLG_CHANNEL_MODE_POS (25)
-#define RXON_FLG_CHANNEL_MODE_MSK __constant_cpu_to_le32(0x3 << 25)
-#define RXON_FLG_CHANNEL_MODE_PURE_40_MSK __constant_cpu_to_le32(0x1 << 25)
-#define RXON_FLG_CHANNEL_MODE_MIXED_MSK __constant_cpu_to_le32(0x2 << 25)
+#define RXON_FLG_CHANNEL_MODE_MSK cpu_to_le32(0x3 << 25)
+#define RXON_FLG_CHANNEL_MODE_PURE_40_MSK cpu_to_le32(0x1 << 25)
+#define RXON_FLG_CHANNEL_MODE_MIXED_MSK cpu_to_le32(0x2 << 25)
/* CTS to self (if spec allows) flag */
-#define RXON_FLG_SELF_CTS_EN __constant_cpu_to_le32(0x1<<30)
+#define RXON_FLG_SELF_CTS_EN cpu_to_le32(0x1<<30)
/* rx_config filter flags */
/* accept all data frames */
-#define RXON_FILTER_PROMISC_MSK __constant_cpu_to_le32(1 << 0)
+#define RXON_FILTER_PROMISC_MSK cpu_to_le32(1 << 0)
/* pass control & management to host */
-#define RXON_FILTER_CTL2HOST_MSK __constant_cpu_to_le32(1 << 1)
+#define RXON_FILTER_CTL2HOST_MSK cpu_to_le32(1 << 1)
/* accept multi-cast */
-#define RXON_FILTER_ACCEPT_GRP_MSK __constant_cpu_to_le32(1 << 2)
+#define RXON_FILTER_ACCEPT_GRP_MSK cpu_to_le32(1 << 2)
/* don't decrypt uni-cast frames */
-#define RXON_FILTER_DIS_DECRYPT_MSK __constant_cpu_to_le32(1 << 3)
+#define RXON_FILTER_DIS_DECRYPT_MSK cpu_to_le32(1 << 3)
/* don't decrypt multi-cast frames */
-#define RXON_FILTER_DIS_GRP_DECRYPT_MSK __constant_cpu_to_le32(1 << 4)
+#define RXON_FILTER_DIS_GRP_DECRYPT_MSK cpu_to_le32(1 << 4)
/* STA is associated */
-#define RXON_FILTER_ASSOC_MSK __constant_cpu_to_le32(1 << 5)
+#define RXON_FILTER_ASSOC_MSK cpu_to_le32(1 << 5)
/* transfer to host non bssid beacons in associated state */
-#define RXON_FILTER_BCON_AWARE_MSK __constant_cpu_to_le32(1 << 6)
+#define RXON_FILTER_BCON_AWARE_MSK cpu_to_le32(1 << 6)
/**
* REPLY_RXON = 0x10 (command, has simple generic response)
@@ -620,7 +631,7 @@ struct iwl4965_rxon_cmd {
u8 ofdm_ht_dual_stream_basic_rates;
} __attribute__ ((packed));
-/* 5000 HW just extend this cmmand */
+/* 5000 HW just extend this command */
struct iwl_rxon_cmd {
u8 node_addr[6];
__le16 reserved1;
@@ -679,8 +690,8 @@ struct iwl4965_rxon_assoc_cmd {
/*
* REPLY_RXON_TIMING = 0x14 (command, has simple generic response)
*/
-struct iwl4965_rxon_time_cmd {
- union tsf timestamp;
+struct iwl_rxon_time_cmd {
+ __le64 timestamp;
__le16 beacon_interval;
__le16 atim_window;
__le32 beacon_init_val;
@@ -691,7 +702,7 @@ struct iwl4965_rxon_time_cmd {
/*
* REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response)
*/
-struct iwl4965_channel_switch_cmd {
+struct iwl_channel_switch_cmd {
u8 band;
u8 expect_beacon;
__le16 channel;
@@ -704,7 +715,7 @@ struct iwl4965_channel_switch_cmd {
/*
* CHANNEL_SWITCH_NOTIFICATION = 0x73 (notification only, not a command)
*/
-struct iwl4965_csa_notification {
+struct iwl_csa_notification {
__le16 band;
__le16 channel;
__le32 status; /* 0 - OK, 1 - fail */
@@ -741,9 +752,9 @@ struct iwl_ac_qos {
} __attribute__ ((packed));
/* QoS flags defines */
-#define QOS_PARAM_FLG_UPDATE_EDCA_MSK __constant_cpu_to_le32(0x01)
-#define QOS_PARAM_FLG_TGN_MSK __constant_cpu_to_le32(0x02)
-#define QOS_PARAM_FLG_TXOP_TYPE_MSK __constant_cpu_to_le32(0x10)
+#define QOS_PARAM_FLG_UPDATE_EDCA_MSK cpu_to_le32(0x01)
+#define QOS_PARAM_FLG_TGN_MSK cpu_to_le32(0x02)
+#define QOS_PARAM_FLG_TXOP_TYPE_MSK cpu_to_le32(0x10)
/* Number of Access Categories (AC) (EDCA), queues 0..3 */
#define AC_NUM 4
@@ -780,34 +791,34 @@ struct iwl_qosparam_cmd {
#define IWL_STATION_COUNT 32 /* MAX(3945,4965)*/
#define IWL_INVALID_STATION 255
-#define STA_FLG_PWR_SAVE_MSK __constant_cpu_to_le32(1 << 8);
-#define STA_FLG_RTS_MIMO_PROT_MSK __constant_cpu_to_le32(1 << 17)
-#define STA_FLG_AGG_MPDU_8US_MSK __constant_cpu_to_le32(1 << 18)
+#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8);
+#define STA_FLG_RTS_MIMO_PROT_MSK cpu_to_le32(1 << 17)
+#define STA_FLG_AGG_MPDU_8US_MSK cpu_to_le32(1 << 18)
#define STA_FLG_MAX_AGG_SIZE_POS (19)
-#define STA_FLG_MAX_AGG_SIZE_MSK __constant_cpu_to_le32(3 << 19)
-#define STA_FLG_FAT_EN_MSK __constant_cpu_to_le32(1 << 21)
-#define STA_FLG_MIMO_DIS_MSK __constant_cpu_to_le32(1 << 22)
+#define STA_FLG_MAX_AGG_SIZE_MSK cpu_to_le32(3 << 19)
+#define STA_FLG_FAT_EN_MSK cpu_to_le32(1 << 21)
+#define STA_FLG_MIMO_DIS_MSK cpu_to_le32(1 << 22)
#define STA_FLG_AGG_MPDU_DENSITY_POS (23)
-#define STA_FLG_AGG_MPDU_DENSITY_MSK __constant_cpu_to_le32(7 << 23)
+#define STA_FLG_AGG_MPDU_DENSITY_MSK cpu_to_le32(7 << 23)
/* Use in mode field. 1: modify existing entry, 0: add new station entry */
#define STA_CONTROL_MODIFY_MSK 0x01
/* key flags __le16*/
-#define STA_KEY_FLG_ENCRYPT_MSK __constant_cpu_to_le16(0x0007)
-#define STA_KEY_FLG_NO_ENC __constant_cpu_to_le16(0x0000)
-#define STA_KEY_FLG_WEP __constant_cpu_to_le16(0x0001)
-#define STA_KEY_FLG_CCMP __constant_cpu_to_le16(0x0002)
-#define STA_KEY_FLG_TKIP __constant_cpu_to_le16(0x0003)
+#define STA_KEY_FLG_ENCRYPT_MSK cpu_to_le16(0x0007)
+#define STA_KEY_FLG_NO_ENC cpu_to_le16(0x0000)
+#define STA_KEY_FLG_WEP cpu_to_le16(0x0001)
+#define STA_KEY_FLG_CCMP cpu_to_le16(0x0002)
+#define STA_KEY_FLG_TKIP cpu_to_le16(0x0003)
#define STA_KEY_FLG_KEYID_POS 8
-#define STA_KEY_FLG_INVALID __constant_cpu_to_le16(0x0800)
+#define STA_KEY_FLG_INVALID cpu_to_le16(0x0800)
/* wep key is either from global key (0) or from station info array (1) */
-#define STA_KEY_FLG_MAP_KEY_MSK __constant_cpu_to_le16(0x0008)
+#define STA_KEY_FLG_MAP_KEY_MSK cpu_to_le16(0x0008)
/* wep key in STA: 5-bytes (0) or 13-bytes (1) */
-#define STA_KEY_FLG_KEY_SIZE_MSK __constant_cpu_to_le16(0x1000)
-#define STA_KEY_MULTICAST_MSK __constant_cpu_to_le16(0x4000)
+#define STA_KEY_FLG_KEY_SIZE_MSK cpu_to_le16(0x1000)
+#define STA_KEY_MULTICAST_MSK cpu_to_le16(0x4000)
#define STA_KEY_MAX_NUM 8
/* Flags indicate whether to modify vs. don't change various station params */
@@ -1013,33 +1024,14 @@ struct iwl_wep_cmd {
*
*****************************************************************************/
-struct iwl4965_rx_frame_stats {
- u8 phy_count;
- u8 id;
- u8 rssi;
- u8 agc;
- __le16 sig_avg;
- __le16 noise_diff;
- u8 payload[0];
-} __attribute__ ((packed));
-
-struct iwl4965_rx_frame_hdr {
- __le16 channel;
- __le16 phy_flags;
- u8 reserved1;
- u8 rate;
- __le16 len;
- u8 payload[0];
-} __attribute__ ((packed));
-
-#define RX_RES_STATUS_NO_CRC32_ERROR __constant_cpu_to_le32(1 << 0)
-#define RX_RES_STATUS_NO_RXE_OVERFLOW __constant_cpu_to_le32(1 << 1)
+#define RX_RES_STATUS_NO_CRC32_ERROR cpu_to_le32(1 << 0)
+#define RX_RES_STATUS_NO_RXE_OVERFLOW cpu_to_le32(1 << 1)
-#define RX_RES_PHY_FLAGS_BAND_24_MSK __constant_cpu_to_le16(1 << 0)
-#define RX_RES_PHY_FLAGS_MOD_CCK_MSK __constant_cpu_to_le16(1 << 1)
-#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK __constant_cpu_to_le16(1 << 2)
-#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK __constant_cpu_to_le16(1 << 3)
-#define RX_RES_PHY_FLAGS_ANTENNA_MSK __constant_cpu_to_le16(0xf0)
+#define RX_RES_PHY_FLAGS_BAND_24_MSK cpu_to_le16(1 << 0)
+#define RX_RES_PHY_FLAGS_MOD_CCK_MSK cpu_to_le16(1 << 1)
+#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK cpu_to_le16(1 << 2)
+#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK cpu_to_le16(1 << 3)
+#define RX_RES_PHY_FLAGS_ANTENNA_MSK cpu_to_le16(0xf0)
#define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8)
#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8)
@@ -1062,26 +1054,6 @@ struct iwl4965_rx_frame_hdr {
#define RX_MPDU_RES_STATUS_TTAK_OK (1 << 7)
#define RX_MPDU_RES_STATUS_DEC_DONE_MSK (0x800)
-struct iwl4965_rx_frame_end {
- __le32 status;
- __le64 timestamp;
- __le32 beacon_timestamp;
-} __attribute__ ((packed));
-
-/*
- * REPLY_3945_RX = 0x1b (response only, not a command)
- *
- * NOTE: DO NOT dereference from casts to this structure
- * It is provided only for calculating minimum data set size.
- * The actual offsets of the hdr and end are dynamic based on
- * stats.phy_count
- */
-struct iwl4965_rx_frame {
- struct iwl4965_rx_frame_stats stats;
- struct iwl4965_rx_frame_hdr hdr;
- struct iwl4965_rx_frame_end end;
-} __attribute__ ((packed));
-
/* Fixed (non-configurable) rx data from phy */
#define IWL49_RX_RES_PHY_CNT 14
@@ -1111,7 +1083,7 @@ struct iwl4965_rx_non_cfg_phy {
#define IWL50_OFDM_RSSI_C_BIT_POS 0
struct iwl5000_non_cfg_phy {
- __le32 non_cfg_phy[IWL50_RX_RES_PHY_CNT]; /* upto 8 phy entries */
+ __le32 non_cfg_phy[IWL50_RX_RES_PHY_CNT]; /* up to 8 phy entries */
} __attribute__ ((packed));
@@ -1167,24 +1139,24 @@ struct iwl4965_rx_mpdu_res_start {
/* REPLY_TX Tx flags field */
-/* 1: Use RTS/CTS protocol or CTS-to-self if spec alows it
+/* 1: Use RTS/CTS protocol or CTS-to-self if spec allows it
* before this frame. if CTS-to-self required check
* RXON_FLG_SELF_CTS_EN status. */
-#define TX_CMD_FLG_RTS_CTS_MSK __constant_cpu_to_le32(1 << 0)
+#define TX_CMD_FLG_RTS_CTS_MSK cpu_to_le32(1 << 0)
/* 1: Use Request-To-Send protocol before this frame.
* Mutually exclusive vs. TX_CMD_FLG_CTS_MSK. */
-#define TX_CMD_FLG_RTS_MSK __constant_cpu_to_le32(1 << 1)
+#define TX_CMD_FLG_RTS_MSK cpu_to_le32(1 << 1)
/* 1: Transmit Clear-To-Send to self before this frame.
* Driver should set this for AUTH/DEAUTH/ASSOC-REQ/REASSOC mgmnt frames.
* Mutually exclusive vs. TX_CMD_FLG_RTS_MSK. */
-#define TX_CMD_FLG_CTS_MSK __constant_cpu_to_le32(1 << 2)
+#define TX_CMD_FLG_CTS_MSK cpu_to_le32(1 << 2)
/* 1: Expect ACK from receiving station
* 0: Don't expect ACK (MAC header's duration field s/b 0)
* Set this for unicast frames, but not broadcast/multicast. */
-#define TX_CMD_FLG_ACK_MSK __constant_cpu_to_le32(1 << 3)
+#define TX_CMD_FLG_ACK_MSK cpu_to_le32(1 << 3)
/* For 4965:
* 1: Use rate scale table (see REPLY_TX_LINK_QUALITY_CMD).
@@ -1192,40 +1164,40 @@ struct iwl4965_rx_mpdu_res_start {
* uCode walks through table for additional Tx attempts.
* 0: Use Tx rate/MCS from Tx command's rate_n_flags field.
* This rate will be used for all Tx attempts; it will not be scaled. */
-#define TX_CMD_FLG_STA_RATE_MSK __constant_cpu_to_le32(1 << 4)
+#define TX_CMD_FLG_STA_RATE_MSK cpu_to_le32(1 << 4)
/* 1: Expect immediate block-ack.
* Set when Txing a block-ack request frame. Also set TX_CMD_FLG_ACK_MSK. */
-#define TX_CMD_FLG_IMM_BA_RSP_MASK __constant_cpu_to_le32(1 << 6)
+#define TX_CMD_FLG_IMM_BA_RSP_MASK cpu_to_le32(1 << 6)
/* 1: Frame requires full Tx-Op protection.
* Set this if either RTS or CTS Tx Flag gets set. */
-#define TX_CMD_FLG_FULL_TXOP_PROT_MSK __constant_cpu_to_le32(1 << 7)
+#define TX_CMD_FLG_FULL_TXOP_PROT_MSK cpu_to_le32(1 << 7)
/* Tx antenna selection field; used only for 3945, reserved (0) for 4965.
* Set field to "0" to allow 3945 uCode to select antenna (normal usage). */
-#define TX_CMD_FLG_ANT_SEL_MSK __constant_cpu_to_le32(0xf00)
-#define TX_CMD_FLG_ANT_A_MSK __constant_cpu_to_le32(1 << 8)
-#define TX_CMD_FLG_ANT_B_MSK __constant_cpu_to_le32(1 << 9)
+#define TX_CMD_FLG_ANT_SEL_MSK cpu_to_le32(0xf00)
+#define TX_CMD_FLG_ANT_A_MSK cpu_to_le32(1 << 8)
+#define TX_CMD_FLG_ANT_B_MSK cpu_to_le32(1 << 9)
/* 1: Ignore Bluetooth priority for this frame.
* 0: Delay Tx until Bluetooth device is done (normal usage). */
-#define TX_CMD_FLG_BT_DIS_MSK __constant_cpu_to_le32(1 << 12)
+#define TX_CMD_FLG_BT_DIS_MSK cpu_to_le32(1 << 12)
/* 1: uCode overrides sequence control field in MAC header.
* 0: Driver provides sequence control field in MAC header.
* Set this for management frames, non-QOS data frames, non-unicast frames,
* and also in Tx command embedded in REPLY_SCAN_CMD for active scans. */
-#define TX_CMD_FLG_SEQ_CTL_MSK __constant_cpu_to_le32(1 << 13)
+#define TX_CMD_FLG_SEQ_CTL_MSK cpu_to_le32(1 << 13)
/* 1: This frame is non-last MPDU; more fragments are coming.
* 0: Last fragment, or not using fragmentation. */
-#define TX_CMD_FLG_MORE_FRAG_MSK __constant_cpu_to_le32(1 << 14)
+#define TX_CMD_FLG_MORE_FRAG_MSK cpu_to_le32(1 << 14)
/* 1: uCode calculates and inserts Timestamp Function (TSF) in outgoing frame.
* 0: No TSF required in outgoing frame.
* Set this for transmitting beacons and probe responses. */
-#define TX_CMD_FLG_TSF_MSK __constant_cpu_to_le32(1 << 16)
+#define TX_CMD_FLG_TSF_MSK cpu_to_le32(1 << 16)
/* 1: Driver inserted 2 bytes pad after the MAC header, for (required) dword
* alignment of frame's payload data field.
@@ -1233,14 +1205,14 @@ struct iwl4965_rx_mpdu_res_start {
* Set this for MAC headers with 26 or 30 bytes, i.e. those with QOS or ADDR4
* field (but not both). Driver must align frame data (i.e. data following
* MAC header) to DWORD boundary. */
-#define TX_CMD_FLG_MH_PAD_MSK __constant_cpu_to_le32(1 << 20)
+#define TX_CMD_FLG_MH_PAD_MSK cpu_to_le32(1 << 20)
/* accelerate aggregation support
* 0 - no CCMP encryption; 1 - CCMP encryption */
-#define TX_CMD_FLG_AGG_CCMP_MSK __constant_cpu_to_le32(1 << 22)
+#define TX_CMD_FLG_AGG_CCMP_MSK cpu_to_le32(1 << 22)
/* HCCA-AP - disable duration overwriting. */
-#define TX_CMD_FLG_DUR_MSK __constant_cpu_to_le32(1 << 25)
+#define TX_CMD_FLG_DUR_MSK cpu_to_le32(1 << 25)
/*
@@ -1266,7 +1238,7 @@ struct iwl4965_rx_mpdu_res_start {
* Used for managing Tx retries when expecting block-acks.
* Driver should set these fields to 0.
*/
-struct iwl4965_dram_scratch {
+struct iwl_dram_scratch {
u8 try_cnt; /* Tx attempts */
u8 bt_kill_cnt; /* Tx attempts blocked by Bluetooth device */
__le16 reserved;
@@ -1297,9 +1269,9 @@ struct iwl_tx_cmd {
__le32 tx_flags; /* TX_CMD_FLG_* */
- /* 4965's uCode may modify this field of the Tx command (in host DRAM!).
+ /* uCode may modify this field of the Tx command (in host DRAM!).
* Driver must also set dram_lsb_ptr and dram_msb_ptr in this cmd. */
- struct iwl4965_dram_scratch scratch;
+ struct iwl_dram_scratch scratch;
/* Rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is cleared. */
__le32 rate_n_flags; /* RATE_MCS_* */
@@ -1411,21 +1383,21 @@ enum {
};
enum {
- TX_STATUS_MSK = 0x000000ff, /* bits 0:7 */
+ TX_STATUS_MSK = 0x000000ff, /* bits 0:7 */
TX_STATUS_DELAY_MSK = 0x00000040,
TX_STATUS_ABORT_MSK = 0x00000080,
TX_PACKET_MODE_MSK = 0x0000ff00, /* bits 8:15 */
TX_FIFO_NUMBER_MSK = 0x00070000, /* bits 16:18 */
- TX_RESERVED = 0x00780000, /* bits 19:22 */
+ TX_RESERVED = 0x00780000, /* bits 19:22 */
TX_POWER_PA_DETECT_MSK = 0x7f800000, /* bits 23:30 */
TX_ABORT_REQUIRED_MSK = 0x80000000, /* bits 31:31 */
};
-static inline int iwl_is_tx_success(u32 status)
+static inline bool iwl_is_tx_success(u32 status)
{
status &= TX_STATUS_MSK;
- return (status == TX_STATUS_SUCCESS)
- || (status == TX_STATUS_DIRECT_DONE);
+ return (status == TX_STATUS_SUCCESS) ||
+ (status == TX_STATUS_DIRECT_DONE);
}
@@ -1450,10 +1422,9 @@ enum {
AGG_TX_STATE_DELAY_TX_MSK = 0x400
};
-#define AGG_TX_STATE_LAST_SENT_MSK \
-(AGG_TX_STATE_LAST_SENT_TTL_MSK | \
- AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK | \
- AGG_TX_STATE_LAST_SENT_BT_KILL_MSK)
+#define AGG_TX_STATE_LAST_SENT_MSK (AGG_TX_STATE_LAST_SENT_TTL_MSK | \
+ AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK | \
+ AGG_TX_STATE_LAST_SENT_BT_KILL_MSK)
/* # tx attempts for first frame in aggregation */
#define AGG_TX_STATE_TRY_CNT_POS 12
@@ -1526,6 +1497,28 @@ struct iwl4965_tx_resp {
} u;
} __attribute__ ((packed));
+/*
+ * definitions for initial rate index field
+ * bits [3:0] initial rate index
+ * bits [6:4] rate table color, used for the initial rate
+ * bit-7 invalid rate indication
+ * i.e. rate was not chosen from rate table
+ * or rate table color was changed during frame retries
+ * refer tlc rate info
+ */
+
+#define IWL50_TX_RES_INIT_RATE_INDEX_POS 0
+#define IWL50_TX_RES_INIT_RATE_INDEX_MSK 0x0f
+#define IWL50_TX_RES_RATE_TABLE_COLOR_POS 4
+#define IWL50_TX_RES_RATE_TABLE_COLOR_MSK 0x70
+#define IWL50_TX_RES_INV_RATE_INDEX_MSK 0x80
+
+/* refer to ra_tid */
+#define IWL50_TX_RES_TID_POS 0
+#define IWL50_TX_RES_TID_MSK 0x0f
+#define IWL50_TX_RES_RA_POS 4
+#define IWL50_TX_RES_RA_MSK 0xf0
+
struct iwl5000_tx_resp {
u8 frame_count; /* 1 no aggregation, >1 aggregation */
u8 bt_kill_count; /* # blocked by bluetooth (unused for agg) */
@@ -1540,14 +1533,17 @@ struct iwl5000_tx_resp {
* For agg: RTS + CTS + aggregation tx time + block-ack time. */
__le16 wireless_media_time; /* uSecs */
- __le16 reserved;
- __le32 pa_power1; /* RF power amplifier measurement (not used) */
- __le32 pa_power2;
+ u8 pa_status; /* RF power amplifier measurement (not used) */
+ u8 pa_integ_res_a[3];
+ u8 pa_integ_res_b[3];
+ u8 pa_integ_res_C[3];
__le32 tfd_info;
__le16 seq_ctl;
__le16 byte_cnt;
- __le32 tlc_info;
+ u8 tlc_info;
+ u8 ra_tid; /* tid (0:3), sta_id (4:7) */
+ __le16 frame_ctrl;
/*
* For non-agg: frame status TX_STATUS_*
* For agg: status of 1st frame, AGG_TX_STATE_*; other frame status
@@ -1742,7 +1738,7 @@ struct iwl_link_qual_agg_params {
* match the modulation characteristics of the history set.
*
* When using block-ack (aggregation), all frames are transmitted at the same
- * rate, since there is no per-attempt acknowledgement from the destination
+ * rate, since there is no per-attempt acknowledgment from the destination
* station. The Tx response struct iwl_tx_resp indicates the Tx rate in
* rate_n_flags field. After receiving a block-ack, the driver can update
* history for the entire block all at once.
@@ -1881,9 +1877,9 @@ struct iwl_link_quality_cmd {
*
* 3945 and 4965 support hardware handshake with Bluetooth device on
* same platform. Bluetooth device alerts wireless device when it will Tx;
- * wireless device can delay or kill its own Tx to accomodate.
+ * wireless device can delay or kill its own Tx to accommodate.
*/
-struct iwl4965_bt_cmd {
+struct iwl_bt_cmd {
u8 flags;
u8 lead_time;
u8 max_kill;
@@ -1909,18 +1905,18 @@ struct iwl4965_bt_cmd {
RXON_FILTER_ASSOC_MSK | \
RXON_FILTER_BCON_AWARE_MSK)
-struct iwl4965_measure_channel {
+struct iwl_measure_channel {
__le32 duration; /* measurement duration in extended beacon
* format */
u8 channel; /* channel to measure */
- u8 type; /* see enum iwl4965_measure_type */
+ u8 type; /* see enum iwl_measure_type */
__le16 reserved;
} __attribute__ ((packed));
/*
* REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (command)
*/
-struct iwl4965_spectrum_cmd {
+struct iwl_spectrum_cmd {
__le16 len; /* number of bytes starting from token */
u8 token; /* token id */
u8 id; /* measurement id -- 0 or 1 */
@@ -1933,13 +1929,13 @@ struct iwl4965_spectrum_cmd {
__le32 filter_flags; /* rxon filter flags */
__le16 channel_count; /* minimum 1, maximum 10 */
__le16 reserved3;
- struct iwl4965_measure_channel channels[10];
+ struct iwl_measure_channel channels[10];
} __attribute__ ((packed));
/*
* REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (response)
*/
-struct iwl4965_spectrum_resp {
+struct iwl_spectrum_resp {
u8 token;
u8 id; /* id of the prior command replaced, or 0xff */
__le16 status; /* 0 - command will be handled
@@ -1947,12 +1943,12 @@ struct iwl4965_spectrum_resp {
* measurement) */
} __attribute__ ((packed));
-enum iwl4965_measurement_state {
+enum iwl_measurement_state {
IWL_MEASUREMENT_START = 0,
IWL_MEASUREMENT_STOP = 1,
};
-enum iwl4965_measurement_status {
+enum iwl_measurement_status {
IWL_MEASUREMENT_OK = 0,
IWL_MEASUREMENT_CONCURRENT = 1,
IWL_MEASUREMENT_CSA_CONFLICT = 2,
@@ -1965,18 +1961,18 @@ enum iwl4965_measurement_status {
#define NUM_ELEMENTS_IN_HISTOGRAM 8
-struct iwl4965_measurement_histogram {
+struct iwl_measurement_histogram {
__le32 ofdm[NUM_ELEMENTS_IN_HISTOGRAM]; /* in 0.8usec counts */
__le32 cck[NUM_ELEMENTS_IN_HISTOGRAM]; /* in 1usec counts */
} __attribute__ ((packed));
/* clear channel availability counters */
-struct iwl4965_measurement_cca_counters {
+struct iwl_measurement_cca_counters {
__le32 ofdm;
__le32 cck;
} __attribute__ ((packed));
-enum iwl4965_measure_type {
+enum iwl_measure_type {
IWL_MEASURE_BASIC = (1 << 0),
IWL_MEASURE_CHANNEL_LOAD = (1 << 1),
IWL_MEASURE_HISTOGRAM_RPI = (1 << 2),
@@ -1989,7 +1985,7 @@ enum iwl4965_measure_type {
/*
* SPECTRUM_MEASURE_NOTIFICATION = 0x75 (notification only, not a command)
*/
-struct iwl4965_spectrum_notification {
+struct iwl_spectrum_notification {
u8 id; /* measurement id -- 0 or 1 */
u8 token;
u8 channel_index; /* index in measurement channel list */
@@ -1997,7 +1993,7 @@ struct iwl4965_spectrum_notification {
__le32 start_time; /* lower 32-bits of TSF */
u8 band; /* 0 - 5.2GHz, 1 - 2.4GHz */
u8 channel;
- u8 type; /* see enum iwl4965_measurement_type */
+ u8 type; /* see enum iwl_measurement_type */
u8 reserved1;
/* NOTE: cca_ofdm, cca_cck, basic_type, and histogram are only only
* valid if applicable for measurement type requested. */
@@ -2007,9 +2003,9 @@ struct iwl4965_spectrum_notification {
u8 basic_type; /* 0 - bss, 1 - ofdm preamble, 2 -
* unidentified */
u8 reserved2[3];
- struct iwl4965_measurement_histogram histogram;
+ struct iwl_measurement_histogram histogram;
__le32 stop_time; /* lower 32-bits of TSF */
- __le32 status; /* see iwl4965_measurement_status */
+ __le32 status; /* see iwl_measurement_status */
} __attribute__ ((packed));
/******************************************************************************
@@ -2043,15 +2039,15 @@ struct iwl4965_spectrum_notification {
* '11' Illegal set
*
* NOTE: if sleep_interval[SLEEP_INTRVL_TABLE_SIZE-1] > DTIM period then
- * ucode assume sleep over DTIM is allowed and we don't need to wakeup
+ * ucode assume sleep over DTIM is allowed and we don't need to wake up
* for every DTIM.
*/
#define IWL_POWER_VEC_SIZE 5
-#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK __constant_cpu_to_le16(1 << 0)
-#define IWL_POWER_SLEEP_OVER_DTIM_MSK __constant_cpu_to_le16(1 << 2)
-#define IWL_POWER_PCI_PM_MSK __constant_cpu_to_le16(1 << 3)
-#define IWL_POWER_FAST_PD __constant_cpu_to_le16(1 << 4)
+#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK cpu_to_le16(1 << 0)
+#define IWL_POWER_SLEEP_OVER_DTIM_MSK cpu_to_le16(1 << 2)
+#define IWL_POWER_PCI_PM_MSK cpu_to_le16(1 << 3)
+#define IWL_POWER_FAST_PD cpu_to_le16(1 << 4)
struct iwl_powertable_cmd {
__le16 flags;
@@ -2067,7 +2063,7 @@ struct iwl_powertable_cmd {
* PM_SLEEP_NOTIFICATION = 0x7A (notification only, not a command)
* 3945 and 4965 identical.
*/
-struct iwl4965_sleep_notification {
+struct iwl_sleep_notification {
u8 pm_sleep_mode;
u8 pm_wakeup_src;
__le16 reserved;
@@ -2097,14 +2093,14 @@ enum {
#define CARD_STATE_CMD_DISABLE 0x00 /* Put card to sleep */
#define CARD_STATE_CMD_ENABLE 0x01 /* Wake up card */
#define CARD_STATE_CMD_HALT 0x02 /* Power down permanently */
-struct iwl4965_card_state_cmd {
+struct iwl_card_state_cmd {
__le32 status; /* CARD_STATE_CMD_* request new power state */
} __attribute__ ((packed));
/*
* CARD_STATE_NOTIFICATION = 0xa1 (notification only, not a command)
*/
-struct iwl4965_card_state_notif {
+struct iwl_card_state_notif {
__le32 flags;
} __attribute__ ((packed));
@@ -2125,8 +2121,8 @@ struct iwl_ct_kill_config {
*
*****************************************************************************/
-#define SCAN_CHANNEL_TYPE_PASSIVE __constant_cpu_to_le32(0)
-#define SCAN_CHANNEL_TYPE_ACTIVE __constant_cpu_to_le32(1)
+#define SCAN_CHANNEL_TYPE_PASSIVE cpu_to_le32(0)
+#define SCAN_CHANNEL_TYPE_ACTIVE cpu_to_le32(1)
/**
* struct iwl_scan_channel - entry in REPLY_SCAN_CMD channel table
@@ -2167,7 +2163,7 @@ struct iwl_scan_channel {
* struct iwl_ssid_ie - directed scan network information element
*
* Up to 4 of these may appear in REPLY_SCAN_CMD, selected by "type" field
- * in struct iwl4965_scan_channel; each channel may select different ssids from
+ * in struct iwl_scan_channel; each channel may select different ssids from
* among the 4 entries. SSID IEs get transmitted in reverse order of entry.
*/
struct iwl_ssid_ie {
@@ -2177,8 +2173,8 @@ struct iwl_ssid_ie {
} __attribute__ ((packed));
#define PROBE_OPTION_MAX 0x14
-#define TX_CMD_LIFE_TIME_INFINITE __constant_cpu_to_le32(0xFFFFFFFF)
-#define IWL_GOOD_CRC_TH __constant_cpu_to_le16(1)
+#define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF)
+#define IWL_GOOD_CRC_TH cpu_to_le16(1)
#define IWL_MAX_SCAN_SIZE 1024
/*
@@ -2267,7 +2263,7 @@ struct iwl_scan_cmd {
* Number of channels in list is specified by channel_count.
* Each channel in list is of type:
*
- * struct iwl4965_scan_channel channels[0];
+ * struct iwl_scan_channel channels[0];
*
* NOTE: Only one band of channels can be scanned per pass. You
* must not mix 2.4GHz channels and 5.2GHz channels, and you must wait
@@ -2278,7 +2274,7 @@ struct iwl_scan_cmd {
} __attribute__ ((packed));
/* Can abort will notify by complete notification with abort status. */
-#define CAN_ABORT_STATUS __constant_cpu_to_le32(0x1)
+#define CAN_ABORT_STATUS cpu_to_le32(0x1)
/* complete notification statuses */
#define ABORT_STATUS 0x2
@@ -2422,6 +2418,8 @@ struct statistics_rx_ht_phy {
__le32 reserved2;
} __attribute__ ((packed));
+#define INTERFERENCE_DATA_AVAILABLE __constant_cpu_to_le32(1)
+
struct statistics_rx_non_phy {
__le32 bogus_cts; /* CTS received when not expecting CTS */
__le32 bogus_ack; /* ACK received when not expecting ACK */
@@ -2540,8 +2538,8 @@ struct statistics_general {
* STATISTICS_NOTIFICATIONs after received beacons (see below). This flag
* does not affect the response to the REPLY_STATISTICS_CMD 0x9c itself.
*/
-#define IWL_STATS_CONF_CLEAR_STATS __constant_cpu_to_le32(0x1) /* see above */
-#define IWL_STATS_CONF_DISABLE_NOTIF __constant_cpu_to_le32(0x2)/* see above */
+#define IWL_STATS_CONF_CLEAR_STATS cpu_to_le32(0x1) /* see above */
+#define IWL_STATS_CONF_DISABLE_NOTIF cpu_to_le32(0x2)/* see above */
struct iwl_statistics_cmd {
__le32 configuration_flags; /* IWL_STATS_CONF_* */
} __attribute__ ((packed));
@@ -2561,8 +2559,8 @@ struct iwl_statistics_cmd {
* appropriately so that each notification contains statistics for only the
* one channel that has just been scanned.
*/
-#define STATISTICS_REPLY_FLG_BAND_24G_MSK __constant_cpu_to_le32(0x2)
-#define STATISTICS_REPLY_FLG_FAT_MODE_MSK __constant_cpu_to_le32(0x8)
+#define STATISTICS_REPLY_FLG_BAND_24G_MSK cpu_to_le32(0x2)
+#define STATISTICS_REPLY_FLG_FAT_MODE_MSK cpu_to_le32(0x8)
struct iwl_notif_statistics {
__le32 flag;
struct statistics_rx rx;
@@ -2578,7 +2576,7 @@ struct iwl_notif_statistics {
* then this notification will be sent. */
#define CONSECUTIVE_MISSED_BCONS_TH 20
-struct iwl4965_missed_beacon_notif {
+struct iwl_missed_beacon_notif {
__le32 consequtive_missed_beacons;
__le32 total_missed_becons;
__le32 num_expected_beacons;
@@ -2778,8 +2776,8 @@ struct iwl4965_missed_beacon_notif {
#define HD_OFDM_ENERGY_TH_IN_INDEX (10)
/* Control field in struct iwl_sensitivity_cmd */
-#define SENSITIVITY_CMD_CONTROL_DEFAULT_TABLE __constant_cpu_to_le16(0)
-#define SENSITIVITY_CMD_CONTROL_WORK_TABLE __constant_cpu_to_le16(1)
+#define SENSITIVITY_CMD_CONTROL_DEFAULT_TABLE cpu_to_le16(0)
+#define SENSITIVITY_CMD_CONTROL_WORK_TABLE cpu_to_le16(1)
/**
* struct iwl_sensitivity_cmd
@@ -2849,56 +2847,26 @@ struct iwl_sensitivity_cmd {
* 1-0: amount of gain, units of 1.5 dB
*/
-/* "Differential Gain" opcode used in REPLY_PHY_CALIBRATION_CMD. */
-#define PHY_CALIBRATE_DIFF_GAIN_CMD (7)
-
-struct iwl4965_calibration_cmd {
- u8 opCode; /* PHY_CALIBRATE_DIFF_GAIN_CMD (7) */
- u8 flags; /* not used */
- __le16 reserved;
- s8 diff_gain_a; /* see above */
- s8 diff_gain_b;
- s8 diff_gain_c;
- u8 reserved1;
-} __attribute__ ((packed));
-
-/* Phy calibration command for 5000 series */
-
-enum {
- IWL5000_PHY_CALIBRATE_DC_CMD = 8,
- IWL5000_PHY_CALIBRATE_LO_CMD = 9,
- IWL5000_PHY_CALIBRATE_RX_BB_CMD = 10,
- IWL5000_PHY_CALIBRATE_TX_IQ_CMD = 11,
- IWL5000_PHY_CALIBRATE_RX_IQ_CMD = 12,
- IWL5000_PHY_CALIBRATION_NOISE_CMD = 13,
- IWL5000_PHY_CALIBRATE_AGC_TABLE_CMD = 14,
- IWL5000_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15,
- IWL5000_PHY_CALIBRATE_BASE_BAND_CMD = 16,
- IWL5000_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17,
- IWL5000_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD = 18,
- IWL5000_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD = 19,
-};
+/* Phy calibration command for series */
enum {
- CALIBRATION_CFG_CMD = 0x65,
- CALIBRATION_RES_NOTIFICATION = 0x66,
- CALIBRATION_COMPLETE_NOTIFICATION = 0x67
+ IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7,
+ IWL_PHY_CALIBRATE_DC_CMD = 8,
+ IWL_PHY_CALIBRATE_LO_CMD = 9,
+ IWL_PHY_CALIBRATE_RX_BB_CMD = 10,
+ IWL_PHY_CALIBRATE_TX_IQ_CMD = 11,
+ IWL_PHY_CALIBRATE_RX_IQ_CMD = 12,
+ IWL_PHY_CALIBRATION_NOISE_CMD = 13,
+ IWL_PHY_CALIBRATE_AGC_TABLE_CMD = 14,
+ IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15,
+ IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16,
+ IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17,
+ IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD = 18,
+ IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD = 19,
};
-struct iwl_cal_crystal_freq_cmd {
- u8 cap_pin1;
- u8 cap_pin2;
-} __attribute__ ((packed));
-
-struct iwl5000_calibration {
- u8 op_code;
- u8 first_group;
- u8 num_groups;
- u8 all_data_valid;
- struct iwl_cal_crystal_freq_cmd data;
-} __attribute__ ((packed));
-#define IWL_CALIB_INIT_CFG_ALL __constant_cpu_to_le32(0xffffffff)
+#define IWL_CALIB_INIT_CFG_ALL cpu_to_le32(0xffffffff)
struct iwl_calib_cfg_elmnt_s {
__le32 is_enable;
@@ -2914,32 +2882,52 @@ struct iwl_calib_cfg_status_s {
__le32 flags;
} __attribute__ ((packed));
-struct iwl5000_calib_cfg_cmd {
+struct iwl_calib_cfg_cmd {
struct iwl_calib_cfg_status_s ucd_calib_cfg;
struct iwl_calib_cfg_status_s drv_calib_cfg;
__le32 reserved1;
} __attribute__ ((packed));
-struct iwl5000_calib_hdr {
+struct iwl_calib_hdr {
u8 op_code;
u8 first_group;
u8 groups_num;
u8 data_valid;
} __attribute__ ((packed));
-struct iwl5000_calibration_chain_noise_reset_cmd {
- u8 op_code; /* IWL5000_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */
- u8 flags; /* not used */
- __le16 reserved;
+struct iwl_calib_cmd {
+ struct iwl_calib_hdr hdr;
+ u8 data[0];
} __attribute__ ((packed));
-struct iwl5000_calibration_chain_noise_gain_cmd {
- u8 op_code; /* IWL5000_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD */
- u8 flags; /* not used */
- __le16 reserved;
+/* IWL_PHY_CALIBRATE_DIFF_GAIN_CMD (7) */
+struct iwl_calib_diff_gain_cmd {
+ struct iwl_calib_hdr hdr;
+ s8 diff_gain_a; /* see above */
+ s8 diff_gain_b;
+ s8 diff_gain_c;
+ u8 reserved1;
+} __attribute__ ((packed));
+
+struct iwl_calib_xtal_freq_cmd {
+ struct iwl_calib_hdr hdr;
+ u8 cap_pin1;
+ u8 cap_pin2;
+ u8 pad[2];
+} __attribute__ ((packed));
+
+/* IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */
+struct iwl_calib_chain_noise_reset_cmd {
+ struct iwl_calib_hdr hdr;
+ u8 data[0];
+};
+
+/* IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD */
+struct iwl_calib_chain_noise_gain_cmd {
+ struct iwl_calib_hdr hdr;
u8 delta_gain_1;
u8 delta_gain_2;
- __le16 reserved1;
+ u8 pad[2];
} __attribute__ ((packed));
/******************************************************************************
@@ -2999,11 +2987,11 @@ struct iwl_wimax_coex_event_entry {
/* COEX flag masks */
-/* Staion table is valid */
+/* Station table is valid */
#define COEX_FLAGS_STA_TABLE_VALID_MSK (0x1)
-/* UnMask wakeup src at unassociated sleep */
+/* UnMask wake up src at unassociated sleep */
#define COEX_FLAGS_UNASSOC_WA_UNMASK_MSK (0x4)
-/* UnMask wakeup src at associated sleep */
+/* UnMask wake up src at associated sleep */
#define COEX_FLAGS_ASSOC_WA_UNMASK_MSK (0x8)
/* Enable CoEx feature. */
#define COEX_FLAGS_COEX_ENABLE_MSK (0x80)
@@ -3025,26 +3013,22 @@ struct iwl_rx_packet {
struct iwl_cmd_header hdr;
union {
struct iwl_alive_resp alive_frame;
- struct iwl4965_rx_frame rx_frame;
- struct iwl4965_tx_resp tx_resp;
- struct iwl4965_spectrum_notification spectrum_notif;
- struct iwl4965_csa_notification csa_notif;
+ struct iwl_spectrum_notification spectrum_notif;
+ struct iwl_csa_notification csa_notif;
struct iwl_error_resp err_resp;
- struct iwl4965_card_state_notif card_state_notif;
- struct iwl4965_beacon_notif beacon_status;
+ struct iwl_card_state_notif card_state_notif;
struct iwl_add_sta_resp add_sta;
struct iwl_rem_sta_resp rem_sta;
- struct iwl4965_sleep_notification sleep_notif;
- struct iwl4965_spectrum_resp spectrum;
+ struct iwl_sleep_notification sleep_notif;
+ struct iwl_spectrum_resp spectrum;
struct iwl_notif_statistics stats;
struct iwl_compressed_ba_resp compressed_ba;
- struct iwl4965_missed_beacon_notif missed_beacon;
- struct iwl5000_calibration calib;
+ struct iwl_missed_beacon_notif missed_beacon;
__le32 status;
u8 raw[0];
} u;
} __attribute__ ((packed));
-#define IWL_RX_FRAME_SIZE (4 + sizeof(struct iwl4965_rx_frame))
+int iwl_agn_check_rxon_cmd(struct iwl_rxon_cmd *rxon);
-#endif /* __iwl4965_commands_h__ */
+#endif /* __iwl_commands_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 01a845851338..73d7973707eb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -22,7 +22,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
- * Tomas Winkler <tomas.winkler@intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
@@ -30,19 +30,19 @@
#include <linux/module.h>
#include <net/mac80211.h>
-struct iwl_priv; /* FIXME: remove */
-#include "iwl-debug.h"
#include "iwl-eeprom.h"
#include "iwl-dev.h" /* FIXME: remove */
+#include "iwl-debug.h"
#include "iwl-core.h"
#include "iwl-io.h"
#include "iwl-rfkill.h"
#include "iwl-power.h"
+#include "iwl-sta.h"
MODULE_DESCRIPTION("iwl core");
MODULE_VERSION(IWLWIFI_VERSION);
-MODULE_AUTHOR(DRV_COPYRIGHT);
+MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");
#define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \
@@ -88,26 +88,27 @@ EXPORT_SYMBOL(iwl_rates);
* translate ucode response to mac80211 tx status control values
*/
void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
- struct ieee80211_tx_info *control)
+ struct ieee80211_tx_info *info)
{
int rate_index;
+ struct ieee80211_tx_rate *r = &info->control.rates[0];
- control->antenna_sel_tx =
+ info->antenna_sel_tx =
((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS);
if (rate_n_flags & RATE_MCS_HT_MSK)
- control->flags |= IEEE80211_TX_CTL_OFDM_HT;
+ r->flags |= IEEE80211_TX_RC_MCS;
if (rate_n_flags & RATE_MCS_GF_MSK)
- control->flags |= IEEE80211_TX_CTL_GREEN_FIELD;
+ r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
if (rate_n_flags & RATE_MCS_FAT_MSK)
- control->flags |= IEEE80211_TX_CTL_40_MHZ_WIDTH;
+ r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
if (rate_n_flags & RATE_MCS_DUP_MSK)
- control->flags |= IEEE80211_TX_CTL_DUP_DATA;
+ r->flags |= IEEE80211_TX_RC_DUP_DATA;
if (rate_n_flags & RATE_MCS_SGI_MSK)
- control->flags |= IEEE80211_TX_CTL_SHORT_GI;
+ r->flags |= IEEE80211_TX_RC_SHORT_GI;
rate_index = iwl_hwrate_to_plcp_idx(rate_n_flags);
- if (control->band == IEEE80211_BAND_5GHZ)
+ if (info->band == IEEE80211_BAND_5GHZ)
rate_index -= IWL_FIRST_OFDM_RATE;
- control->tx_rate_idx = rate_index;
+ r->idx = rate_index;
}
EXPORT_SYMBOL(iwl_hwrate_to_tx_control);
@@ -119,7 +120,9 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
if (rate_n_flags & RATE_MCS_HT_MSK) {
idx = (rate_n_flags & 0xff);
- if (idx >= IWL_RATE_MIMO2_6M_PLCP)
+ if (idx >= IWL_RATE_MIMO3_6M_PLCP)
+ idx = idx - IWL_RATE_MIMO3_6M_PLCP;
+ else if (idx >= IWL_RATE_MIMO2_6M_PLCP)
idx = idx - IWL_RATE_MIMO2_6M_PLCP;
idx += IWL_FIRST_OFDM_RATE;
@@ -140,7 +143,17 @@ int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
}
EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx);
-
+u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant)
+{
+ int i;
+ u8 ind = ant;
+ for (i = 0; i < RATE_ANT_NUM - 1; i++) {
+ ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0;
+ if (priv->hw_params.valid_tx_ant & BIT(ind))
+ return ind;
+ }
+ return ant;
+}
const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
EXPORT_SYMBOL(iwl_bcast_addr);
@@ -177,52 +190,6 @@ void iwl_hw_detect(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_hw_detect);
-/* Tell nic where to find the "keep warm" buffer */
-int iwl_kw_init(struct iwl_priv *priv)
-{
- unsigned long flags;
- int ret;
-
- spin_lock_irqsave(&priv->lock, flags);
- ret = iwl_grab_nic_access(priv);
- if (ret)
- goto out;
-
- iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG,
- priv->kw.dma_addr >> 4);
- iwl_release_nic_access(priv);
-out:
- spin_unlock_irqrestore(&priv->lock, flags);
- return ret;
-}
-
-int iwl_kw_alloc(struct iwl_priv *priv)
-{
- struct pci_dev *dev = priv->pci_dev;
- struct iwl_kw *kw = &priv->kw;
-
- kw->size = IWL_KW_SIZE;
- kw->v_addr = pci_alloc_consistent(dev, kw->size, &kw->dma_addr);
- if (!kw->v_addr)
- return -ENOMEM;
-
- return 0;
-}
-
-/**
- * iwl_kw_free - Free the "keep warm" buffer
- */
-void iwl_kw_free(struct iwl_priv *priv)
-{
- struct pci_dev *dev = priv->pci_dev;
- struct iwl_kw *kw = &priv->kw;
-
- if (kw->v_addr) {
- pci_free_consistent(dev, kw->size, kw->v_addr, kw->dma_addr);
- memset(kw, 0, sizeof(*kw));
- }
-}
-
int iwl_hw_nic_init(struct iwl_priv *priv)
{
unsigned long flags;
@@ -271,55 +238,30 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_hw_nic_init);
-/**
- * iwl_clear_stations_table - Clear the driver's station table
- *
- * NOTE: This does not clear or otherwise alter the device's station table.
- */
-void iwl_clear_stations_table(struct iwl_priv *priv)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
-
- if (iwl_is_alive(priv) &&
- !test_bit(STATUS_EXIT_PENDING, &priv->status) &&
- iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL))
- IWL_ERROR("Couldn't clear the station table\n");
-
- priv->num_stations = 0;
- memset(priv->stations, 0, sizeof(priv->stations));
-
- /* clean ucode key table bit map */
- priv->ucode_key_table = 0;
-
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-}
-EXPORT_SYMBOL(iwl_clear_stations_table);
-
void iwl_reset_qos(struct iwl_priv *priv)
{
u16 cw_min = 15;
u16 cw_max = 1023;
u8 aifs = 2;
- u8 is_legacy = 0;
+ bool is_legacy = false;
unsigned long flags;
int i;
spin_lock_irqsave(&priv->lock, flags);
- priv->qos_data.qos_active = 0;
+ /* QoS always active in AP and ADHOC mode
+ * In STA mode wait for association
+ */
+ if (priv->iw_mode == NL80211_IFTYPE_ADHOC ||
+ priv->iw_mode == NL80211_IFTYPE_AP)
+ priv->qos_data.qos_active = 1;
+ else
+ priv->qos_data.qos_active = 0;
- if (priv->iw_mode == NL80211_IFTYPE_ADHOC) {
- if (priv->qos_data.qos_enable)
- priv->qos_data.qos_active = 1;
- if (!(priv->active_rate & 0xfff0)) {
- cw_min = 31;
- is_legacy = 1;
- }
- } else if (priv->iw_mode == NL80211_IFTYPE_AP) {
- if (priv->qos_data.qos_enable)
- priv->qos_data.qos_active = 1;
- } else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
+ /* check for legacy mode */
+ if ((priv->iw_mode == NL80211_IFTYPE_ADHOC &&
+ (priv->active_rate & IWL_OFDM_RATES_MASK) == 0) ||
+ (priv->iw_mode == NL80211_IFTYPE_STATION &&
+ (priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK) == 0)) {
cw_min = 31;
is_legacy = 1;
}
@@ -385,10 +327,10 @@ void iwl_reset_qos(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_reset_qos);
-#define MAX_BIT_RATE_40_MHZ 0x96 /* 150 Mbps */
-#define MAX_BIT_RATE_20_MHZ 0x48 /* 72 Mbps */
+#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
+#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
- struct ieee80211_ht_info *ht_info,
+ struct ieee80211_sta_ht_cap *ht_info,
enum ieee80211_band band)
{
u16 max_bit_rate = 0;
@@ -396,45 +338,46 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv,
u8 tx_chains_num = priv->hw_params.tx_chains_num;
ht_info->cap = 0;
- memset(ht_info->supp_mcs_set, 0, 16);
+ memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
- ht_info->ht_supported = 1;
+ ht_info->ht_supported = true;
- ht_info->cap |= (u16)IEEE80211_HT_CAP_GRN_FLD;
- ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_20;
- ht_info->cap |= (u16)(IEEE80211_HT_CAP_SM_PS &
+ ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD;
+ ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
+ ht_info->cap |= (IEEE80211_HT_CAP_SM_PS &
(WLAN_HT_CAP_SM_PS_DISABLED << 2));
max_bit_rate = MAX_BIT_RATE_20_MHZ;
if (priv->hw_params.fat_channel & BIT(band)) {
- ht_info->cap |= (u16)IEEE80211_HT_CAP_SUP_WIDTH;
- ht_info->cap |= (u16)IEEE80211_HT_CAP_SGI_40;
- ht_info->supp_mcs_set[4] = 0x01;
+ ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+ ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
+ ht_info->mcs.rx_mask[4] = 0x01;
max_bit_rate = MAX_BIT_RATE_40_MHZ;
}
if (priv->cfg->mod_params->amsdu_size_8K)
- ht_info->cap |= (u16)IEEE80211_HT_CAP_MAX_AMSDU;
+ ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
- ht_info->supp_mcs_set[0] = 0xFF;
+ ht_info->mcs.rx_mask[0] = 0xFF;
if (rx_chains_num >= 2)
- ht_info->supp_mcs_set[1] = 0xFF;
+ ht_info->mcs.rx_mask[1] = 0xFF;
if (rx_chains_num >= 3)
- ht_info->supp_mcs_set[2] = 0xFF;
+ ht_info->mcs.rx_mask[2] = 0xFF;
/* Highest supported Rx data rate */
max_bit_rate *= rx_chains_num;
- ht_info->supp_mcs_set[10] = (u8)(max_bit_rate & 0x00FF);
- ht_info->supp_mcs_set[11] = (u8)((max_bit_rate & 0xFF00) >> 8);
+ WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK);
+ ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate);
/* Tx MCS capabilities */
- ht_info->supp_mcs_set[12] = IEEE80211_HT_CAP_MCS_TX_DEFINED;
+ ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
if (tx_chains_num != rx_chains_num) {
- ht_info->supp_mcs_set[12] |= IEEE80211_HT_CAP_MCS_TX_RX_DIFF;
- ht_info->supp_mcs_set[12] |= ((tx_chains_num - 1) << 2);
+ ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
+ ht_info->mcs.tx_params |= ((tx_chains_num - 1) <<
+ IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
}
}
@@ -498,7 +441,7 @@ static int iwlcore_init_geos(struct iwl_priv *priv)
sband->n_bitrates = IWL_RATE_COUNT - IWL_FIRST_OFDM_RATE;
if (priv->cfg->sku & IWL_SKU_N)
- iwlcore_init_ht_hw_capab(priv, &sband->ht_info,
+ iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
IEEE80211_BAND_5GHZ);
sband = &priv->bands[IEEE80211_BAND_2GHZ];
@@ -508,7 +451,7 @@ static int iwlcore_init_geos(struct iwl_priv *priv)
sband->n_bitrates = IWL_RATE_COUNT;
if (priv->cfg->sku & IWL_SKU_N)
- iwlcore_init_ht_hw_capab(priv, &sband->ht_info,
+ iwlcore_init_ht_hw_capab(priv, &sband->ht_cap,
IEEE80211_BAND_2GHZ);
priv->ieee_channels = channels;
@@ -598,8 +541,8 @@ static void iwlcore_free_geos(struct iwl_priv *priv)
static bool is_single_rx_stream(struct iwl_priv *priv)
{
return !priv->current_ht_config.is_ht ||
- ((priv->current_ht_config.supp_mcs_set[1] == 0) &&
- (priv->current_ht_config.supp_mcs_set[2] == 0));
+ ((priv->current_ht_config.mcs.rx_mask[1] == 0) &&
+ (priv->current_ht_config.mcs.rx_mask[2] == 0));
}
static u8 iwl_is_channel_extension(struct iwl_priv *priv,
@@ -612,10 +555,10 @@ static u8 iwl_is_channel_extension(struct iwl_priv *priv,
if (!is_channel_valid(ch_info))
return 0;
- if (extension_chan_offset == IEEE80211_HT_IE_CHA_SEC_ABOVE)
+ if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
return !(ch_info->fat_extension_channel &
IEEE80211_CHAN_NO_FAT_ABOVE);
- else if (extension_chan_offset == IEEE80211_HT_IE_CHA_SEC_BELOW)
+ else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
return !(ch_info->fat_extension_channel &
IEEE80211_CHAN_NO_FAT_BELOW);
@@ -623,24 +566,24 @@ static u8 iwl_is_channel_extension(struct iwl_priv *priv,
}
u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
- struct ieee80211_ht_info *sta_ht_inf)
+ struct ieee80211_sta_ht_cap *sta_ht_inf)
{
struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config;
if ((!iwl_ht_conf->is_ht) ||
(iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) ||
- (iwl_ht_conf->extension_chan_offset == IEEE80211_HT_IE_CHA_SEC_NONE))
+ (iwl_ht_conf->extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE))
return 0;
if (sta_ht_inf) {
if ((!sta_ht_inf->ht_supported) ||
- (!(sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH)))
+ (!(sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)))
return 0;
}
return iwl_is_channel_extension(priv, priv->band,
- iwl_ht_conf->control_channel,
- iwl_ht_conf->extension_chan_offset);
+ le16_to_cpu(priv->staging_rxon.channel),
+ iwl_ht_conf->extension_chan_offset);
}
EXPORT_SYMBOL(iwl_is_fat_tx_allowed);
@@ -665,22 +608,15 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK |
RXON_FLG_CHANNEL_MODE_PURE_40_MSK);
- if (le16_to_cpu(rxon->channel) != ht_info->control_channel) {
- IWL_DEBUG_ASSOC("control diff than current %d %d\n",
- le16_to_cpu(rxon->channel),
- ht_info->control_channel);
- return;
- }
-
/* Note: control channel is opposite of extension channel */
switch (ht_info->extension_chan_offset) {
- case IEEE80211_HT_IE_CHA_SEC_ABOVE:
+ case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
break;
- case IEEE80211_HT_IE_CHA_SEC_BELOW:
+ case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
break;
- case IEEE80211_HT_IE_CHA_SEC_NONE:
+ case IEEE80211_HT_PARAM_CHA_SEC_NONE:
default:
rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK;
break;
@@ -694,14 +630,12 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
IWL_DEBUG_ASSOC("supported HT rate 0x%X 0x%X 0x%X "
"rxon flags 0x%X operation mode :0x%X "
- "extension channel offset 0x%x "
- "control chan %d\n",
- ht_info->supp_mcs_set[0],
- ht_info->supp_mcs_set[1],
- ht_info->supp_mcs_set[2],
+ "extension channel offset 0x%x\n",
+ ht_info->mcs.rx_mask[0],
+ ht_info->mcs.rx_mask[1],
+ ht_info->mcs.rx_mask[2],
le32_to_cpu(rxon->flags), ht_info->ht_protection,
- ht_info->extension_chan_offset,
- ht_info->control_channel);
+ ht_info->extension_chan_offset);
return;
}
EXPORT_SYMBOL(iwl_set_rxon_ht);
@@ -745,7 +679,7 @@ static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
break;
case WLAN_HT_CAP_SM_PS_INVALID:
default:
- IWL_ERROR("invalide mimo ps mode %d\n",
+ IWL_ERROR("invalid mimo ps mode %d\n",
priv->current_ht_config.sm_ps);
WARN_ON(1);
idle_cnt = -1;
@@ -871,11 +805,14 @@ int iwl_setup_mac(struct iwl_priv *priv)
/* Tell mac80211 our characteristics */
hw->flags = IEEE80211_HW_SIGNAL_DBM |
- IEEE80211_HW_NOISE_DBM;
+ IEEE80211_HW_NOISE_DBM |
+ IEEE80211_HW_AMPDU_AGGREGATION;
hw->wiphy->interface_modes =
- BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC);
+
+ hw->wiphy->fw_handles_regulatory = true;
+
/* Default value; 4 EDCA QOS priorities */
hw->queues = 4;
/* queues to support 11n aggregation */
@@ -948,16 +885,12 @@ int iwl_init_drv(struct iwl_priv *priv)
priv->iw_mode = NL80211_IFTYPE_STATION;
- priv->use_ant_b_for_management_frame = 1; /* start with ant B */
priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED;
/* Choose which receivers/antennas to use */
iwl_set_rxon_chain(priv);
iwl_init_scan_params(priv);
- if (priv->cfg->mod_params->enable_qos)
- priv->qos_data.qos_enable = 1;
-
iwl_reset_qos(priv);
priv->qos_data.qos_active = 0;
@@ -1025,6 +958,30 @@ void iwl_uninit_drv(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_uninit_drv);
+
+void iwl_disable_interrupts(struct iwl_priv *priv)
+{
+ clear_bit(STATUS_INT_ENABLED, &priv->status);
+
+ /* disable interrupts from uCode/NIC to host */
+ iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+
+ /* acknowledge/clear/reset any interrupts still pending
+ * from uCode or flow handler (Rx/Tx DMA) */
+ iwl_write32(priv, CSR_INT, 0xffffffff);
+ iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
+ IWL_DEBUG_ISR("Disabled interrupts\n");
+}
+EXPORT_SYMBOL(iwl_disable_interrupts);
+
+void iwl_enable_interrupts(struct iwl_priv *priv)
+{
+ IWL_DEBUG_ISR("Enabling interrupts\n");
+ set_bit(STATUS_INT_ENABLED, &priv->status);
+ iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK);
+}
+EXPORT_SYMBOL(iwl_enable_interrupts);
+
int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags)
{
u32 stat_flags = 0;
@@ -1172,24 +1129,47 @@ int iwl_verify_ucode(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_verify_ucode);
+
+static const char *desc_lookup_text[] = {
+ "OK",
+ "FAIL",
+ "BAD_PARAM",
+ "BAD_CHECKSUM",
+ "NMI_INTERRUPT_WDG",
+ "SYSASSERT",
+ "FATAL_ERROR",
+ "BAD_COMMAND",
+ "HW_ERROR_TUNE_LOCK",
+ "HW_ERROR_TEMPERATURE",
+ "ILLEGAL_CHAN_FREQ",
+ "VCC_NOT_STABLE",
+ "FH_ERROR",
+ "NMI_INTERRUPT_HOST",
+ "NMI_INTERRUPT_ACTION_PT",
+ "NMI_INTERRUPT_UNKNOWN",
+ "UCODE_VERSION_MISMATCH",
+ "HW_ERROR_ABS_LOCK",
+ "HW_ERROR_CAL_LOCK_FAIL",
+ "NMI_INTERRUPT_INST_ACTION_PT",
+ "NMI_INTERRUPT_DATA_ACTION_PT",
+ "NMI_TRM_HW_ER",
+ "NMI_INTERRUPT_TRM",
+ "NMI_INTERRUPT_BREAK_POINT"
+ "DEBUG_0",
+ "DEBUG_1",
+ "DEBUG_2",
+ "DEBUG_3",
+ "UNKNOWN"
+};
+
static const char *desc_lookup(int i)
{
- switch (i) {
- case 1:
- return "FAIL";
- case 2:
- return "BAD_PARAM";
- case 3:
- return "BAD_CHECKSUM";
- case 4:
- return "NMI_INTERRUPT";
- case 5:
- return "SYSASSERT";
- case 6:
- return "FATAL_ERROR";
- }
+ int max = ARRAY_SIZE(desc_lookup_text) - 1;
- return "UNKNOWN";
+ if (i < 0 || i > max)
+ i = max;
+
+ return desc_lookup_text[i];
}
#define ERROR_START_OFFSET (1 * sizeof(u32))
@@ -1235,9 +1215,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32));
time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32));
- IWL_ERROR("Desc Time "
+ IWL_ERROR("Desc Time "
"data1 data2 line\n");
- IWL_ERROR("%-13s (#%d) %010u 0x%08X 0x%08X %u\n",
+ IWL_ERROR("%-28s (#%02d) %010u 0x%08X 0x%08X %u\n",
desc_lookup(desc), desc, time, data1, data2, line);
IWL_ERROR("blink1 blink2 ilink1 ilink2\n");
IWL_ERROR("0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
@@ -1377,6 +1357,7 @@ void iwl_rf_kill_ct_config(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_rf_kill_ct_config);
+
/*
* CARD_STATE_CMD
*
@@ -1465,6 +1446,16 @@ int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv)
return 0;
}
+ /* when driver is up while rfkill is on, it wont receive
+ * any CARD_STATE_NOTIFICATION notifications so we have to
+ * restart it in here
+ */
+ if (priv->is_open && !test_bit(STATUS_ALIVE, &priv->status)) {
+ clear_bit(STATUS_RF_KILL_SW, &priv->status);
+ if (!iwl_is_rfkill(priv))
+ queue_work(priv->workqueue, &priv->up);
+ }
+
/* If the driver is already loaded, it will receive
* CARD_STATE_NOTIFICATION notifications and the handler will
* call restart to reload the driver.
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 288b6a800e03..7c3a20a986bb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
- * Tomas Winkler <tomas.winkler@intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@@ -72,6 +72,7 @@ struct iwl_cmd;
#define IWLWIFI_VERSION "1.3.27k"
#define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation"
+#define DRV_AUTHOR "<ilw@linux.intel.com>"
#define IWL_PCI_DEVICE(dev, subdev, cfg) \
.vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \
@@ -100,12 +101,8 @@ struct iwl_hcmd_utils_ops {
};
struct iwl_lib_ops {
- /* set hw dependant perameters */
+ /* set hw dependent parameters */
int (*set_hw_params)(struct iwl_priv *priv);
- /* ucode shared memory */
- int (*alloc_shared_mem)(struct iwl_priv *priv);
- void (*free_shared_mem)(struct iwl_priv *priv);
- int (*shared_mem_rx_idx)(struct iwl_priv *priv);
/* Handling TX */
void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv,
struct iwl_tx_queue *txq,
@@ -157,22 +154,53 @@ struct iwl_ops {
struct iwl_mod_params {
int disable; /* def: 0 = enable radio */
int sw_crypto; /* def: 0 = using hardware encryption */
- int debug; /* def: 0 = minimal debug log messages */
+ u32 debug; /* def: 0 = minimal debug log messages */
int disable_hw_scan; /* def: 0 = use h/w scan */
int num_of_queues; /* def: HW dependent */
int num_of_ampdu_queues;/* def: HW dependent */
- int enable_qos; /* def: 1 = use quality of service */
int disable_11n; /* def: 0 = disable 11n capabilities */
int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */
int antenna; /* def: 0 = both antennas (use diversity) */
int restart_fw; /* def: 1 = restart firmware */
};
+/**
+ * struct iwl_cfg
+ * @fw_name_pre: Firmware filename prefix. The api version and extension
+ * (.ucode) will be added to filename before loading from disk. The
+ * filename is constructed as fw_name_pre<api>.ucode.
+ * @ucode_api_max: Highest version of uCode API supported by driver.
+ * @ucode_api_min: Lowest version of uCode API supported by driver.
+ *
+ * We enable the driver to be backward compatible wrt API version. The
+ * driver specifies which APIs it supports (with @ucode_api_max being the
+ * highest and @ucode_api_min the lowest). Firmware will only be loaded if
+ * it has a supported API version. The firmware's API version will be
+ * stored in @iwl_priv, enabling the driver to make runtime changes based
+ * on firmware version used.
+ *
+ * For example,
+ * if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
+ * Driver interacts with Firmware API version >= 2.
+ * } else {
+ * Driver interacts with Firmware API version 1.
+ * }
+ *
+ * The ideal usage of this infrastructure is to treat a new ucode API
+ * release as a new hardware revision. That is, through utilizing the
+ * iwl_hcmd_utils_ops etc. we accommodate different command structures
+ * and flows between hardware versions (4965/5000) as well as their API
+ * versions.
+ */
struct iwl_cfg {
const char *name;
- const char *fw_name;
+ const char *fw_name_pre;
+ const unsigned int ucode_api_max;
+ const unsigned int ucode_api_min;
unsigned int sku;
int eeprom_size;
+ u16 eeprom_ver;
+ u16 eeprom_calib_ver;
const struct iwl_ops *ops;
const struct iwl_mod_params *mod_params;
};
@@ -184,22 +212,17 @@ struct iwl_cfg {
struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
struct ieee80211_ops *hw_ops);
void iwl_hw_detect(struct iwl_priv *priv);
-void iwl_clear_stations_table(struct iwl_priv *priv);
void iwl_reset_qos(struct iwl_priv *priv);
void iwl_set_rxon_chain(struct iwl_priv *priv);
int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch);
void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info);
u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
- struct ieee80211_ht_info *sta_ht_inf);
+ struct ieee80211_sta_ht_cap *sta_ht_inf);
int iwl_hw_nic_init(struct iwl_priv *priv);
int iwl_setup_mac(struct iwl_priv *priv);
int iwl_set_hw_params(struct iwl_priv *priv);
int iwl_init_drv(struct iwl_priv *priv);
void iwl_uninit_drv(struct iwl_priv *priv);
-/* "keep warm" functions */
-int iwl_kw_init(struct iwl_priv *priv);
-int iwl_kw_alloc(struct iwl_priv *priv);
-void iwl_kw_free(struct iwl_priv *priv);
/*****************************************************
* RX
@@ -212,8 +235,6 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
void iwl_rx_replenish(struct iwl_priv *priv);
int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
-int iwl_rx_agg_start(struct iwl_priv *priv, const u8 *addr, int tid, u16 ssn);
-int iwl_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid);
int iwl_rx_queue_restock(struct iwl_priv *priv);
int iwl_rx_queue_space(const struct iwl_rx_queue *q);
void iwl_rx_allocate(struct iwl_priv *priv);
@@ -237,7 +258,6 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn);
int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid);
int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id);
-
/*****************************************************
* TX power
****************************************************/
@@ -259,6 +279,13 @@ void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
struct ieee80211_tx_info *info);
int iwl_hwrate_to_plcp_idx(u32 rate_n_flags);
+u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx);
+
+static inline u32 iwl_ant_idx_to_flags(u8 ant_idx)
+{
+ return BIT(ant_idx) << RATE_MCS_ANT_POS;
+}
+
static inline u8 iwl_hw_get_rate(__le32 rate_n_flags)
{
return le32_to_cpu(rate_n_flags) & 0xFF;
@@ -289,6 +316,14 @@ int iwl_send_calib_results(struct iwl_priv *priv);
int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len);
void iwl_calib_free_results(struct iwl_priv *priv);
+/*******************************************************************************
+ * Spectrum Measureemtns in iwl-spectrum.c
+ ******************************************************************************/
+#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT
+void iwl_setup_spectrum_handlers(struct iwl_priv *priv);
+#else
+static inline void iwl_setup_spectrum_handlers(struct iwl_priv *priv) {}
+#endif
/*****************************************************
* S e n d i n g H o s t C o m m a n d s *
*****************************************************/
@@ -308,11 +343,18 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
/*****************************************************
+ * PCI *
+ *****************************************************/
+void iwl_disable_interrupts(struct iwl_priv *priv);
+void iwl_enable_interrupts(struct iwl_priv *priv);
+
+/*****************************************************
* Error Handling Debugging
******************************************************/
void iwl_dump_nic_error_log(struct iwl_priv *priv);
void iwl_dump_nic_event_log(struct iwl_priv *priv);
+
/*************** DRIVER STATUS FUNCTIONS *****/
#define STATUS_HCMD_ACTIVE 0 /* host command in progress */
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index 662edf4f8d22..f34ede44ed10 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@@ -60,6 +60,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
+#ifndef __iwl_csr_h__
+#define __iwl_csr_h__
/*=== CSR (control and status registers) ===*/
#define CSR_BASE (0x000)
@@ -214,6 +216,8 @@
/* EEPROM REG */
#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001)
#define CSR_EEPROM_REG_BIT_CMD (0x00000002)
+#define CSR_EEPROM_REG_MSK_ADDR (0x0000FFFC)
+#define CSR_EEPROM_REG_MSK_DATA (0xFFFF0000)
/* EEPROM GP */
#define CSR_EEPROM_GP_VALID_MSK (0x00000006)
@@ -286,4 +290,4 @@
#define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004)
-
+#endif /* !__iwl_csr_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index e548d67f87fd..56c13b458de7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -21,7 +21,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -40,6 +40,13 @@ do { if ((priv->debug_level & (level)) && net_ratelimit()) \
dev_printk(KERN_ERR, &(priv->hw->wiphy->dev), "%c %s " fmt, \
in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0)
+#define iwl_print_hex_dump(priv, level, p, len) \
+do { \
+ if (priv->debug_level & level) \
+ print_hex_dump(KERN_DEBUG, "iwl data: ", \
+ DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \
+} while (0)
+
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct iwl_debugfs {
const char *name;
@@ -53,6 +60,7 @@ struct iwl_debugfs {
struct dentry *file_rx_statistics;
struct dentry *file_tx_statistics;
struct dentry *file_log_event;
+ struct dentry *file_channels;
} dbgfs_data_files;
struct dir_rf_files {
struct dentry *file_disable_sensitivity;
@@ -70,6 +78,9 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv);
#else
#define IWL_DEBUG(level, fmt, args...)
#define IWL_DEBUG_LIMIT(level, fmt, args...)
+static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level,
+ void *p, u32 len)
+{}
#endif /* CONFIG_IWLWIFI_DEBUG */
@@ -85,29 +96,25 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
#endif /* CONFIG_IWLWIFI_DEBUGFS */
/*
- * To use the debug system;
+ * To use the debug system:
*
* If you are defining a new debug classification, simply add it to the #define
- * list here in the form of:
+ * list here in the form of
*
* #define IWL_DL_xxxx VALUE
*
- * shifting value to the left one bit from the previous entry. xxxx should be
- * the name of the classification (for example, WEP)
+ * where xxxx should be the name of the classification (for example, WEP).
*
* You then need to either add a IWL_xxxx_DEBUG() macro definition for your
* classification, or use IWL_DEBUG(IWL_DL_xxxx, ...) whenever you want
* to send output to that classification.
*
- * To add your debug level to the list of levels seen when you perform
- *
- * % cat /proc/net/iwl/debug_level
- *
- * you simply need to add your entry to the iwl_debug_levels array.
+ * The active debug levels can be accessed via files
*
- * If you do not see debug_level in /proc/net/iwl then you do not have
- * CONFIG_IWLWIFI_DEBUG defined in your kernel configuration
+ * /sys/module/iwlagn/parameters/debug{50}
+ * /sys/class/net/wlan0/device/debug_level
*
+ * when CONFIG_IWLWIFI_DEBUG=y.
*/
#define IWL_DL_INFO (1 << 0)
@@ -183,6 +190,8 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv)
#define IWL_DEBUG_STATS(f, a...) IWL_DEBUG(IWL_DL_STATS, f, ## a)
#define IWL_DEBUG_STATS_LIMIT(f, a...) IWL_DEBUG_LIMIT(IWL_DL_STATS, f, ## a)
#define IWL_DEBUG_TX_REPLY(f, a...) IWL_DEBUG(IWL_DL_TX_REPLY, f, ## a)
+#define IWL_DEBUG_TX_REPLY_LIMIT(f, a...) \
+ IWL_DEBUG_LIMIT(IWL_DL_TX_REPLY, f, ## a)
#define IWL_DEBUG_QOS(f, a...) IWL_DEBUG(IWL_DL_QOS, f, ## a)
#define IWL_DEBUG_RADIO(f, a...) IWL_DEBUG(IWL_DL_RADIO, f, ## a)
#define IWL_DEBUG_POWER(f, a...) IWL_DEBUG(IWL_DL_POWER, f, ## a)
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 20db0eb636a8..d5253a179dec 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -22,7 +22,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
- * Tomas Winkler <tomas.winkler@intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
@@ -58,7 +58,8 @@
#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \
dbgfs->dbgfs_##parent##_files.file_##name = \
debugfs_create_bool(#name, 0644, dbgfs->dir_##parent, ptr); \
- if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name)) \
+ if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \
+ || !dbgfs->dbgfs_##parent##_files.file_##name) \
goto err; \
} while (0)
@@ -228,7 +229,6 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
ssize_t ret;
/* Add 30 for initial string */
const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations);
- DECLARE_MAC_BUF(mac);
buf = kmalloc(bufsz, GFP_KERNEL);
if (!buf)
@@ -242,7 +242,6 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
if (station->used) {
pos += scnprintf(buf + pos, bufsz - pos,
"station %d:\ngeneral data:\n", i+1);
- print_mac(mac, station->sta.sta.addr);
pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n",
station->sta.sta.sta_id);
pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n",
@@ -349,12 +348,86 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file,
return count;
}
+
+
+static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
+ struct ieee80211_channel *channels = NULL;
+ const struct ieee80211_supported_band *supp_band = NULL;
+ int pos = 0, i, bufsz = PAGE_SIZE;
+ char *buf;
+ ssize_t ret;
+
+ if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
+ return -EAGAIN;
+
+ buf = kzalloc(bufsz, GFP_KERNEL);
+ if (!buf) {
+ IWL_ERROR("Can not allocate Buffer\n");
+ return -ENOMEM;
+ }
+
+ supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ);
+ channels = supp_band->channels;
+
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Displaying %d channels in 2.4GHz band 802.11bg):\n",
+ supp_band->n_channels);
+
+ for (i = 0; i < supp_band->n_channels; i++)
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "%d: %ddBm: BSS%s%s, %s.\n",
+ ieee80211_frequency_to_channel(
+ channels[i].center_freq),
+ channels[i].max_power,
+ channels[i].flags & IEEE80211_CHAN_RADAR ?
+ " (IEEE 802.11h required)" : "",
+ (!(channels[i].flags & IEEE80211_CHAN_NO_IBSS)
+ || (channels[i].flags &
+ IEEE80211_CHAN_RADAR)) ? "" :
+ ", IBSS",
+ channels[i].flags &
+ IEEE80211_CHAN_PASSIVE_SCAN ?
+ "passive only" : "active/passive");
+
+ supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ);
+ channels = supp_band->channels;
+
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "Displaying %d channels in 5.2GHz band (802.11a)\n",
+ supp_band->n_channels);
+
+ for (i = 0; i < supp_band->n_channels; i++)
+ pos += scnprintf(buf + pos, bufsz - pos,
+ "%d: %ddBm: BSS%s%s, %s.\n",
+ ieee80211_frequency_to_channel(
+ channels[i].center_freq),
+ channels[i].max_power,
+ channels[i].flags & IEEE80211_CHAN_RADAR ?
+ " (IEEE 802.11h required)" : "",
+ ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
+ || (channels[i].flags &
+ IEEE80211_CHAN_RADAR)) ? "" :
+ ", IBSS",
+ channels[i].flags &
+ IEEE80211_CHAN_PASSIVE_SCAN ?
+ "passive only" : "active/passive");
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+ kfree(buf);
+ return ret;
+}
+
+
DEBUGFS_READ_WRITE_FILE_OPS(sram);
DEBUGFS_WRITE_FILE_OPS(log_event);
DEBUGFS_READ_FILE_OPS(eeprom);
DEBUGFS_READ_FILE_OPS(stations);
DEBUGFS_READ_FILE_OPS(rx_statistics);
DEBUGFS_READ_FILE_OPS(tx_statistics);
+DEBUGFS_READ_FILE_OPS(channels);
/*
* Create the debugfs files and directories
@@ -388,6 +461,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
DEBUGFS_ADD_FILE(stations, data);
DEBUGFS_ADD_FILE(rx_statistics, data);
DEBUGFS_ADD_FILE(tx_statistics, data);
+ DEBUGFS_ADD_FILE(channels, data);
DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal);
DEBUGFS_ADD_BOOL(disable_chain_noise, rf,
&priv->disable_chain_noise_cal);
@@ -416,6 +490,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations);
+ DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels);
DEBUGFS_REMOVE(priv->dbgfs->dir_data);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity);
DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 9966d4e384ce..0468fcc1ea98 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -54,6 +54,7 @@ extern struct iwl_cfg iwl5100_agn_cfg;
extern struct iwl_cfg iwl5350_agn_cfg;
extern struct iwl_cfg iwl5100_bg_cfg;
extern struct iwl_cfg iwl5100_abg_cfg;
+extern struct iwl_cfg iwl5150_agn_cfg;
/* CT-KILL constants */
#define CT_KILL_THRESHOLD 110 /* in Celsius */
@@ -113,11 +114,9 @@ struct iwl_queue {
* space less than this */
} __attribute__ ((packed));
-#define MAX_NUM_OF_TBS (20)
-
/* One for each TFD */
struct iwl_tx_info {
- struct sk_buff *skb[MAX_NUM_OF_TBS];
+ struct sk_buff *skb[IWL_NUM_OF_TBS - 1];
};
/**
@@ -135,12 +134,13 @@ struct iwl_tx_info {
*/
struct iwl_tx_queue {
struct iwl_queue q;
- struct iwl_tfd_frame *bd;
+ struct iwl_tfd *tfds;
struct iwl_cmd *cmd[TFD_TX_CMD_SLOTS];
struct iwl_tx_info *txb;
- int need_update;
- int sched_retry;
- int active;
+ u8 need_update;
+ u8 sched_retry;
+ u8 active;
+ u8 swq_id;
};
#define IWL_NUM_SCAN_RATES (2)
@@ -186,12 +186,6 @@ struct iwl_channel_info {
u8 fat_extension_channel; /* HT_IE_EXT_CHANNEL_* */
};
-struct iwl4965_clip_group {
- /* maximum power level to prevent clipping for each rate, derived by
- * us from this band's saturation power in EEPROM */
- const s8 clip_powers[IWL_MAX_RATES];
-};
-
#define IWL_TX_FIFO_AC0 0
#define IWL_TX_FIFO_AC1 1
@@ -253,7 +247,8 @@ struct iwl_cmd_meta {
/* The CMD_SIZE_HUGE flag bit indicates that the command
* structure is stored at the end of the shared queue memory. */
u32 flags;
-
+ DECLARE_PCI_UNMAP_ADDR(mapping)
+ DECLARE_PCI_UNMAP_LEN(len)
} __attribute__ ((packed));
#define IWL_CMD_MAX_PAYLOAD 320
@@ -269,24 +264,16 @@ struct iwl_cmd {
struct iwl_cmd_meta meta; /* driver data */
struct iwl_cmd_header hdr; /* uCode API */
union {
- struct iwl_addsta_cmd addsta;
- struct iwl_led_cmd led;
u32 flags;
u8 val8;
u16 val16;
u32 val32;
- struct iwl4965_bt_cmd bt;
- struct iwl4965_rxon_time_cmd rxon_time;
- struct iwl_powertable_cmd powertable;
- struct iwl_qosparam_cmd qosparam;
struct iwl_tx_cmd tx;
- struct iwl4965_rxon_assoc_cmd rxon_assoc;
- struct iwl_rem_sta_cmd rm_sta;
- u8 *indirect;
u8 payload[IWL_CMD_MAX_PAYLOAD];
} __attribute__ ((packed)) cmd;
} __attribute__ ((packed));
+
struct iwl_host_cmd {
u8 id;
u16 len;
@@ -309,7 +296,6 @@ struct iwl_host_cmd {
/**
* struct iwl_rx_queue - Rx queue
- * @processed: Internal index to last handled Rx packet
* @read: Shared index to newest available Rx buffer
* @write: Shared index to oldest written Rx packet
* @free_count: Number of pre-allocated buffers in rx_free
@@ -324,26 +310,19 @@ struct iwl_rx_queue {
dma_addr_t dma_addr;
struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE];
- u32 processed;
u32 read;
u32 write;
u32 free_count;
struct list_head rx_free;
struct list_head rx_used;
int need_update;
+ struct iwl_rb_status *rb_stts;
+ dma_addr_t rb_stts_dma;
spinlock_t lock;
};
#define IWL_SUPPORTED_RATES_IE_LEN 8
-#define SCAN_INTERVAL 100
-
-#define MAX_A_CHANNELS 252
-#define MIN_A_CHANNELS 7
-
-#define MAX_B_CHANNELS 14
-#define MIN_B_CHANNELS 1
-
#define MAX_TID_COUNT 9
#define IWL_INVALID_RATE 0xFF
@@ -413,9 +392,8 @@ struct iwl_ht_info {
u8 max_amsdu_size;
u8 ampdu_factor;
u8 mpdu_density;
- u8 supp_mcs_set[16];
+ struct ieee80211_mcs_info mcs;
/* BSS related data */
- u8 control_channel;
u8 extension_chan_offset;
u8 tx_chan_width;
u8 ht_protection;
@@ -444,7 +422,6 @@ union iwl_qos_capabity {
/* QoS structures */
struct iwl_qos_info {
- int qos_enable;
int qos_active;
union iwl_qos_capabity qos_cap;
struct iwl_qosparam_cmd def_qos_parm;
@@ -470,7 +447,7 @@ struct fw_desc {
/* uCode file layout */
struct iwl_ucode {
- __le32 ver; /* major/minor/subminor */
+ __le32 ver; /* major/minor/API/serial */
__le32 inst_size; /* bytes of runtime instructions */
__le32 data_size; /* bytes of runtime data */
__le32 init_size; /* bytes of initialization instructions */
@@ -511,11 +488,15 @@ struct iwl_sensitivity_ranges {
};
-#define IWL_FAT_CHANNEL_52 BIT(IEEE80211_BAND_5GHZ)
+#define KELVIN_TO_CELSIUS(x) ((x)-273)
+#define CELSIUS_TO_KELVIN(x) ((x)+273)
+
/**
* struct iwl_hw_params
* @max_txq_num: Max # Tx queues supported
+ * @dma_chnl_num: Number of Tx DMA/FIFO channels
+ * @scd_bc_tbls_size: size of scheduler byte count tables
* @tx/rx_chains_num: Number of TX/RX chains
* @valid_tx/rx_ant: usable antennas
* @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
@@ -528,11 +509,13 @@ struct iwl_sensitivity_ranges {
* @sw_crypto: 0 for hw, 1 for sw
* @max_xxx_size: for ucode uses
* @ct_kill_threshold: temperature threshold
+ * @calib_init_cfg: setup initial calibrations for the hw
* @struct iwl_sensitivity_ranges: range of sensitivity values
- * @first_ampdu_q: first HW queue available for ampdu
*/
struct iwl_hw_params {
- u16 max_txq_num;
+ u8 max_txq_num;
+ u8 dma_chnl_num;
+ u16 scd_bc_tbls_size;
u8 tx_chains_num;
u8 rx_chains_num;
u8 valid_tx_ant;
@@ -549,22 +532,10 @@ struct iwl_hw_params {
u32 max_data_size;
u32 max_bsm_size;
u32 ct_kill_threshold; /* value in hw-dependent units */
+ u32 calib_init_cfg;
const struct iwl_sensitivity_ranges *sens;
- u8 first_ampdu_q;
};
-#define HT_SHORT_GI_20MHZ (1 << 0)
-#define HT_SHORT_GI_40MHZ (1 << 1)
-
-
-#define IWL_RX_HDR(x) ((struct iwl4965_rx_frame_hdr *)(\
- x->u.rx_frame.stats.payload + \
- x->u.rx_frame.stats.phy_count))
-#define IWL_RX_END(x) ((struct iwl4965_rx_frame_end *)(\
- IWL_RX_HDR(x)->payload + \
- le16_to_cpu(IWL_RX_HDR(x)->len)))
-#define IWL_RX_STATS(x) (&x->u.rx_frame.stats)
-#define IWL_RX_DATA(x) (IWL_RX_HDR(x)->payload)
/******************************************************************************
*
@@ -581,13 +552,8 @@ struct iwl_hw_params {
* iwl4965_mac_ <-- mac80211 callback
*
****************************************************************************/
-struct iwl_addsta_cmd;
-extern int iwl_send_add_sta(struct iwl_priv *priv,
- struct iwl_addsta_cmd *sta, u8 flags);
-extern u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr,
- int is_ap, u8 flags, struct ieee80211_ht_info *ht_info);
-extern void iwl4965_update_chain_flags(struct iwl_priv *priv);
-extern int iwl4965_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src);
+extern void iwl_update_chain_flags(struct iwl_priv *priv);
+extern int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src);
extern const u8 iwl_bcast_addr[ETH_ALEN];
extern int iwl_rxq_stop(struct iwl_priv *priv);
extern void iwl_txq_ctx_stop(struct iwl_priv *priv);
@@ -611,19 +577,15 @@ static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge)
}
-struct iwl_priv;
-
-
-/* Structures, enum, and defines specific to the 4965 */
-
-#define IWL_KW_SIZE 0x1000 /*4k */
-
-struct iwl_kw {
- dma_addr_t dma_addr;
- void *v_addr;
+struct iwl_dma_ptr {
+ dma_addr_t dma;
+ void *addr;
size_t size;
};
+#define HT_SHORT_GI_20MHZ (1 << 0)
+#define HT_SHORT_GI_40MHZ (1 << 1)
+
#define IWL_CHANNEL_WIDTH_20MHZ 0
#define IWL_CHANNEL_WIDTH_40MHZ 1
@@ -638,7 +600,6 @@ struct iwl_kw {
#define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000
/* Sensitivity and chain noise calibration */
-#define INTERFERENCE_DATA_AVAILABLE __constant_cpu_to_le32(1)
#define INITIALIZATION_VALUE 0xFFFF
#define CAL_NUM_OF_BEACONS 20
#define MAXIMUM_ALLOWED_PATHLOSS 15
@@ -691,13 +652,20 @@ enum iwl4965_calib_enabled_state {
IWL_CALIB_ENABLED = 1,
};
-struct statistics_general_data {
- u32 beacon_silence_rssi_a;
- u32 beacon_silence_rssi_b;
- u32 beacon_silence_rssi_c;
- u32 beacon_energy_a;
- u32 beacon_energy_b;
- u32 beacon_energy_c;
+
+/*
+ * enum iwl_calib
+ * defines the order in which results of initial calibrations
+ * should be sent to the runtime uCode
+ */
+enum iwl_calib {
+ IWL_CALIB_XTAL,
+ IWL_CALIB_DC,
+ IWL_CALIB_LO,
+ IWL_CALIB_TX_IQ,
+ IWL_CALIB_TX_IQ_PERD,
+ IWL_CALIB_BASE_BAND,
+ IWL_CALIB_MAX
};
/* Opaque calibration results */
@@ -766,7 +734,6 @@ enum {
#define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */
-#define IWL_CALIB_MAX 3
struct iwl_priv {
@@ -790,7 +757,7 @@ struct iwl_priv {
#ifdef CONFIG_IWLAGN_SPECTRUM_MEASUREMENT
/* spectrum measurement report caching */
- struct iwl4965_spectrum_notification measure_report;
+ struct iwl_spectrum_notification measure_report;
u8 measurement_status;
#endif
/* ucode beacon time */
@@ -801,10 +768,6 @@ struct iwl_priv {
struct iwl_channel_info *channel_info; /* channel info array */
u8 channel_count; /* # of channels */
- /* each calibration channel group in the EEPROM has a derived
- * clip setting for each rate. */
- const struct iwl4965_clip_group clip_groups[5];
-
/* thermal calibration */
s32 temperature; /* degrees Kelvin */
s32 last_temperature;
@@ -818,12 +781,13 @@ struct iwl_priv {
unsigned long scan_start;
unsigned long scan_pass_start;
unsigned long scan_start_tsf;
+ struct iwl_scan_cmd *scan;
int scan_bands;
int one_direct_scan;
u8 direct_ssid_len;
u8 direct_ssid[IW_ESSID_MAX_SIZE];
- struct iwl_scan_cmd *scan;
- u32 scan_tx_ant[IEEE80211_NUM_BANDS];
+ u8 scan_tx_ant[IEEE80211_NUM_BANDS];
+ u8 mgmt_tx_ant;
/* spinlock */
spinlock_t lock; /* protect general shared data */
@@ -840,6 +804,8 @@ struct iwl_priv {
u8 rev_id;
/* uCode images, save to reload in case of failure */
+ u32 ucode_ver; /* version of ucode, copy of
+ iwl_ucode.ver */
struct fw_desc ucode_code; /* runtime inst */
struct fw_desc ucode_data; /* runtime data original */
struct fw_desc ucode_data_backup; /* runtime data save/restore */
@@ -850,7 +816,7 @@ struct iwl_priv {
u8 ucode_write_complete; /* the image write is complete */
- struct iwl4965_rxon_time_cmd rxon_timing;
+ struct iwl_rxon_time_cmd rxon_timing;
/* We declare this const so it can only be
* changed via explicit cast within the
@@ -882,7 +848,6 @@ struct iwl_priv {
u16 active_rate_basic;
u8 assoc_station_added;
- u8 use_ant_b_for_management_frame; /* Tx antenna selection */
u8 start_calib;
struct iwl_sensitivity_data sensitivity_data;
struct iwl_chain_noise_data chain_noise_data;
@@ -903,12 +868,14 @@ struct iwl_priv {
struct iwl_rx_queue rxq;
struct iwl_tx_queue txq[IWL_MAX_NUM_QUEUES];
unsigned long txq_ctx_active_msk;
- struct iwl_kw kw; /* keep warm address */
+ struct iwl_dma_ptr kw; /* keep warm address */
+ struct iwl_dma_ptr scd_bc_tbls;
+
u32 scd_base_addr; /* scheduler sram base address */
unsigned long status;
- int last_rx_rssi; /* From Rx packet statisitics */
+ int last_rx_rssi; /* From Rx packet statistics */
int last_rx_noise; /* From beacon statistics */
/* counts mgmt, ctl, and data packets */
@@ -923,8 +890,6 @@ struct iwl_priv {
unsigned long last_statistics_time;
/* context information */
- u8 essid[IW_ESSID_MAX_SIZE];
- u8 essid_len;
u16 rates_mask;
u32 power_mode;
@@ -965,11 +930,7 @@ struct iwl_priv {
struct ieee80211_vif *vif;
struct iwl_hw_params hw_params;
- /* driver/uCode shared Tx Byte Counts and Rx status */
- void *shared_virt;
- int rb_closed_offset;
- /* Physical Pointer to Tx Byte Counts and Rx status */
- dma_addr_t shared_phys;
+
/* Current association information needed to configure the
* hardware */
@@ -992,7 +953,6 @@ struct iwl_priv {
struct work_struct report_work;
struct work_struct request_scan;
struct work_struct beacon_update;
- struct work_struct set_monitor;
struct tasklet_struct irq_tasklet;
@@ -1004,9 +964,6 @@ struct iwl_priv {
s8 tx_power_user_lmt;
s8 tx_power_channel_lmt;
-#ifdef CONFIG_PM
- u32 pm_state[16];
-#endif
#ifdef CONFIG_IWLWIFI_DEBUG
/* debugging info */
@@ -1091,26 +1048,4 @@ static inline int is_channel_ibss(const struct iwl_channel_info *ch)
return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0;
}
-#ifdef CONFIG_IWLWIFI_DEBUG
-static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level,
- void *p, u32 len)
-{
- if (!(priv->debug_level & level))
- return;
-
- print_hex_dump(KERN_DEBUG, "iwl data: ", DUMP_PREFIX_OFFSET, 16, 1,
- p, len, 1);
-}
-#else
-static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level,
- void *p, u32 len)
-{
-}
-#endif
-
-extern const struct iwl_channel_info *iwl_get_channel_info(
- const struct iwl_priv *priv, enum ieee80211_band band, u16 channel);
-
-/* Requires full declaration of iwl_priv before including */
-
#endif /* __iwl_dev_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 37155755efc5..ce2f47306cea 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
- * Tomas Winkler <tomas.winkler@intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@@ -169,10 +169,9 @@ int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv)
CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
/* See if we got it */
- ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
- CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
- CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
- EEPROM_SEM_TIMEOUT);
+ ret = iwl_poll_direct_bit(priv, CSR_HW_IF_CONFIG_REG,
+ CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
+ EEPROM_SEM_TIMEOUT);
if (ret >= 0) {
IWL_DEBUG_IO("Acquired semaphore after %d tries.\n",
count+1);
@@ -210,10 +209,8 @@ int iwl_eeprom_init(struct iwl_priv *priv)
{
u16 *e;
u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
- u32 r;
int sz = priv->cfg->eeprom_size;
int ret;
- int i;
u16 addr;
/* allocate eeprom */
@@ -241,22 +238,19 @@ int iwl_eeprom_init(struct iwl_priv *priv)
/* eeprom is an array of 16bit values */
for (addr = 0; addr < sz; addr += sizeof(u16)) {
- _iwl_write32(priv, CSR_EEPROM_REG, addr << 1);
- _iwl_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
-
- for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT;
- i += IWL_EEPROM_ACCESS_DELAY) {
- r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
- if (r & CSR_EEPROM_REG_READ_VALID_MSK)
- break;
- udelay(IWL_EEPROM_ACCESS_DELAY);
- }
+ u32 r;
+
+ _iwl_write32(priv, CSR_EEPROM_REG,
+ CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
- if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) {
+ ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
+ CSR_EEPROM_REG_READ_VALID_MSK,
+ IWL_EEPROM_ACCESS_TIMEOUT);
+ if (ret < 0) {
IWL_ERROR("Time out reading EEPROM[%d]\n", addr);
- ret = -ETIMEDOUT;
goto done;
}
+ r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
}
ret = 0;
@@ -279,7 +273,23 @@ EXPORT_SYMBOL(iwl_eeprom_free);
int iwl_eeprom_check_version(struct iwl_priv *priv)
{
- return priv->cfg->ops->lib->eeprom_ops.check_version(priv);
+ u16 eeprom_ver;
+ u16 calib_ver;
+
+ eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
+ calib_ver = priv->cfg->ops->lib->eeprom_ops.calib_version(priv);
+
+ if (eeprom_ver < priv->cfg->eeprom_ver ||
+ calib_ver < priv->cfg->eeprom_calib_ver)
+ goto err;
+
+ return 0;
+err:
+ IWL_ERROR("Unsupported EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n",
+ eeprom_ver, priv->cfg->eeprom_ver,
+ calib_ver, priv->cfg->eeprom_calib_ver);
+ return -EINVAL;
+
}
EXPORT_SYMBOL(iwl_eeprom_check_version);
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index d3a2a5b4ac56..603c84bed630 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
- * Tomas Winkler <tomas.winkler@intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@@ -68,17 +68,14 @@ struct iwl_priv;
/*
* EEPROM access time values:
*
- * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG,
- * then clearing (with subsequent read/modify/write) CSR_EEPROM_REG bit
- * CSR_EEPROM_REG_BIT_CMD (0x2).
+ * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG.
* Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1).
* When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec.
* Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG.
*/
#define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */
-#define IWL_EEPROM_ACCESS_DELAY 10 /* uSec */
-#define IWL_EEPROM_SEM_TIMEOUT 10 /* milliseconds */
+#define IWL_EEPROM_SEM_TIMEOUT 10 /* microseconds */
#define IWL_EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */
@@ -147,6 +144,7 @@ struct iwl_eeprom_channel {
/*5000 calibrations */
#define EEPROM_5000_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION)
#define EEPROM_5000_XTAL ((2*0x128) | EEPROM_5000_CALIB_ALL)
+#define EEPROM_5000_TEMPERATURE ((2*0x12A) | EEPROM_5000_CALIB_ALL)
/* 5000 links */
#define EEPROM_5000_LINK_HOST (2*0x64)
@@ -174,6 +172,9 @@ struct iwl_eeprom_channel {
#define EEPROM_5000_REG_BAND_52_FAT_CHANNELS ((0x92)\
| INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */
+/* 5050 Specific */
+#define EEPROM_5050_TX_POWER_VERSION (4)
+#define EEPROM_5050_EEPROM_VERSION (0x21E)
/* 2.4 GHz */
extern const u8 iwl_eeprom_band_1[14];
@@ -371,7 +372,7 @@ struct iwl_eeprom_ops {
int (*verify_signature) (struct iwl_priv *priv);
int (*acquire_semaphore) (struct iwl_priv *priv);
void (*release_semaphore) (struct iwl_priv *priv);
- int (*check_version) (struct iwl_priv *priv);
+ u16 (*calib_version) (struct iwl_priv *priv);
const u8* (*query_addr) (const struct iwl_priv *priv, size_t offset);
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h
index a72efdf6d1dd..d7da19864550 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fh.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fh.h
@@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@@ -60,6 +60,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*****************************************************************************/
+#ifndef __iwl_fh_h__
+#define __iwl_fh_h__
/****************************/
/* Flow Handler Definitions */
@@ -70,7 +72,7 @@
* Addresses are offsets from device's PCI hardware base address.
*/
#define FH_MEM_LOWER_BOUND (0x1000)
-#define FH_MEM_UPPER_BOUND (0x1EF0)
+#define FH_MEM_UPPER_BOUND (0x2000)
/**
* Keep-Warm (KW) buffer base address.
@@ -264,6 +266,7 @@
#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000)
#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000)
+#define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */
/**
* Rx Shared Status Registers (RSSR)
@@ -290,6 +293,13 @@
#define FH_MEM_TFDIB_REG1_ADDR_BITSHIFT 28
+/* TFDB Area - TFDs buffer table */
+#define FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK (0xFFFFFFFF)
+#define FH_TFDIB_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x900)
+#define FH_TFDIB_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0x958)
+#define FH_TFDIB_CTRL0_REG(_chnl) (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl))
+#define FH_TFDIB_CTRL1_REG(_chnl) (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl) + 0x4)
+
/**
* Transmit DMA Channel Control/Status Registers (TCSR)
*
@@ -316,34 +326,41 @@
#define FH_TCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xE60)
/* Find Control/Status reg for given Tx DMA/FIFO channel */
-#define FH_TCSR_CHNL_TX_CONFIG_REG(_chnl) \
- (FH_TCSR_LOWER_BOUND + 0x20 * _chnl)
+#define FH49_TCSR_CHNL_NUM (7)
+#define FH50_TCSR_CHNL_NUM (8)
+
+/* TCSR: tx_config register values */
+#define FH_TCSR_CHNL_TX_CONFIG_REG(_chnl) \
+ (FH_TCSR_LOWER_BOUND + 0x20 * (_chnl))
+#define FH_TCSR_CHNL_TX_CREDIT_REG(_chnl) \
+ (FH_TCSR_LOWER_BOUND + 0x20 * (_chnl) + 0x4)
+#define FH_TCSR_CHNL_TX_BUF_STS_REG(_chnl) \
+ (FH_TCSR_LOWER_BOUND + 0x20 * (_chnl) + 0x8)
+
+#define FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF (0x00000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRV (0x00000001)
-#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL (0x00000000)
-#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL (0x00000008)
+#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE (0x00000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE (0x00000008)
-#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE (0x00000000)
-#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE_EOF (0x40000000)
-#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE (0x80000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_NOINT (0x00000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD (0x00100000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD (0x00200000)
-#define FH_TCSR_CHNL_NUM (7)
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT (0x00000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_ENDTFD (0x00400000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_IFTFD (0x00800000)
-#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_EMPTY (0x00000000)
-#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_WAIT (0x00002000)
-#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID (0x00000003)
+#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE (0x00000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE_EOF (0x40000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE (0x80000000)
-#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_NOINT (0x00000000)
-#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD (0x00100000)
-#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD (0x00200000)
+#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_EMPTY (0x00000000)
+#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_WAIT (0x00002000)
+#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID (0x00000003)
-#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM (20)
-#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX (12)
-#define FH_TCSR_CHNL_TX_CONFIG_REG(_chnl) \
- (FH_TCSR_LOWER_BOUND + 0x20 * _chnl)
-#define FH_TCSR_CHNL_TX_CREDIT_REG(_chnl) \
- (FH_TCSR_LOWER_BOUND + 0x20 * _chnl + 0x4)
-#define FH_TCSR_CHNL_TX_BUF_STS_REG(_chnl) \
- (FH_TCSR_LOWER_BOUND + 0x20 * _chnl + 0x8)
+#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM (20)
+#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX (12)
/**
* Tx Shared Status Registers (TSSR)
@@ -360,7 +377,7 @@
#define FH_TSSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xEA0)
#define FH_TSSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xEC0)
-#define FH_TSSR_TX_STATUS_REG (FH_TSSR_LOWER_BOUND + 0x010)
+#define FH_TSSR_TX_STATUS_REG (FH_TSSR_LOWER_BOUND + 0x010)
#define FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) ((1 << (_chnl)) << 24)
#define FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl) ((1 << (_chnl)) << 16)
@@ -369,25 +386,99 @@
(FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) | \
FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl))
-
-
-#define FH_REGS_LOWER_BOUND (0x1000)
-#define FH_REGS_UPPER_BOUND (0x2000)
-
/* Tx service channels */
-#define FH_SRVC_CHNL (9)
-#define FH_SRVC_LOWER_BOUND (FH_REGS_LOWER_BOUND + 0x9C8)
-#define FH_SRVC_UPPER_BOUND (FH_REGS_LOWER_BOUND + 0x9D0)
+#define FH_SRVC_CHNL (9)
+#define FH_SRVC_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x9C8)
+#define FH_SRVC_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0x9D0)
#define FH_SRVC_CHNL_SRAM_ADDR_REG(_chnl) \
(FH_SRVC_LOWER_BOUND + ((_chnl) - 9) * 0x4)
-/* TFDB Area - TFDs buffer table */
-#define FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK (0xFFFFFFFF)
-#define FH_TFDIB_LOWER_BOUND (FH_REGS_LOWER_BOUND + 0x900)
-#define FH_TFDIB_UPPER_BOUND (FH_REGS_LOWER_BOUND + 0x958)
-#define FH_TFDIB_CTRL0_REG(_chnl) (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl))
-#define FH_TFDIB_CTRL1_REG(_chnl) (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl) + 0x4)
+#define FH_TX_CHICKEN_BITS_REG (FH_MEM_LOWER_BOUND + 0xE98)
+/* Instruct FH to increment the retry count of a packet when
+ * it is brought from the memory to TX-FIFO
+ */
+#define FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN (0x00000002)
-/* TCSR: tx_config register values */
-#define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */
+/**
+ * struct iwl_rb_status - reseve buffer status
+ * host memory mapped FH registers
+ * @closed_rb_num [0:11] - Indicates the index of the RB which was closed
+ * @closed_fr_num [0:11] - Indicates the index of the RX Frame which was closed
+ * @finished_rb_num [0:11] - Indicates the index of the current RB
+ * in which the last frame was written to
+ * @finished_fr_num [0:11] - Indicates the index of the RX Frame
+ * which was transfered
+ */
+struct iwl_rb_status {
+ __le16 closed_rb_num;
+ __le16 closed_fr_num;
+ __le16 finished_rb_num;
+ __le16 finished_fr_nam;
+} __attribute__ ((packed));
+
+
+#define TFD_QUEUE_SIZE_MAX (256)
+#define TFD_QUEUE_SIZE_BC_DUP (64)
+#define TFD_QUEUE_BC_SIZE (TFD_QUEUE_SIZE_MAX + TFD_QUEUE_SIZE_BC_DUP)
+#define IWL_TX_DMA_MASK DMA_BIT_MASK(36)
+#define IWL_NUM_OF_TBS 20
+
+static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr)
+{
+ return (sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0) & 0xF;
+}
+/**
+ * struct iwl_tfd_tb transmit buffer descriptor within transmit frame descriptor
+ *
+ * This structure contains dma address and length of transmission address
+ *
+ * @lo: low [31:0] portion of the dma address of TX buffer
+ * every even is unaligned on 16 bit boundary
+ * @hi_n_len 0-3 [35:32] portion of dma
+ * 4-15 length of the tx buffer
+ */
+struct iwl_tfd_tb {
+ __le32 lo;
+ __le16 hi_n_len;
+} __attribute__((packed));
+
+/**
+ * struct iwl_tfd
+ *
+ * Transmit Frame Descriptor (TFD)
+ *
+ * @ __reserved1[3] reserved
+ * @ num_tbs 0-4 number of active tbs
+ * 5 reserved
+ * 6-7 padding (not used)
+ * @ tbs[20] transmit frame buffer descriptors
+ * @ __pad padding
+ *
+ * Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM.
+ * Both driver and device share these circular buffers, each of which must be
+ * contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes
+ *
+ * Driver must indicate the physical address of the base of each
+ * circular buffer via the FH_MEM_CBBC_QUEUE registers.
+ *
+ * Each TFD contains pointer/size information for up to 20 data buffers
+ * in host DRAM. These buffers collectively contain the (one) frame described
+ * by the TFD. Each buffer must be a single contiguous block of memory within
+ * itself, but buffers may be scattered in host DRAM. Each buffer has max size
+ * of (4K - 4). The concatenates all of a TFD's buffers into a single
+ * Tx frame, up to 8 KBytes in size.
+ *
+ * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx.
+ */
+struct iwl_tfd {
+ u8 __reserved1[3];
+ u8 num_tbs;
+ struct iwl_tfd_tb tbs[IWL_NUM_OF_TBS];
+ __le32 __pad;
+} __attribute__ ((packed));
+
+
+/* Keep Warm Size */
+#define IWL_KW_SIZE 0x1000 /* 4k */
+#endif /* !__iwl_fh_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index 8300f3d00a06..01a2169cecec 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -22,7 +22,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
- * Tomas Winkler <tomas.winkler@intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
@@ -36,7 +36,7 @@
#include "iwl-core.h"
-#define IWL_CMD(x) case x : return #x
+#define IWL_CMD(x) case x: return #x
const char *get_cmd_string(u8 cmd)
{
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
index 41eed6793328..ca4f638ab9d0 100644
--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -32,110 +32,6 @@
#include <linux/ctype.h>
-/*
- * The structures defined by the hardware/uCode interface
- * have bit-wise operations. For each bit-field there is
- * a data symbol in the structure, the start bit position
- * and the length of the bit-field.
- *
- * iwl_get_bits and iwl_set_bits will return or set the
- * appropriate bits on a 32-bit value.
- *
- * IWL_GET_BITS and IWL_SET_BITS use symbol expansion to
- * expand out to the appropriate call to iwl_get_bits
- * and iwl_set_bits without having to reference all of the
- * numerical constants and defines provided in the hardware
- * definition
- */
-
-/**
- * iwl_get_bits - Extract a hardware bit-field value
- * @src: source hardware value (__le32)
- * @pos: bit-position (0-based) of first bit of value
- * @len: length of bit-field
- *
- * iwl_get_bits will return the bit-field in cpu endian ordering.
- *
- * NOTE: If used from IWL_GET_BITS then pos and len are compile-constants and
- * will collapse to minimal code by the compiler.
- */
-static inline u32 iwl_get_bits(__le32 src, u8 pos, u8 len)
-{
- u32 tmp = le32_to_cpu(src);
-
- tmp >>= pos;
- tmp &= (1UL << len) - 1;
- return tmp;
-}
-
-/**
- * iwl_set_bits - Set a hardware bit-field value
- * @dst: Address of __le32 hardware value
- * @pos: bit-position (0-based) of first bit of value
- * @len: length of bit-field
- * @val: cpu endian value to encode into the bit-field
- *
- * iwl_set_bits will encode val into dst, masked to be len bits long at bit
- * position pos.
- *
- * NOTE: If used IWL_SET_BITS pos and len will be compile-constants and
- * will collapse to minimal code by the compiler.
- */
-static inline void iwl_set_bits(__le32 *dst, u8 pos, u8 len, int val)
-{
- u32 tmp = le32_to_cpu(*dst);
-
- tmp &= ~(((1UL << len) - 1) << pos);
- tmp |= (val & ((1UL << len) - 1)) << pos;
- *dst = cpu_to_le32(tmp);
-}
-
-static inline void iwl_set_bits16(__le16 *dst, u8 pos, u8 len, int val)
-{
- u16 tmp = le16_to_cpu(*dst);
-
- tmp &= ~((1UL << (pos + len)) - (1UL << pos));
- tmp |= (val & ((1UL << len) - 1)) << pos;
- *dst = cpu_to_le16(tmp);
-}
-
-/*
- * The bit-field definitions in iwl-xxxx-hw.h are in the form of:
- *
- * struct example {
- * __le32 val1;
- * #define IWL_name_POS 8
- * #define IWL_name_LEN 4
- * #define IWL_name_SYM val1
- * };
- *
- * The IWL_SET_BITS and IWL_GET_BITS macros are provided to allow the driver
- * to call:
- *
- * struct example bar;
- * u32 val = IWL_GET_BITS(bar, name);
- * val = val * 2;
- * IWL_SET_BITS(bar, name, val);
- *
- * All cpu / host ordering, masking, and shifts are performed by the macros
- * and iwl_{get,set}_bits.
- *
- */
-#define IWL_SET_BITS(s, sym, v) \
- iwl_set_bits(&(s).IWL_ ## sym ## _SYM, IWL_ ## sym ## _POS, \
- IWL_ ## sym ## _LEN, (v))
-
-#define IWL_SET_BITS16(s, sym, v) \
- iwl_set_bits16(&(s).IWL_ ## sym ## _SYM, IWL_ ## sym ## _POS, \
- IWL_ ## sym ## _LEN, (v))
-
-#define IWL_GET_BITS(s, sym) \
- iwl_get_bits((s).IWL_ ## sym ## _SYM, IWL_ ## sym ## _POS, \
- IWL_ ## sym ## _LEN)
-
-
-#define KELVIN_TO_CELSIUS(x) ((x)-273)
-#define CELSIUS_TO_KELVIN(x) ((x)+273)
#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
@@ -159,11 +55,6 @@ static inline unsigned long elapsed_jiffies(unsigned long start,
return end + (MAX_JIFFY_OFFSET - start) + 1;
}
-static inline u8 iwl_get_dma_hi_address(dma_addr_t addr)
-{
- return sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0;
-}
-
/**
* iwl_queue_inc_wrap - increment queue index, wrap back to beginning
* @index -- current index
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
index 9740fcc1805e..0a92e7431ada 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-io.h
@@ -21,7 +21,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -55,7 +55,7 @@
* _iwl_read32.)
*
* These declarations are *extremely* useful in quickly isolating code deltas
- * which result in misconfiguring of the hardware I/O. In combination with
+ * which result in misconfiguration of the hardware I/O. In combination with
* git-bisect and the IO debug level you can quickly determine the specific
* commit which breaks the IO sequence to the hardware.
*
@@ -87,17 +87,18 @@ static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs)
#define iwl_read32(p, o) _iwl_read32(p, o)
#endif
+#define IWL_POLL_INTERVAL 10 /* microseconds */
static inline int _iwl_poll_bit(struct iwl_priv *priv, u32 addr,
u32 bits, u32 mask, int timeout)
{
- int i = 0;
+ int t = 0;
do {
if ((_iwl_read32(priv, addr) & mask) == (bits & mask))
- return i;
- mdelay(10);
- i += 10;
- } while (i < timeout);
+ return t;
+ udelay(IWL_POLL_INTERVAL);
+ t += IWL_POLL_INTERVAL;
+ } while (t < timeout);
return -ETIMEDOUT;
}
@@ -109,7 +110,7 @@ static inline int __iwl_poll_bit(const char *f, u32 l,
int ret = _iwl_poll_bit(priv, addr, bits, mask, timeout);
IWL_DEBUG_IO("poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n",
addr, bits, mask,
- unlikely(ret == -ETIMEDOUT)?"timeout":"", f, l);
+ unlikely(ret == -ETIMEDOUT) ? "timeout" : "", f, l);
return ret;
}
#define iwl_poll_bit(priv, addr, bits, mask, timeout) \
@@ -269,19 +270,10 @@ static inline void iwl_write_reg_buf(struct iwl_priv *priv,
}
}
-static inline int _iwl_poll_direct_bit(struct iwl_priv *priv,
- u32 addr, u32 mask, int timeout)
+static inline int _iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr,
+ u32 mask, int timeout)
{
- int i = 0;
-
- do {
- if ((_iwl_read_direct32(priv, addr) & mask) == mask)
- return i;
- mdelay(10);
- i += 10;
- } while (i < timeout);
-
- return -ETIMEDOUT;
+ return _iwl_poll_bit(priv, addr, mask, mask, timeout);
}
#ifdef CONFIG_IWLWIFI_DEBUG
@@ -308,6 +300,7 @@ static inline int __iwl_poll_direct_bit(const char *f, u32 l,
static inline u32 _iwl_read_prph(struct iwl_priv *priv, u32 reg)
{
_iwl_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
+ rmb();
return _iwl_read_direct32(priv, HBUS_TARG_PRPH_RDAT);
}
#ifdef CONFIG_IWLWIFI_DEBUG
@@ -330,6 +323,7 @@ static inline void _iwl_write_prph(struct iwl_priv *priv,
{
_iwl_write_direct32(priv, HBUS_TARG_PRPH_WADDR,
((addr & 0x0000FFFF) | (3 << 24)));
+ wmb();
_iwl_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val);
}
#ifdef CONFIG_IWLWIFI_DEBUG
@@ -392,12 +386,14 @@ static inline void iwl_clear_bits_prph(struct iwl_priv
static inline u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr)
{
iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr);
+ rmb();
return iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
}
static inline void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val)
{
iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
+ wmb();
iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, val);
}
@@ -405,6 +401,7 @@ static inline void iwl_write_targ_mem_buf(struct iwl_priv *priv, u32 addr,
u32 len, u32 *values)
{
iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
+ wmb();
for (; 0 < len; len -= sizeof(u32), values++)
iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index 4eee1b163cd2..11eccd7d268c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -41,7 +41,6 @@
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-io.h"
-#include "iwl-helpers.h"
#ifdef CONFIG_IWLWIFI_DEBUG
static const char *led_type_str[] = {
@@ -278,7 +277,7 @@ static int iwl_get_blink_rate(struct iwl_priv *priv)
/* FIXME: + priv->rx_stats[2].bytes; */
s64 tpt = current_tpt - priv->led_tpt;
- if (tpt < 0) /* wrapparound */
+ if (tpt < 0) /* wraparound */
tpt = -tpt;
IWL_DEBUG_LED("tpt %lld current_tpt %llu\n",
@@ -293,7 +292,7 @@ static int iwl_get_blink_rate(struct iwl_priv *priv)
if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE))
break;
- IWL_DEBUG_LED("LED BLINK IDX=%d", i);
+ IWL_DEBUG_LED("LED BLINK IDX=%d\n", i);
return i;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h
index 588c9ad20e83..021e00bcd1be 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.h
+++ b/drivers/net/wireless/iwlwifi/iwl-led.h
@@ -19,7 +19,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 60a03d2d2d0e..75ca6a542174 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
@@ -39,7 +39,6 @@
#include "iwl-commands.h"
#include "iwl-debug.h"
#include "iwl-power.h"
-#include "iwl-helpers.h"
/*
* Setting power level allow the card to go to sleep when not busy
@@ -80,7 +79,7 @@
#define IWL_REDUCED_POWER_TEMPERATURE 95
/* default power management (not Tx power) table values */
-/* for tim 0-10 */
+/* for TIM 0-10 */
static struct iwl_power_vec_entry range_0[IWL_POWER_MAX] = {
{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
@@ -91,7 +90,7 @@ static struct iwl_power_vec_entry range_0[IWL_POWER_MAX] = {
};
-/* for tim = 3-10 */
+/* for TIM = 3-10 */
static struct iwl_power_vec_entry range_1[IWL_POWER_MAX] = {
{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
@@ -101,7 +100,7 @@ static struct iwl_power_vec_entry range_1[IWL_POWER_MAX] = {
{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2}
};
-/* for tim > 11 */
+/* for TIM > 11 */
static struct iwl_power_vec_entry range_2[IWL_POWER_MAX] = {
{{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
@@ -183,7 +182,7 @@ static int iwl_power_init_handle(struct iwl_priv *priv)
return 0;
}
-/* adjust power command according to dtim period and power level*/
+/* adjust power command according to DTIM period and power level*/
static int iwl_update_power_command(struct iwl_priv *priv,
struct iwl_powertable_cmd *cmd,
u16 mode)
@@ -257,15 +256,11 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
struct iwl_power_mgr *setting = &(priv->power_data);
int ret = 0;
u16 uninitialized_var(final_mode);
+ bool update_chains;
/* Don't update the RX chain when chain noise calibration is running */
- if (priv->chain_noise_data.state != IWL_CHAIN_NOISE_DONE &&
- priv->chain_noise_data.state != IWL_CHAIN_NOISE_ALIVE) {
- IWL_DEBUG_POWER("Cannot update the power, chain noise "
- "calibration running: %d\n",
- priv->chain_noise_data.state);
- return -EAGAIN;
- }
+ update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
+ priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
/* If on battery, set to 3,
* if plugged into AC power, set to CAM ("continuously aware mode"),
@@ -313,9 +308,12 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
else
set_bit(STATUS_POWER_PMI, &priv->status);
- if (priv->cfg->ops->lib->update_chain_flags)
+ if (priv->cfg->ops->lib->update_chain_flags && update_chains)
priv->cfg->ops->lib->update_chain_flags(priv);
-
+ else
+ IWL_DEBUG_POWER("Cannot update the power, chain noise "
+ "calibration running: %d\n",
+ priv->chain_noise_data.state);
if (!ret)
setting->power_mode = final_mode;
}
@@ -325,7 +323,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
EXPORT_SYMBOL(iwl_power_update_mode);
/* Allow other iwl code to disable/enable power management active
- * this will be usefull for rate scale to disable PM during heavy
+ * this will be useful for rate scale to disable PM during heavy
* Tx/Rx activities
*/
int iwl_power_disable_management(struct iwl_priv *priv, u32 ms)
@@ -352,8 +350,8 @@ int iwl_power_disable_management(struct iwl_priv *priv, u32 ms)
EXPORT_SYMBOL(iwl_power_disable_management);
/* Allow other iwl code to disable/enable power management active
- * this will be usefull for rate scale to disable PM during hight
- * valume activities
+ * this will be useful for rate scale to disable PM during high
+ * volume activities
*/
int iwl_power_enable_management(struct iwl_priv *priv)
{
@@ -391,7 +389,7 @@ int iwl_power_set_system_mode(struct iwl_priv *priv, u16 mode)
}
EXPORT_SYMBOL(iwl_power_set_system_mode);
-/* initilize to default */
+/* initialize to default */
void iwl_power_initialize(struct iwl_priv *priv)
{
@@ -443,7 +441,7 @@ static void iwl_bg_set_power_save(struct work_struct *work)
mutex_lock(&priv->mutex);
- /* on starting association we disable power managment
+ /* on starting association we disable power management
* until association, if association failed then this
* timer will expire and enable PM again.
*/
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h
index df484a90ae64..fa098d8975ce 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
#ifndef __iwl_power_setting_h__
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index ee5afd48d3af..b7a5f23351c3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -25,7 +25,7 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
* BSD LICENSE
@@ -158,9 +158,9 @@
*
* 4) Point (via BSM_DRAM_*) to the "runtime" uCode data and instruction
* images in host DRAM. The last register loaded must be the instruction
- * bytecount register ("1" in MSbit tells initialization uCode to load
+ * byte count register ("1" in MSbit tells initialization uCode to load
* the runtime uCode):
- * BSM_DRAM_INST_BYTECOUNT_REG = bytecount | BSM_DRAM_INST_LOAD
+ * BSM_DRAM_INST_BYTECOUNT_REG = byte count | BSM_DRAM_INST_LOAD
*
* 5) Wait for "alive" notification, then issue normal runtime commands.
*
@@ -244,7 +244,7 @@
/**
* Tx Scheduler
*
- * The Tx Scheduler selects the next frame to be transmitted, chosing TFDs
+ * The Tx Scheduler selects the next frame to be transmitted, choosing TFDs
* (Transmit Frame Descriptors) from up to 16 circular Tx queues resident in
* host DRAM. It steers each frame's Tx command (which contains the frame
* data) into one of up to 7 prioritized Tx DMA FIFO channels within the
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
index 5d642298f04c..4b69da30665c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c
@@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
#include <linux/kernel.h>
@@ -34,8 +34,6 @@
#include "iwl-eeprom.h"
#include "iwl-dev.h"
#include "iwl-core.h"
-#include "iwl-helpers.h"
-
/* software rf-kill from user */
static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
@@ -64,7 +62,7 @@ static int iwl_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
iwl_radio_kill_sw_disable_radio(priv);
break;
default:
- IWL_WARNING("we recieved unexpected RFKILL state %d\n", state);
+ IWL_WARNING("we received unexpected RFKILL state %d\n", state);
break;
}
out_unlock:
@@ -83,7 +81,7 @@ int iwl_rfkill_init(struct iwl_priv *priv)
IWL_DEBUG_RF_KILL("Initializing RFKILL.\n");
priv->rfkill = rfkill_allocate(device, RFKILL_TYPE_WLAN);
if (!priv->rfkill) {
- IWL_ERROR("Unable to allocate rfkill device.\n");
+ IWL_ERROR("Unable to allocate RFKILL device.\n");
ret = -ENOMEM;
goto error;
}
@@ -99,7 +97,7 @@ int iwl_rfkill_init(struct iwl_priv *priv)
ret = rfkill_register(priv->rfkill);
if (ret) {
- IWL_ERROR("Unable to register rfkill: %d\n", ret);
+ IWL_ERROR("Unable to register RFKILL: %d\n", ret);
goto free_rfkill;
}
@@ -127,7 +125,7 @@ void iwl_rfkill_unregister(struct iwl_priv *priv)
}
EXPORT_SYMBOL(iwl_rfkill_unregister);
-/* set rf-kill to the right state. */
+/* set RFKILL to the right state. */
void iwl_rfkill_set_hw_state(struct iwl_priv *priv)
{
if (!priv->rfkill)
diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.h b/drivers/net/wireless/iwlwifi/iwl-rfkill.h
index 402fd4c781da..86dc055a2e94 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rfkill.h
+++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.h
@@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
#ifndef __iwl_rf_kill_h__
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index 0509c16dbe75..c5f1aa0feac8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -218,8 +218,7 @@ int iwl_rx_queue_restock(struct iwl_priv *priv)
/* If we've added more space for the firmware to place data, tell it.
* Increment device's write pointer in multiples of 8. */
- if ((write != (rxq->write & ~0x7))
- || (abs(rxq->write - rxq->read) > 7)) {
+ if (write != (rxq->write & ~0x7)) {
spin_lock_irqsave(&rxq->lock, flags);
rxq->need_update = 1;
spin_unlock_irqrestore(&rxq->lock, flags);
@@ -245,25 +244,31 @@ void iwl_rx_allocate(struct iwl_priv *priv)
struct list_head *element;
struct iwl_rx_mem_buffer *rxb;
unsigned long flags;
- spin_lock_irqsave(&rxq->lock, flags);
- while (!list_empty(&rxq->rx_used)) {
+
+ while (1) {
+ spin_lock_irqsave(&rxq->lock, flags);
+
+ if (list_empty(&rxq->rx_used)) {
+ spin_unlock_irqrestore(&rxq->lock, flags);
+ return;
+ }
element = rxq->rx_used.next;
rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+ list_del(element);
+
+ spin_unlock_irqrestore(&rxq->lock, flags);
/* Alloc a new receive buffer */
rxb->skb = alloc_skb(priv->hw_params.rx_buf_size + 256,
- __GFP_NOWARN | GFP_ATOMIC);
+ GFP_KERNEL);
if (!rxb->skb) {
- if (net_ratelimit())
- printk(KERN_CRIT DRV_NAME
- ": Can not allocate SKB buffers\n");
+ printk(KERN_CRIT DRV_NAME
+ "Can not allocate SKB buffers\n");
/* We don't reschedule replenish work here -- we will
* call the restock method and if it still needs
* more buffers it will schedule replenish */
break;
}
- priv->alloc_rxb_skb++;
- list_del(element);
/* Get physical address of RB/SKB */
rxb->real_dma_addr = pci_map_single(
@@ -277,12 +282,15 @@ void iwl_rx_allocate(struct iwl_priv *priv)
rxb->aligned_dma_addr = ALIGN(rxb->real_dma_addr, 256);
skb_reserve(rxb->skb, rxb->aligned_dma_addr - rxb->real_dma_addr);
+ spin_lock_irqsave(&rxq->lock, flags);
+
list_add_tail(&rxb->list, &rxq->rx_free);
rxq->free_count++;
+ priv->alloc_rxb_skb++;
+
+ spin_unlock_irqrestore(&rxq->lock, flags);
}
- spin_unlock_irqrestore(&rxq->lock, flags);
}
-EXPORT_SYMBOL(iwl_rx_allocate);
void iwl_rx_replenish(struct iwl_priv *priv)
{
@@ -317,7 +325,10 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
rxq->dma_addr);
+ pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status),
+ rxq->rb_stts, rxq->rb_stts_dma);
rxq->bd = NULL;
+ rxq->rb_stts = NULL;
}
EXPORT_SYMBOL(iwl_rx_queue_free);
@@ -334,7 +345,12 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv)
/* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */
rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr);
if (!rxq->bd)
- return -ENOMEM;
+ goto err_bd;
+
+ rxq->rb_stts = pci_alloc_consistent(dev, sizeof(struct iwl_rb_status),
+ &rxq->rb_stts_dma);
+ if (!rxq->rb_stts)
+ goto err_rb;
/* Fill the rx_used queue with _all_ of the Rx buffers */
for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
@@ -346,6 +362,12 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv)
rxq->free_count = 0;
rxq->need_update = 0;
return 0;
+
+err_rb:
+ pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+ rxq->dma_addr);
+err_bd:
+ return -ENOMEM;
}
EXPORT_SYMBOL(iwl_rx_queue_alloc);
@@ -412,10 +434,10 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
/* Tell device where in DRAM to update its Rx status */
iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
- (priv->shared_phys + priv->rb_closed_offset) >> 4);
+ rxq->rb_stts_dma >> 4);
/* Enable Rx DMA
- * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set becuase of HW bug in
+ * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in
* the credit mechanism in 5000 HW RX FIFO
* Direct rx interrupts to hosts
* Rx buffer size 4 or 8k
@@ -426,6 +448,7 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY |
FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
+ FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK |
rb_size|
(rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
(rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
@@ -453,10 +476,8 @@ int iwl_rxq_stop(struct iwl_priv *priv)
/* stop Rx DMA */
iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
- ret = iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
- (1 << 24), 1000);
- if (ret < 0)
- IWL_ERROR("Can't stop Rx DMA.\n");
+ iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
+ FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
iwl_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -470,7 +491,7 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
{
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
- struct iwl4965_missed_beacon_notif *missed_beacon;
+ struct iwl_missed_beacon_notif *missed_beacon;
missed_beacon = &pkt->u.missed_beacon;
if (le32_to_cpu(missed_beacon->consequtive_missed_beacons) > 5) {
@@ -485,49 +506,6 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
}
EXPORT_SYMBOL(iwl_rx_missed_beacon_notif);
-int iwl_rx_agg_start(struct iwl_priv *priv, const u8 *addr, int tid, u16 ssn)
-{
- unsigned long flags;
- int sta_id;
-
- sta_id = iwl_find_station(priv, addr);
- if (sta_id == IWL_INVALID_STATION)
- return -ENXIO;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].sta.station_flags_msk = 0;
- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
- priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
- priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- return iwl_send_add_sta(priv, &priv->stations[sta_id].sta,
- CMD_ASYNC);
-}
-EXPORT_SYMBOL(iwl_rx_agg_start);
-
-int iwl_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid)
-{
- unsigned long flags;
- int sta_id;
-
- sta_id = iwl_find_station(priv, addr);
- if (sta_id == IWL_INVALID_STATION)
- return -ENXIO;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].sta.station_flags_msk = 0;
- priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
- priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- return iwl_send_add_sta(priv, &priv->stations[sta_id].sta,
- CMD_ASYNC);
-}
-EXPORT_SYMBOL(iwl_rx_agg_stop);
-
/* Calculate noise level, based on measurements during network silence just
* before arriving beacon. This measurement can be done only if we know
@@ -651,20 +629,24 @@ static int iwl_calc_sig_qual(int rssi_dbm, int noise_dbm)
return sig_qual;
}
-#ifdef CONFIG_IWLWIFI_DEBUG
+/* Calc max signal level (dBm) among 3 possible receivers */
+static inline int iwl_calc_rssi(struct iwl_priv *priv,
+ struct iwl_rx_phy_res *rx_resp)
+{
+ return priv->cfg->ops->utils->calc_rssi(priv, rx_resp);
+}
+#ifdef CONFIG_IWLWIFI_DEBUG
/**
* iwl_dbg_report_frame - dump frame to syslog during debug sessions
*
* You may hack this function to show different aspects of received frames,
* including selective frame dumps.
- * group100 parameter selects whether to show 1 out of 100 good frames.
- *
- * TODO: This was originally written for 3945, need to audit for
- * proper operation with 4965.
+ * group100 parameter selects whether to show 1 out of 100 good data frames.
+ * All beacon and probe response frames are printed.
*/
static void iwl_dbg_report_frame(struct iwl_priv *priv,
- struct iwl_rx_packet *pkt,
+ struct iwl_rx_phy_res *phy_res, u16 length,
struct ieee80211_hdr *header, int group100)
{
u32 to_us;
@@ -676,20 +658,9 @@ static void iwl_dbg_report_frame(struct iwl_priv *priv,
u16 seq_ctl;
u16 channel;
u16 phy_flags;
- int rate_sym;
- u16 length;
- u16 status;
- u16 bcn_tmr;
+ u32 rate_n_flags;
u32 tsf_low;
- u64 tsf;
- u8 rssi;
- u8 agc;
- u16 sig_avg;
- u16 noise_diff;
- struct iwl4965_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
- struct iwl4965_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
- struct iwl4965_rx_frame_end *rx_end = IWL_RX_END(pkt);
- u8 *data = IWL_RX_DATA(pkt);
+ int rssi;
if (likely(!(priv->debug_level & IWL_DL_RX)))
return;
@@ -699,22 +670,13 @@ static void iwl_dbg_report_frame(struct iwl_priv *priv,
seq_ctl = le16_to_cpu(header->seq_ctrl);
/* metadata */
- channel = le16_to_cpu(rx_hdr->channel);
- phy_flags = le16_to_cpu(rx_hdr->phy_flags);
- rate_sym = rx_hdr->rate;
- length = le16_to_cpu(rx_hdr->len);
-
- /* end-of-frame status and timestamp */
- status = le32_to_cpu(rx_end->status);
- bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp);
- tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff;
- tsf = le64_to_cpu(rx_end->timestamp);
+ channel = le16_to_cpu(phy_res->channel);
+ phy_flags = le16_to_cpu(phy_res->phy_flags);
+ rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
/* signal statistics */
- rssi = rx_stats->rssi;
- agc = rx_stats->agc;
- sig_avg = le16_to_cpu(rx_stats->sig_avg);
- noise_diff = le16_to_cpu(rx_stats->noise_diff);
+ rssi = iwl_calc_rssi(priv, phy_res);
+ tsf_low = le64_to_cpu(phy_res->timestamp) & 0x0ffffffff;
to_us = !compare_ether_addr(header->addr1, priv->mac_addr);
@@ -768,11 +730,13 @@ static void iwl_dbg_report_frame(struct iwl_priv *priv,
else
title = "Frame";
- rate_idx = iwl_hwrate_to_plcp_idx(rate_sym);
- if (unlikely(rate_idx == -1))
+ rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags);
+ if (unlikely((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT))) {
bitrate = 0;
- else
+ WARN_ON_ONCE(1);
+ } else {
bitrate = iwl_rates[rate_idx].ieee / 2;
+ }
/* print frame summary.
* MAC addresses show just the last byte (for brevity),
@@ -784,24 +748,17 @@ static void iwl_dbg_report_frame(struct iwl_priv *priv,
length, rssi, channel, bitrate);
else {
/* src/dst addresses assume managed mode */
- IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, "
- "src=0x%02x, rssi=%u, tim=%lu usec, "
+ IWL_DEBUG_RX("%s: 0x%04x, dst=0x%02x, src=0x%02x, "
+ "len=%u, rssi=%d, tim=%lu usec, "
"phy=0x%02x, chnl=%d\n",
title, le16_to_cpu(fc), header->addr1[5],
- header->addr3[5], rssi,
+ header->addr3[5], length, rssi,
tsf_low - priv->scan_start_tsf,
phy_flags, channel);
}
}
if (print_dump)
- iwl_print_hex_dump(priv, IWL_DL_RX, data, length);
-}
-#else
-static inline void iwl_dbg_report_frame(struct iwl_priv *priv,
- struct iwl_rx_packet *pkt,
- struct ieee80211_hdr *header,
- int group100)
-{
+ iwl_print_hex_dump(priv, IWL_DL_RX, header, length);
}
#endif
@@ -995,46 +952,6 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
rxb->skb = NULL;
}
-/* Calc max signal level (dBm) among 3 possible receivers */
-static inline int iwl_calc_rssi(struct iwl_priv *priv,
- struct iwl_rx_phy_res *rx_resp)
-{
- return priv->cfg->ops->utils->calc_rssi(priv, rx_resp);
-}
-
-
-static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&priv->sta_lock, flags);
- priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK;
- priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
- priv->stations[sta_id].sta.sta.modify_mask = 0;
- priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
- spin_unlock_irqrestore(&priv->sta_lock, flags);
-
- iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
-}
-
-static void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr)
-{
- /* FIXME: need locking over ps_status ??? */
- u8 sta_id = iwl_find_station(priv, addr);
-
- if (sta_id != IWL_INVALID_STATION) {
- u8 sta_awake = priv->stations[sta_id].
- ps_status == STA_PS_STATUS_WAKE;
-
- if (sta_awake && ps_bit)
- priv->stations[sta_id].ps_status = STA_PS_STATUS_SLEEP;
- else if (!sta_awake && !ps_bit) {
- iwl_sta_modify_ps_wake(priv, sta_id);
- priv->stations[sta_id].ps_status = STA_PS_STATUS_WAKE;
- }
- }
-}
-
/* This is necessary only for a number of statistics, see the caller. */
static int iwl_is_network_packet(struct iwl_priv *priv,
struct ieee80211_hdr *header)
@@ -1157,9 +1074,10 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
/* Set "1" to report good data frames in groups of 100 */
- /* FIXME: need to optimze the call: */
- iwl_dbg_report_frame(priv, pkt, header, 1);
-
+#ifdef CONFIG_IWLWIFI_DEBUG
+ if (unlikely(priv->debug_level & IWL_DL_RX))
+ iwl_dbg_report_frame(priv, rx_start, len, header, 1);
+#endif
IWL_DEBUG_STATS_LIMIT("Rssi %d, noise %d, qual %d, TSF %llu\n",
rx_status.signal, rx_status.noise, rx_status.signal,
(unsigned long long)rx_status.mactime);
@@ -1168,12 +1086,12 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
* "antenna number"
*
* It seems that the antenna field in the phy flags value
- * is actually a bitfield. This is undefined by radiotap,
+ * is actually a bit field. This is undefined by radiotap,
* it wants an actual antenna number but I always get "7"
* for most legacy frames I receive indicating that the
* same frame was received on all three RX chains.
*
- * I think this field should be removed in favour of a
+ * I think this field should be removed in favor of a
* new 802.11n radiotap field "RX chains" that is defined
* as a bitmask.
*/
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index c89365e2ca58..3c803f6922ef 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -22,11 +22,13 @@
* in the file called LICENSE.GPL.
*
* Contact Information:
- * Tomas Winkler <tomas.winkler@intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*****************************************************************************/
-#include <net/mac80211.h>
+#include <linux/types.h>
#include <linux/etherdevice.h>
+#include <net/lib80211.h>
+#include <net/mac80211.h>
#include "iwl-eeprom.h"
#include "iwl-dev.h"
@@ -64,54 +66,6 @@
#define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1))))
-static int scan_tx_ant[3] = {
- RATE_MCS_ANT_A_MSK, RATE_MCS_ANT_B_MSK, RATE_MCS_ANT_C_MSK
-};
-
-
-
-static int iwl_is_empty_essid(const char *essid, int essid_len)
-{
- /* Single white space is for Linksys APs */
- if (essid_len == 1 && essid[0] == ' ')
- return 1;
-
- /* Otherwise, if the entire essid is 0, we assume it is hidden */
- while (essid_len) {
- essid_len--;
- if (essid[essid_len] != '\0')
- return 0;
- }
-
- return 1;
-}
-
-
-
-static const char *iwl_escape_essid(const char *essid, u8 essid_len)
-{
- static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
- const char *s = essid;
- char *d = escaped;
-
- if (iwl_is_empty_essid(essid, essid_len)) {
- memcpy(escaped, "<hidden>", sizeof("<hidden>"));
- return escaped;
- }
-
- essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
- while (essid_len--) {
- if (*s == '\0') {
- *d++ = '\\';
- *d++ = '0';
- s++;
- } else
- *d++ = *s++;
- }
- *d = '\0';
- return escaped;
-}
-
/**
* iwl_scan_cancel - Cancel any currently executing HW scan
*
@@ -455,10 +409,11 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
void iwl_init_scan_params(struct iwl_priv *priv)
{
+ u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1;
if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ])
- priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = RATE_MCS_ANT_INIT_IND;
+ priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx;
if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ])
- priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = RATE_MCS_ANT_INIT_IND;
+ priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx;
}
int iwl_scan_initiate(struct iwl_priv *priv)
@@ -550,7 +505,7 @@ static void iwl_ht_cap_to_ie(const struct ieee80211_supported_band *sband,
{
struct ieee80211_ht_cap *ht_cap;
- if (!sband || !sband->ht_info.ht_supported)
+ if (!sband || !sband->ht_cap.ht_supported)
return;
if (*left < sizeof(struct ieee80211_ht_cap))
@@ -559,12 +514,12 @@ static void iwl_ht_cap_to_ie(const struct ieee80211_supported_band *sband,
*pos++ = sizeof(struct ieee80211_ht_cap);
ht_cap = (struct ieee80211_ht_cap *) pos;
- ht_cap->cap_info = cpu_to_le16(sband->ht_info.cap);
- memcpy(ht_cap->supp_mcs_set, sband->ht_info.supp_mcs_set, 16);
+ ht_cap->cap_info = cpu_to_le16(sband->ht_cap.cap);
+ memcpy(&ht_cap->mcs, &sband->ht_cap.mcs, 16);
ht_cap->ampdu_params_info =
- (sband->ht_info.ampdu_factor & IEEE80211_HT_CAP_AMPDU_FACTOR) |
- ((sband->ht_info.ampdu_density << 2) &
- IEEE80211_HT_CAP_AMPDU_DENSITY);
+ (sband->ht_cap.ampdu_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) |
+ ((sband->ht_cap.ampdu_density << 2) &
+ IEEE80211_HT_AMPDU_PARM_DENSITY);
*left -= sizeof(struct ieee80211_ht_cap);
}
@@ -670,23 +625,6 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
return (u16)len;
}
-static u32 iwl_scan_tx_ant(struct iwl_priv *priv, enum ieee80211_band band)
-{
- int i, ind;
-
- ind = priv->scan_tx_ant[band];
- for (i = 0; i < priv->hw_params.tx_chains_num; i++) {
- ind = (ind+1) >= priv->hw_params.tx_chains_num ? 0 : ind+1;
- if (priv->hw_params.valid_tx_ant & (1 << ind)) {
- priv->scan_tx_ant[band] = ind;
- break;
- }
- }
- IWL_DEBUG_SCAN("select TX ANT = %c\n", 'A' + ind);
- return scan_tx_ant[ind];
-}
-
-
static void iwl_bg_request_scan(struct work_struct *data)
{
struct iwl_priv *priv =
@@ -699,11 +637,13 @@ static void iwl_bg_request_scan(struct work_struct *data)
struct iwl_scan_cmd *scan;
struct ieee80211_conf *conf = NULL;
int ret = 0;
- u32 tx_ant;
+ u32 rate_flags = 0;
u16 cmd_len;
enum ieee80211_band band;
u8 n_probes = 2;
u8 rx_chain = priv->hw_params.valid_rx_ant;
+ u8 rate;
+ DECLARE_SSID_BUF(ssid);
conf = ieee80211_get_hw_conf(priv->hw);
@@ -714,7 +654,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
goto done;
}
- /* Make sure the scan wasn't cancelled before this queued work
+ /* Make sure the scan wasn't canceled before this queued work
* was given the chance to run... */
if (!test_bit(STATUS_SCANNING, &priv->status))
goto done;
@@ -796,20 +736,13 @@ static void iwl_bg_request_scan(struct work_struct *data)
/* We should add the ability for user to lock to PASSIVE ONLY */
if (priv->one_direct_scan) {
IWL_DEBUG_SCAN("Start direct scan for '%s'\n",
- iwl_escape_essid(priv->direct_ssid,
- priv->direct_ssid_len));
+ print_ssid(ssid, priv->direct_ssid,
+ priv->direct_ssid_len));
scan->direct_scan[0].id = WLAN_EID_SSID;
scan->direct_scan[0].len = priv->direct_ssid_len;
memcpy(scan->direct_scan[0].ssid,
priv->direct_ssid, priv->direct_ssid_len);
n_probes++;
- } else if (!iwl_is_associated(priv) && priv->essid_len) {
- IWL_DEBUG_SCAN("Start direct scan for '%s' (not associated)\n",
- iwl_escape_essid(priv->essid, priv->essid_len));
- scan->direct_scan[0].id = WLAN_EID_SSID;
- scan->direct_scan[0].len = priv->essid_len;
- memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
- n_probes++;
} else {
IWL_DEBUG_SCAN("Start indirect scan.\n");
}
@@ -822,23 +755,16 @@ static void iwl_bg_request_scan(struct work_struct *data)
if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {
band = IEEE80211_BAND_2GHZ;
scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
- tx_ant = iwl_scan_tx_ant(priv, band);
- if (priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK)
- scan->tx_cmd.rate_n_flags =
- iwl_hw_set_rate_n_flags(IWL_RATE_6M_PLCP,
- tx_ant);
- else
- scan->tx_cmd.rate_n_flags =
- iwl_hw_set_rate_n_flags(IWL_RATE_1M_PLCP,
- tx_ant |
- RATE_MCS_CCK_MSK);
+ if (priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) {
+ rate = IWL_RATE_6M_PLCP;
+ } else {
+ rate = IWL_RATE_1M_PLCP;
+ rate_flags = RATE_MCS_CCK_MSK;
+ }
scan->good_CRC_th = 0;
} else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
band = IEEE80211_BAND_5GHZ;
- tx_ant = iwl_scan_tx_ant(priv, band);
- scan->tx_cmd.rate_n_flags =
- iwl_hw_set_rate_n_flags(IWL_RATE_6M_PLCP,
- tx_ant);
+ rate = IWL_RATE_6M_PLCP;
scan->good_CRC_th = IWL_GOOD_CRC_TH;
/* Force use of chains B and C (0x6) for scan Rx for 4965
@@ -851,6 +777,11 @@ static void iwl_bg_request_scan(struct work_struct *data)
goto done;
}
+ priv->scan_tx_ant[band] =
+ iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]);
+ rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]);
+ scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
+
/* MIMO is not used here, but value is required */
scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK |
cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.c b/drivers/net/wireless/iwlwifi/iwl-spectrum.c
new file mode 100644
index 000000000000..836c3c80b69e
--- /dev/null
+++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.c
@@ -0,0 +1,198 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2008 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project, as well
+ * as portions of the ieee80211 subsystem header files.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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, USA
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called LICENSE.
+ *
+ * Contact Information:
+ * Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+
+#include <net/mac80211.h>
+
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-spectrum.h"
+
+#define BEACON_TIME_MASK_LOW 0x00FFFFFF
+#define BEACON_TIME_MASK_HIGH 0xFF000000
+#define TIME_UNIT 1024
+
+/*
+ * extended beacon time format
+ * time in usec will be changed into a 32-bit value in 8:24 format
+ * the high 1 byte is the beacon counts
+ * the lower 3 bytes is the time in usec within one beacon interval
+ */
+
+/* TOOD: was used in sysfs debug interface need to add to mac */
+#if 0
+static u32 iwl_usecs_to_beacons(u32 usec, u32 beacon_interval)
+{
+ u32 quot;
+ u32 rem;
+ u32 interval = beacon_interval * 1024;
+
+ if (!interval || !usec)
+ return 0;
+
+ quot = (usec / interval) & (BEACON_TIME_MASK_HIGH >> 24);
+ rem = (usec % interval) & BEACON_TIME_MASK_LOW;
+
+ return (quot << 24) + rem;
+}
+
+/* base is usually what we get from ucode with each received frame,
+ * the same as HW timer counter counting down
+ */
+
+static __le32 iwl_add_beacon_time(u32 base, u32 addon, u32 beacon_interval)
+{
+ u32 base_low = base & BEACON_TIME_MASK_LOW;
+ u32 addon_low = addon & BEACON_TIME_MASK_LOW;
+ u32 interval = beacon_interval * TIME_UNIT;
+ u32 res = (base & BEACON_TIME_MASK_HIGH) +
+ (addon & BEACON_TIME_MASK_HIGH);
+
+ if (base_low > addon_low)
+ res += base_low - addon_low;
+ else if (base_low < addon_low) {
+ res += interval + base_low - addon_low;
+ res += (1 << 24);
+ } else
+ res += (1 << 24);
+
+ return cpu_to_le32(res);
+}
+static int iwl_get_measurement(struct iwl_priv *priv,
+ struct ieee80211_measurement_params *params,
+ u8 type)
+{
+ struct iwl4965_spectrum_cmd spectrum;
+ struct iwl_rx_packet *res;
+ struct iwl_host_cmd cmd = {
+ .id = REPLY_SPECTRUM_MEASUREMENT_CMD,
+ .data = (void *)&spectrum,
+ .meta.flags = CMD_WANT_SKB,
+ };
+ u32 add_time = le64_to_cpu(params->start_time);
+ int rc;
+ int spectrum_resp_status;
+ int duration = le16_to_cpu(params->duration);
+
+ if (iwl_is_associated(priv))
+ add_time =
+ iwl_usecs_to_beacons(
+ le64_to_cpu(params->start_time) - priv->last_tsf,
+ le16_to_cpu(priv->rxon_timing.beacon_interval));
+
+ memset(&spectrum, 0, sizeof(spectrum));
+
+ spectrum.channel_count = cpu_to_le16(1);
+ spectrum.flags =
+ RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK;
+ spectrum.filter_flags = MEASUREMENT_FILTER_FLAG;
+ cmd.len = sizeof(spectrum);
+ spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
+
+ if (iwl_is_associated(priv))
+ spectrum.start_time =
+ iwl_add_beacon_time(priv->last_beacon_time,
+ add_time,
+ le16_to_cpu(priv->rxon_timing.beacon_interval));
+ else
+ spectrum.start_time = 0;
+
+ spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT);
+ spectrum.channels[0].channel = params->channel;
+ spectrum.channels[0].type = type;
+ if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK)
+ spectrum.flags |= RXON_FLG_BAND_24G_MSK |
+ RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
+
+ rc = iwl_send_cmd_sync(priv, &cmd);
+ if (rc)
+ return rc;
+
+ res = (struct iwl_rx_packet *)cmd.meta.u.skb->data;
+ if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
+ IWL_ERROR("Bad return from REPLY_RX_ON_ASSOC command\n");
+ rc = -EIO;
+ }
+
+ spectrum_resp_status = le16_to_cpu(res->u.spectrum.status);
+ switch (spectrum_resp_status) {
+ case 0: /* Command will be handled */
+ if (res->u.spectrum.id != 0xff) {
+ IWL_DEBUG_INFO
+ ("Replaced existing measurement: %d\n",
+ res->u.spectrum.id);
+ priv->measurement_status &= ~MEASUREMENT_READY;
+ }
+ priv->measurement_status |= MEASUREMENT_ACTIVE;
+ rc = 0;
+ break;
+
+ case 1: /* Command will not be handled */
+ rc = -EAGAIN;
+ break;
+ }
+
+ dev_kfree_skb_any(cmd.meta.u.skb);
+
+ return rc;
+}
+#endif
+
+static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
+ struct iwl_rx_mem_buffer *rxb)
+{
+ struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
+ struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
+
+ if (!report->state) {
+ IWL_DEBUG(IWL_DL_11H,
+ "Spectrum Measure Notification: Start\n");
+ return;
+ }
+
+ memcpy(&priv->measure_report, report, sizeof(*report));
+ priv->measurement_status |= MEASUREMENT_READY;
+}
+
+void iwl_setup_spectrum_handlers(struct iwl_priv *priv)
+{
+ priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
+ iwl_rx_spectrum_measure_notif;
+}
+EXPORT_SYMBOL(iwl_setup_spectrum_handlers);
diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.h b/drivers/net/wireless/iwlwifi/iwl-spectrum.h
index a40a2174df98..b7d7943e476b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-spectrum.h
+++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.h
@@ -21,7 +21,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -88,4 +88,5 @@ struct ieee80211_measurement_report {
struct ieee80211_basic_report basic[0];
} u;
} __attribute__ ((packed));
+
#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index 26f7084d3011..412f66bac1af 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -33,8 +33,6 @@
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-sta.h"
-#include "iwl-helpers.h"
-
#define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */
#define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */
@@ -45,7 +43,6 @@ u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
int start = 0;
int ret = IWL_INVALID_STATION;
unsigned long flags;
- DECLARE_MAC_BUF(mac);
if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) ||
(priv->iw_mode == NL80211_IFTYPE_AP))
@@ -63,8 +60,8 @@ u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
goto out;
}
- IWL_DEBUG_ASSOC_LIMIT("can not find STA %s total %d\n",
- print_mac(mac, addr), priv->num_stations);
+ IWL_DEBUG_ASSOC_LIMIT("can not find STA %pM total %d\n",
+ addr, priv->num_stations);
out:
spin_unlock_irqrestore(&priv->sta_lock, flags);
@@ -86,7 +83,6 @@ EXPORT_SYMBOL(iwl_get_ra_sta_id);
static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
{
unsigned long flags;
- DECLARE_MAC_BUF(mac);
spin_lock_irqsave(&priv->sta_lock, flags);
@@ -94,8 +90,8 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
IWL_ERROR("ACTIVATE a non DRIVER active station %d\n", sta_id);
priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE;
- IWL_DEBUG_ASSOC("Added STA to Ucode: %s\n",
- print_mac(mac, priv->stations[sta_id].sta.sta.addr));
+ IWL_DEBUG_ASSOC("Added STA to Ucode: %pM\n",
+ priv->stations[sta_id].sta.sta.addr);
spin_unlock_irqrestore(&priv->sta_lock, flags);
}
@@ -104,7 +100,9 @@ static int iwl_add_sta_callback(struct iwl_priv *priv,
struct iwl_cmd *cmd, struct sk_buff *skb)
{
struct iwl_rx_packet *res = NULL;
- u8 sta_id = cmd->cmd.addsta.sta.sta_id;
+ struct iwl_addsta_cmd *addsta =
+ (struct iwl_addsta_cmd *)cmd->cmd.payload;
+ u8 sta_id = addsta->sta.sta_id;
if (!skb) {
IWL_ERROR("Error: Response NULL in REPLY_ADD_STA.\n");
@@ -132,7 +130,7 @@ static int iwl_add_sta_callback(struct iwl_priv *priv,
return 1;
}
-int iwl_send_add_sta(struct iwl_priv *priv,
+static int iwl_send_add_sta(struct iwl_priv *priv,
struct iwl_addsta_cmd *sta, u8 flags)
{
struct iwl_rx_packet *res = NULL;
@@ -180,10 +178,9 @@ int iwl_send_add_sta(struct iwl_priv *priv,
return ret;
}
-EXPORT_SYMBOL(iwl_send_add_sta);
static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
- struct ieee80211_ht_info *sta_ht_inf)
+ struct ieee80211_sta_ht_cap *sta_ht_inf)
{
__le32 sta_flags;
u8 mimo_ps_mode;
@@ -231,13 +228,12 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
* iwl_add_station_flags - Add station to tables in driver and device
*/
u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap,
- u8 flags, struct ieee80211_ht_info *ht_info)
+ u8 flags, struct ieee80211_sta_ht_cap *ht_info)
{
int i;
int sta_id = IWL_INVALID_STATION;
struct iwl_station_entry *station;
unsigned long flags_spin;
- DECLARE_MAC_BUF(mac);
spin_lock_irqsave(&priv->sta_lock, flags_spin);
if (is_ap)
@@ -273,8 +269,8 @@ u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr, int is_ap,
station = &priv->stations[sta_id];
station->used = IWL_STA_DRIVER_ACTIVE;
- IWL_DEBUG_ASSOC("Add STA to driver ID %d: %s\n",
- sta_id, print_mac(mac, addr));
+ IWL_DEBUG_ASSOC("Add STA to driver ID %d: %pM\n",
+ sta_id, addr);
priv->num_stations++;
/* Set up the REPLY_ADD_STA command to send to device */
@@ -301,14 +297,11 @@ EXPORT_SYMBOL(iwl_add_station_flags);
static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr)
{
unsigned long flags;
- DECLARE_MAC_BUF(mac);
-
u8 sta_id = iwl_find_station(priv, addr);
BUG_ON(sta_id == IWL_INVALID_STATION);
- IWL_DEBUG_ASSOC("Removed STA from Ucode: %s\n",
- print_mac(mac, addr));
+ IWL_DEBUG_ASSOC("Removed STA from Ucode: %pM\n", addr);
spin_lock_irqsave(&priv->sta_lock, flags);
@@ -326,7 +319,9 @@ static int iwl_remove_sta_callback(struct iwl_priv *priv,
struct iwl_cmd *cmd, struct sk_buff *skb)
{
struct iwl_rx_packet *res = NULL;
- const char *addr = cmd->cmd.rm_sta.addr;
+ struct iwl_rem_sta_cmd *rm_sta =
+ (struct iwl_rem_sta_cmd *)cmd->cmd.payload;
+ const char *addr = rm_sta->addr;
if (!skb) {
IWL_ERROR("Error: Response NULL in REPLY_REMOVE_STA.\n");
@@ -415,7 +410,6 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
int sta_id = IWL_INVALID_STATION;
int i, ret = -EINVAL;
unsigned long flags;
- DECLARE_MAC_BUF(mac);
spin_lock_irqsave(&priv->sta_lock, flags);
@@ -435,18 +429,18 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
if (unlikely(sta_id == IWL_INVALID_STATION))
goto out;
- IWL_DEBUG_ASSOC("Removing STA from driver:%d %s\n",
- sta_id, print_mac(mac, addr));
+ IWL_DEBUG_ASSOC("Removing STA from driver:%d %pM\n",
+ sta_id, addr);
if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
- IWL_ERROR("Removing %s but non DRIVER active\n",
- print_mac(mac, addr));
+ IWL_ERROR("Removing %pM but non DRIVER active\n",
+ addr);
goto out;
}
if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
- IWL_ERROR("Removing %s but non UCODE active\n",
- print_mac(mac, addr));
+ IWL_ERROR("Removing %pM but non UCODE active\n",
+ addr);
goto out;
}
@@ -467,6 +461,29 @@ out:
}
EXPORT_SYMBOL(iwl_remove_station);
+/**
+ * iwl_clear_stations_table - Clear the driver's station table
+ *
+ * NOTE: This does not clear or otherwise alter the device's station table.
+ */
+void iwl_clear_stations_table(struct iwl_priv *priv)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+
+ if (iwl_is_alive(priv) &&
+ !test_bit(STATUS_EXIT_PENDING, &priv->status) &&
+ iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL))
+ IWL_ERROR("Couldn't clear the station table\n");
+
+ priv->num_stations = 0;
+ memset(priv->stations, 0, sizeof(priv->stations));
+
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+}
+EXPORT_SYMBOL(iwl_clear_stations_table);
+
static int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
{
int i;
@@ -717,6 +734,55 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv,
return ret;
}
+void iwl_update_tkip_key(struct iwl_priv *priv,
+ struct ieee80211_key_conf *keyconf,
+ const u8 *addr, u32 iv32, u16 *phase1key)
+{
+ u8 sta_id = IWL_INVALID_STATION;
+ unsigned long flags;
+ __le16 key_flags = 0;
+ int i;
+ DECLARE_MAC_BUF(mac);
+
+ sta_id = iwl_find_station(priv, addr);
+ if (sta_id == IWL_INVALID_STATION) {
+ IWL_DEBUG_MAC80211("leave - %pM not in station map.\n",
+ addr);
+ return;
+ }
+
+ if (iwl_scan_cancel(priv)) {
+ /* cancel scan failed, just live w/ bad key and rely
+ briefly on SW decryption */
+ return;
+ }
+
+ key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
+ key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+ key_flags &= ~STA_KEY_FLG_INVALID;
+
+ if (sta_id == priv->hw_params.bcast_sta_id)
+ key_flags |= STA_KEY_MULTICAST_MSK;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+
+ priv->stations[sta_id].sta.key.key_flags = key_flags;
+ priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
+
+ for (i = 0; i < 5; i++)
+ priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
+ cpu_to_le16(phase1key[i]);
+
+ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+ iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+}
+EXPORT_SYMBOL(iwl_update_tkip_key);
+
int iwl_remove_dynamic_key(struct iwl_priv *priv,
struct ieee80211_key_conf *keyconf,
u8 sta_id)
@@ -809,7 +875,7 @@ static void iwl_dump_lq_cmd(struct iwl_priv *priv,
{
int i;
IWL_DEBUG_RATE("lq station id 0x%x\n", lq->sta_id);
- IWL_DEBUG_RATE("lq dta 0x%X 0x%X\n",
+ IWL_DEBUG_RATE("lq ant 0x%X 0x%X\n",
lq->general_params.single_stream_ant_msk,
lq->general_params.dual_stream_ant_msk);
@@ -870,7 +936,7 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, int is_ap)
struct iwl_link_quality_cmd link_cmd = {
.reserved1 = 0,
};
- u16 rate_flags;
+ u32 rate_flags;
/* Set up the rate scaling to start at selected rate, fall back
* all the way down to 1M in IEEE order, and then spin on 1M */
@@ -886,15 +952,16 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, int is_ap)
if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
rate_flags |= RATE_MCS_CCK_MSK;
- /* Use Tx antenna B only */
- rate_flags |= RATE_MCS_ANT_B_MSK; /*FIXME:RS*/
+ rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) <<
+ RATE_MCS_ANT_POS;
link_cmd.rs_table[i].rate_n_flags =
iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
- r = iwl4965_get_prev_ieee_rate(r);
+ r = iwl_get_prev_ieee_rate(r);
}
- link_cmd.general_params.single_stream_ant_msk = 2;
+ link_cmd.general_params.single_stream_ant_msk =
+ first_antenna(priv->hw_params.valid_tx_ant);
link_cmd.general_params.dual_stream_ant_msk = 3;
link_cmd.agg_params.agg_dis_start_th = 3;
link_cmd.agg_params.agg_time_limit = cpu_to_le16(4000);
@@ -910,24 +977,35 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, int is_ap)
* iwl_rxon_add_station - add station into station table.
*
* there is only one AP station with id= IWL_AP_ID
- * NOTE: mutex must be held before calling this fnction
+ * NOTE: mutex must be held before calling this function
*/
int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
{
+ struct ieee80211_sta *sta;
+ struct ieee80211_sta_ht_cap ht_config;
+ struct ieee80211_sta_ht_cap *cur_ht_config = NULL;
u8 sta_id;
/* Add station to device's station table */
- struct ieee80211_conf *conf = &priv->hw->conf;
- struct ieee80211_ht_info *cur_ht_config = &conf->ht_conf;
-
- if ((is_ap) &&
- (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) &&
- (priv->iw_mode == NL80211_IFTYPE_STATION))
- sta_id = iwl_add_station_flags(priv, addr, is_ap,
- 0, cur_ht_config);
- else
- sta_id = iwl_add_station_flags(priv, addr, is_ap,
- 0, NULL);
+
+ /*
+ * XXX: This check is definitely not correct, if we're an AP
+ * it'll always be false which is not what we want, but
+ * it doesn't look like iwlagn is prepared to be an HT
+ * AP anyway.
+ */
+ if (priv->current_ht_config.is_ht) {
+ rcu_read_lock();
+ sta = ieee80211_find_sta(priv->hw, addr);
+ if (sta) {
+ memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config));
+ cur_ht_config = &ht_config;
+ }
+ rcu_read_unlock();
+ }
+
+ sta_id = iwl_add_station_flags(priv, addr, is_ap,
+ 0, cur_ht_config);
/* Set up default rate scaling table in device's station table */
iwl_sta_init_lq(priv, addr, is_ap);
@@ -945,7 +1023,6 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
{
int sta_id;
u16 fc = le16_to_cpu(hdr->frame_control);
- DECLARE_MAC_BUF(mac);
/* If this frame is broadcast or management, use broadcast station id */
if (((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA) ||
@@ -980,9 +1057,9 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
if (sta_id != IWL_INVALID_STATION)
return sta_id;
- IWL_DEBUG_DROP("Station %s not in station map. "
+ IWL_DEBUG_DROP("Station %pM not in station map. "
"Defaulting to broadcast...\n",
- print_mac(mac, hdr->addr1));
+ hdr->addr1);
iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
return priv->hw_params.bcast_sta_id;
@@ -999,9 +1076,9 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
EXPORT_SYMBOL(iwl_get_sta_id);
/**
- * iwl_sta_modify_enable_tid_tx - Enable Tx for this TID in station table
+ * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
*/
-void iwl_sta_modify_enable_tid_tx(struct iwl_priv *priv, int sta_id, int tid)
+void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
{
unsigned long flags;
@@ -1014,5 +1091,81 @@ void iwl_sta_modify_enable_tid_tx(struct iwl_priv *priv, int sta_id, int tid)
iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
}
-EXPORT_SYMBOL(iwl_sta_modify_enable_tid_tx);
+EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid);
+
+int iwl_sta_rx_agg_start(struct iwl_priv *priv,
+ const u8 *addr, int tid, u16 ssn)
+{
+ unsigned long flags;
+ int sta_id;
+
+ sta_id = iwl_find_station(priv, addr);
+ if (sta_id == IWL_INVALID_STATION)
+ return -ENXIO;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ priv->stations[sta_id].sta.station_flags_msk = 0;
+ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
+ priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
+ priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return iwl_send_add_sta(priv, &priv->stations[sta_id].sta,
+ CMD_ASYNC);
+}
+EXPORT_SYMBOL(iwl_sta_rx_agg_start);
+
+int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid)
+{
+ unsigned long flags;
+ int sta_id;
+
+ sta_id = iwl_find_station(priv, addr);
+ if (sta_id == IWL_INVALID_STATION)
+ return -ENXIO;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ priv->stations[sta_id].sta.station_flags_msk = 0;
+ priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
+ priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ return iwl_send_add_sta(priv, &priv->stations[sta_id].sta,
+ CMD_ASYNC);
+}
+EXPORT_SYMBOL(iwl_sta_rx_agg_stop);
+
+static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->sta_lock, flags);
+ priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK;
+ priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
+ priv->stations[sta_id].sta.sta.modify_mask = 0;
+ priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+ spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+ iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+}
+
+void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr)
+{
+ /* FIXME: need locking over ps_status ??? */
+ u8 sta_id = iwl_find_station(priv, addr);
+
+ if (sta_id != IWL_INVALID_STATION) {
+ u8 sta_awake = priv->stations[sta_id].
+ ps_status == STA_PS_STATUS_WAKE;
+
+ if (sta_awake && ps_bit)
+ priv->stations[sta_id].ps_status = STA_PS_STATUS_SLEEP;
+ else if (!sta_awake && !ps_bit) {
+ iwl_sta_modify_ps_wake(priv, sta_id);
+ priv->stations[sta_id].ps_status = STA_PS_STATUS_WAKE;
+ }
+ }
+}
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index 221b93e670a6..9bb7cefc1f3c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -47,9 +47,21 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
struct ieee80211_key_conf *key, u8 sta_id);
int iwl_remove_dynamic_key(struct iwl_priv *priv,
struct ieee80211_key_conf *key, u8 sta_id);
+void iwl_update_tkip_key(struct iwl_priv *priv,
+ struct ieee80211_key_conf *keyconf,
+ const u8 *addr, u32 iv32, u16 *phase1key);
+
int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap);
int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, int is_ap);
+void iwl_clear_stations_table(struct iwl_priv *priv);
int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr);
-void iwl_sta_modify_enable_tid_tx(struct iwl_priv *priv, int sta_id, int tid);
int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr);
+u8 iwl_add_station_flags(struct iwl_priv *priv, const u8 *addr,
+ int is_ap, u8 flags,
+ struct ieee80211_sta_ht_cap *ht_info);
+void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
+int iwl_sta_rx_agg_start(struct iwl_priv *priv,
+ const u8 *addr, int tid, u16 ssn);
+int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid);
+void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr);
#endif /* __iwl_sta_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 907a53ebc6e4..b0ee86c62685 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -56,96 +56,132 @@ static const u16 default_tid_to_tx_fifo[] = {
IWL_TX_FIFO_AC3
};
+static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv,
+ struct iwl_dma_ptr *ptr, size_t size)
+{
+ ptr->addr = pci_alloc_consistent(priv->pci_dev, size, &ptr->dma);
+ if (!ptr->addr)
+ return -ENOMEM;
+ ptr->size = size;
+ return 0;
+}
+
+static inline void iwl_free_dma_ptr(struct iwl_priv *priv,
+ struct iwl_dma_ptr *ptr)
+{
+ if (unlikely(!ptr->addr))
+ return;
+
+ pci_free_consistent(priv->pci_dev, ptr->size, ptr->addr, ptr->dma);
+ memset(ptr, 0, sizeof(*ptr));
+}
+
+static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
+{
+ struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+
+ dma_addr_t addr = get_unaligned_le32(&tb->lo);
+ if (sizeof(dma_addr_t) > sizeof(u32))
+ addr |=
+ ((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16;
+
+ return addr;
+}
+
+static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
+{
+ struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+
+ return le16_to_cpu(tb->hi_n_len) >> 4;
+}
+
+static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
+ dma_addr_t addr, u16 len)
+{
+ struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+ u16 hi_n_len = len << 4;
+
+ put_unaligned_le32(addr, &tb->lo);
+ if (sizeof(dma_addr_t) > sizeof(u32))
+ hi_n_len |= ((addr >> 16) >> 16) & 0xF;
+
+ tb->hi_n_len = cpu_to_le16(hi_n_len);
+
+ tfd->num_tbs = idx + 1;
+}
+
+static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd)
+{
+ return tfd->num_tbs & 0x1f;
+}
/**
* iwl_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
+ * @priv - driver private data
+ * @txq - tx queue
*
* Does NOT advance any TFD circular buffer read/write indexes
* Does NOT free the TFD itself (which is within circular buffer)
*/
-static int iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+static void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
{
- struct iwl_tfd_frame *bd_tmp = (struct iwl_tfd_frame *)&txq->bd[0];
- struct iwl_tfd_frame *bd = &bd_tmp[txq->q.read_ptr];
+ struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)&txq->tfds[0];
+ struct iwl_tfd *tfd;
struct pci_dev *dev = priv->pci_dev;
+ int index = txq->q.read_ptr;
int i;
- int counter = 0;
- int index, is_odd;
+ int num_tbs;
- /* Host command buffers stay mapped in memory, nothing to clean */
- if (txq->q.id == IWL_CMD_QUEUE_NUM)
- return 0;
+ tfd = &tfd_tmp[index];
/* Sanity check on number of chunks */
- counter = IWL_GET_BITS(*bd, num_tbs);
- if (counter > MAX_NUM_OF_TBS) {
- IWL_ERROR("Too many chunks: %i\n", counter);
+ num_tbs = iwl_tfd_get_num_tbs(tfd);
+
+ if (num_tbs >= IWL_NUM_OF_TBS) {
+ IWL_ERROR("Too many chunks: %i\n", num_tbs);
/* @todo issue fatal error, it is quite serious situation */
- return 0;
+ return;
}
- /* Unmap chunks, if any.
- * TFD info for odd chunks is different format than for even chunks. */
- for (i = 0; i < counter; i++) {
- index = i / 2;
- is_odd = i & 0x1;
-
- if (is_odd)
- pci_unmap_single(
- dev,
- IWL_GET_BITS(bd->pa[index], tb2_addr_lo16) |
- (IWL_GET_BITS(bd->pa[index],
- tb2_addr_hi20) << 16),
- IWL_GET_BITS(bd->pa[index], tb2_len),
+ /* Unmap tx_cmd */
+ if (num_tbs)
+ pci_unmap_single(dev,
+ pci_unmap_addr(&txq->cmd[index]->meta, mapping),
+ pci_unmap_len(&txq->cmd[index]->meta, len),
PCI_DMA_TODEVICE);
- else if (i > 0)
- pci_unmap_single(dev,
- le32_to_cpu(bd->pa[index].tb1_addr),
- IWL_GET_BITS(bd->pa[index], tb1_len),
- PCI_DMA_TODEVICE);
+ /* Unmap chunks, if any. */
+ for (i = 1; i < num_tbs; i++) {
+ pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i),
+ iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE);
- /* Free SKB, if any, for this chunk */
- if (txq->txb[txq->q.read_ptr].skb[i]) {
- struct sk_buff *skb = txq->txb[txq->q.read_ptr].skb[i];
-
- dev_kfree_skb(skb);
- txq->txb[txq->q.read_ptr].skb[i] = NULL;
+ if (txq->txb) {
+ dev_kfree_skb(txq->txb[txq->q.read_ptr].skb[i - 1]);
+ txq->txb[txq->q.read_ptr].skb[i - 1] = NULL;
}
}
- return 0;
}
-static int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, void *ptr,
- dma_addr_t addr, u16 len)
+static int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
+ struct iwl_tfd *tfd,
+ dma_addr_t addr, u16 len)
{
- int index, is_odd;
- struct iwl_tfd_frame *tfd = ptr;
- u32 num_tbs = IWL_GET_BITS(*tfd, num_tbs);
+
+ u32 num_tbs = iwl_tfd_get_num_tbs(tfd);
/* Each TFD can point to a maximum 20 Tx buffers */
- if (num_tbs >= MAX_NUM_OF_TBS) {
+ if (num_tbs >= IWL_NUM_OF_TBS) {
IWL_ERROR("Error can not send more than %d chunks\n",
- MAX_NUM_OF_TBS);
+ IWL_NUM_OF_TBS);
return -EINVAL;
}
- index = num_tbs / 2;
- is_odd = num_tbs & 0x1;
-
- if (!is_odd) {
- tfd->pa[index].tb1_addr = cpu_to_le32(addr);
- IWL_SET_BITS(tfd->pa[index], tb1_addr_hi,
- iwl_get_dma_hi_address(addr));
- IWL_SET_BITS(tfd->pa[index], tb1_len, len);
- } else {
- IWL_SET_BITS(tfd->pa[index], tb2_addr_lo16,
- (u32) (addr & 0xffff));
- IWL_SET_BITS(tfd->pa[index], tb2_addr_hi20, addr >> 16);
- IWL_SET_BITS(tfd->pa[index], tb2_len, len);
- }
+ BUG_ON(addr & ~DMA_BIT_MASK(36));
+ if (unlikely(addr & ~IWL_TX_DMA_MASK))
+ IWL_ERROR("Unaligned address = %llx\n",
+ (unsigned long long)addr);
- IWL_SET_BITS(*tfd, num_tbs, num_tbs + 1);
+ iwl_tfd_set_tb(tfd, num_tbs, addr, len);
return 0;
}
@@ -210,7 +246,7 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
struct iwl_tx_queue *txq = &priv->txq[txq_id];
struct iwl_queue *q = &txq->q;
struct pci_dev *dev = priv->pci_dev;
- int i, slots_num, len;
+ int i, len;
if (q->n_bd == 0)
return;
@@ -221,21 +257,15 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
iwl_hw_txq_free_tfd(priv, txq);
len = sizeof(struct iwl_cmd) * q->n_window;
- if (q->id == IWL_CMD_QUEUE_NUM)
- len += IWL_MAX_SCAN_SIZE;
/* De-alloc array of command/tx buffers */
- slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
- TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
- for (i = 0; i < slots_num; i++)
+ for (i = 0; i < TFD_TX_CMD_SLOTS; i++)
kfree(txq->cmd[i]);
- if (txq_id == IWL_CMD_QUEUE_NUM)
- kfree(txq->cmd[slots_num]);
/* De-alloc circular buffer of TFDs */
if (txq->q.n_bd)
- pci_free_consistent(dev, sizeof(struct iwl_tfd_frame) *
- txq->q.n_bd, txq->bd, txq->q.dma_addr);
+ pci_free_consistent(dev, sizeof(struct iwl_tfd) *
+ txq->q.n_bd, txq->tfds, txq->q.dma_addr);
/* De-alloc array of per-TFD driver data */
kfree(txq->txb);
@@ -245,6 +275,40 @@ static void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
memset(txq, 0, sizeof(*txq));
}
+
+/**
+ * iwl_cmd_queue_free - Deallocate DMA queue.
+ * @txq: Transmit queue to deallocate.
+ *
+ * Empty queue by removing and destroying all BD's.
+ * Free all buffers.
+ * 0-fill, but do not free "txq" descriptor structure.
+ */
+static void iwl_cmd_queue_free(struct iwl_priv *priv)
+{
+ struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
+ struct iwl_queue *q = &txq->q;
+ struct pci_dev *dev = priv->pci_dev;
+ int i, len;
+
+ if (q->n_bd == 0)
+ return;
+
+ len = sizeof(struct iwl_cmd) * q->n_window;
+ len += IWL_MAX_SCAN_SIZE;
+
+ /* De-alloc array of command/tx buffers */
+ for (i = 0; i <= TFD_CMD_SLOTS; i++)
+ kfree(txq->cmd[i]);
+
+ /* De-alloc circular buffer of TFDs */
+ if (txq->q.n_bd)
+ pci_free_consistent(dev, sizeof(struct iwl_tfd) *
+ txq->q.n_bd, txq->tfds, txq->q.dma_addr);
+
+ /* 0-fill queue descriptor structure */
+ memset(txq, 0, sizeof(*txq));
+}
/*************** DMA-QUEUE-GENERAL-FUNCTIONS *****
* DMA services
*
@@ -340,13 +404,13 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv,
/* Circular buffer of transmit frame descriptors (TFDs),
* shared with device */
- txq->bd = pci_alloc_consistent(dev,
- sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX,
+ txq->tfds = pci_alloc_consistent(dev,
+ sizeof(txq->tfds[0]) * TFD_QUEUE_SIZE_MAX,
&txq->q.dma_addr);
- if (!txq->bd) {
+ if (!txq->tfds) {
IWL_ERROR("pci_alloc_consistent(%zd) failed\n",
- sizeof(txq->bd[0]) * TFD_QUEUE_SIZE_MAX);
+ sizeof(txq->tfds[0]) * TFD_QUEUE_SIZE_MAX);
goto error;
}
txq->q.id = id;
@@ -370,26 +434,21 @@ static int iwl_tx_queue_alloc(struct iwl_priv *priv,
static int iwl_hw_tx_queue_init(struct iwl_priv *priv,
struct iwl_tx_queue *txq)
{
- int rc;
+ int ret;
unsigned long flags;
int txq_id = txq->q.id;
spin_lock_irqsave(&priv->lock, flags);
- rc = iwl_grab_nic_access(priv);
- if (rc) {
+ ret = iwl_grab_nic_access(priv);
+ if (ret) {
spin_unlock_irqrestore(&priv->lock, flags);
- return rc;
+ return ret;
}
/* Circular buffer (TFD queue in DRAM) physical base address */
iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
txq->q.dma_addr >> 8);
- /* Enable DMA channel, using same id as for TFD queue */
- iwl_write_direct32(
- priv, FH_TCSR_CHNL_TX_CONFIG_REG(txq_id),
- FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
- FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL);
iwl_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -468,16 +527,20 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
/* Tx queues */
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
- iwl_tx_queue_free(priv, txq_id);
+ if (txq_id == IWL_CMD_QUEUE_NUM)
+ iwl_cmd_queue_free(priv);
+ else
+ iwl_tx_queue_free(priv, txq_id);
- /* Keep-warm buffer */
- iwl_kw_free(priv);
+ iwl_free_dma_ptr(priv, &priv->kw);
+
+ iwl_free_dma_ptr(priv, &priv->scd_bc_tbls);
}
EXPORT_SYMBOL(iwl_hw_txq_ctx_free);
/**
* iwl_txq_ctx_reset - Reset TX queue context
- * Destroys all DMA structures and initialise them again
+ * Destroys all DMA structures and initialize them again
*
* @param priv
* @return error code
@@ -488,13 +551,17 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
int txq_id, slots_num;
unsigned long flags;
- iwl_kw_free(priv);
-
/* Free all tx/cmd queues and keep-warm buffer */
iwl_hw_txq_ctx_free(priv);
+ ret = iwl_alloc_dma_ptr(priv, &priv->scd_bc_tbls,
+ priv->hw_params.scd_bc_tbls_size);
+ if (ret) {
+ IWL_ERROR("Scheduler BC Table allocation failed\n");
+ goto error_bc_tbls;
+ }
/* Alloc keep-warm buffer */
- ret = iwl_kw_alloc(priv);
+ ret = iwl_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE);
if (ret) {
IWL_ERROR("Keep Warm allocation failed\n");
goto error_kw;
@@ -509,17 +576,12 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
/* Turn off all Tx DMA fifos */
priv->cfg->ops->lib->txq_set_sched(priv, 0);
+ /* Tell NIC where to find the "keep warm" buffer */
+ iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
+
iwl_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
-
- /* Tell nic where to find the keep-warm buffer */
- ret = iwl_kw_init(priv);
- if (ret) {
- IWL_ERROR("kw_init failed\n");
- goto error_reset;
- }
-
/* Alloc and init all Tx queues, including the command queue (#4) */
for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ?
@@ -537,8 +599,10 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
error:
iwl_hw_txq_ctx_free(priv);
error_reset:
- iwl_kw_free(priv);
+ iwl_free_dma_ptr(priv, &priv->kw);
error_kw:
+ iwl_free_dma_ptr(priv, &priv->scd_bc_tbls);
+ error_bc_tbls:
return ret;
}
@@ -547,11 +611,9 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
*/
void iwl_txq_ctx_stop(struct iwl_priv *priv)
{
-
- int txq_id;
+ int ch;
unsigned long flags;
-
/* Turn off all Tx DMA fifos */
spin_lock_irqsave(&priv->lock, flags);
if (iwl_grab_nic_access(priv)) {
@@ -562,12 +624,11 @@ void iwl_txq_ctx_stop(struct iwl_priv *priv)
priv->cfg->ops->lib->txq_set_sched(priv, 0);
/* Stop each Tx DMA channel, and wait for it to be idle */
- for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
- iwl_write_direct32(priv,
- FH_TCSR_CHNL_TX_CONFIG_REG(txq_id), 0x0);
+ for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) {
+ iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG,
- FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE
- (txq_id), 200);
+ FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
+ 1000);
}
iwl_release_nic_access(priv);
spin_unlock_irqrestore(&priv->lock, flags);
@@ -584,7 +645,7 @@ static void iwl_tx_cmd_build_basic(struct iwl_priv *priv,
struct iwl_tx_cmd *tx_cmd,
struct ieee80211_tx_info *info,
struct ieee80211_hdr *hdr,
- int is_unicast, u8 std_id)
+ u8 std_id)
{
__le16 fc = hdr->frame_control;
__le32 tx_flags = tx_cmd->tx_flags;
@@ -647,11 +708,11 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv,
__le16 fc, int sta_id,
int is_hcca)
{
+ u32 rate_flags = 0;
+ int rate_idx;
u8 rts_retry_limit = 0;
u8 data_retry_limit = 0;
u8 rate_plcp;
- u16 rate_flags = 0;
- int rate_idx;
rate_idx = min(ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xffff,
IWL_RATE_COUNT - 1);
@@ -694,14 +755,8 @@ static void iwl_tx_cmd_build_rate(struct iwl_priv *priv,
break;
}
- /* Alternate between antenna A and B for successive frames */
- if (priv->use_ant_b_for_management_frame) {
- priv->use_ant_b_for_management_frame = 0;
- rate_flags |= RATE_MCS_ANT_B_MSK;
- } else {
- priv->use_ant_b_for_management_frame = 1;
- rate_flags |= RATE_MCS_ANT_A_MSK;
- }
+ priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant);
+ rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant);
}
tx_cmd->rts_retry_limit = rts_retry_limit;
@@ -723,7 +778,7 @@ static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
memcpy(tx_cmd->key, keyconf->key, keyconf->keylen);
if (info->flags & IEEE80211_TX_CTL_AMPDU)
tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
- IWL_DEBUG_TX("tx_cmd with aes hwcrypto\n");
+ IWL_DEBUG_TX("tx_cmd with AES hwcrypto\n");
break;
case ALG_TKIP:
@@ -767,7 +822,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct iwl_tfd_frame *tfd;
+ struct iwl_tfd *tfd;
struct iwl_tx_queue *txq;
struct iwl_queue *q;
struct iwl_cmd *out_cmd;
@@ -776,10 +831,10 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
dma_addr_t phys_addr;
dma_addr_t txcmd_phys;
dma_addr_t scratch_phys;
- u16 len, idx, len_org;
+ u16 len, len_org;
u16 seq_number = 0;
__le16 fc;
- u8 hdr_len, unicast;
+ u8 hdr_len;
u8 sta_id;
u8 wait_write_ptr = 0;
u8 tid = 0;
@@ -799,8 +854,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
goto drop_unlock;
}
- unicast = !is_multicast_ether_addr(hdr->addr1);
-
fc = hdr->frame_control;
#ifdef CONFIG_IWLWIFI_DEBUG
@@ -830,10 +883,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
/* Find (or create) index into station table for destination station */
sta_id = iwl_get_sta_id(priv, hdr);
if (sta_id == IWL_INVALID_STATION) {
- DECLARE_MAC_BUF(mac);
-
- IWL_DEBUG_DROP("Dropping - INVALID STATION: %s\n",
- print_mac(mac, hdr->addr1));
+ IWL_DEBUG_DROP("Dropping - INVALID STATION: %pM\n",
+ hdr->addr1);
goto drop;
}
@@ -856,23 +907,22 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
priv->stations[sta_id].tid[tid].tfds_in_queue++;
}
- /* Descriptor for chosen Tx queue */
txq = &priv->txq[txq_id];
q = &txq->q;
+ txq->swq_id = swq_id;
spin_lock_irqsave(&priv->lock, flags);
/* Set up first empty TFD within this queue's circular TFD buffer */
- tfd = &txq->bd[q->write_ptr];
+ tfd = &txq->tfds[q->write_ptr];
memset(tfd, 0, sizeof(*tfd));
- idx = get_cmd_index(q, q->write_ptr, 0);
/* Set up driver data for this TFD */
memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
txq->txb[q->write_ptr].skb[0] = skb;
/* Set up first empty entry in queue's array of Tx/cmd buffers */
- out_cmd = txq->cmd[idx];
+ out_cmd = txq->cmd[q->write_ptr];
tx_cmd = &out_cmd->cmd.tx;
memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd));
@@ -912,12 +962,14 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
/* Physical address of this Tx command's header (not MAC header!),
* within command buffer array. */
- txcmd_phys = pci_map_single(priv->pci_dev, out_cmd,
- sizeof(struct iwl_cmd), PCI_DMA_TODEVICE);
- txcmd_phys += offsetof(struct iwl_cmd, hdr);
-
+ txcmd_phys = pci_map_single(priv->pci_dev,
+ out_cmd, sizeof(struct iwl_cmd),
+ PCI_DMA_TODEVICE);
+ pci_unmap_addr_set(&out_cmd->meta, mapping, txcmd_phys);
+ pci_unmap_len_set(&out_cmd->meta, len, sizeof(struct iwl_cmd));
/* Add buffer containing Tx command and MAC(!) header to TFD's
* first entry */
+ txcmd_phys += offsetof(struct iwl_cmd, hdr);
iwl_hw_txq_attach_buf_to_tfd(priv, tfd, txcmd_phys, len);
if (info->control.hw_key)
@@ -940,7 +992,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
len = (u16)skb->len;
tx_cmd->len = cpu_to_le16(len);
/* TODO need this for burst mode later on */
- iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, unicast, sta_id);
+ iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id);
/* set is_hcca to 0; it probably will never be implemented */
iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, sta_id, 0);
@@ -950,7 +1002,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
offsetof(struct iwl_tx_cmd, scratch);
tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
- tx_cmd->dram_msb_ptr = iwl_get_dma_hi_address(scratch_phys);
+ tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
if (!ieee80211_has_morefrags(hdr->frame_control)) {
txq->need_update = 1;
@@ -983,7 +1035,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
iwl_txq_update_write_ptr(priv, txq);
spin_unlock_irqrestore(&priv->lock, flags);
} else {
- ieee80211_stop_queue(priv->hw, swq_id);
+ ieee80211_stop_queue(priv->hw, txq->swq_id);
}
}
@@ -1011,7 +1063,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
{
struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
struct iwl_queue *q = &txq->q;
- struct iwl_tfd_frame *tfd;
+ struct iwl_tfd *tfd;
struct iwl_cmd *out_cmd;
dma_addr_t phys_addr;
unsigned long flags;
@@ -1040,7 +1092,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
spin_lock_irqsave(&priv->hcmd_lock, flags);
- tfd = &txq->bd[q->write_ptr];
+ tfd = &txq->tfds[q->write_ptr];
memset(tfd, 0, sizeof(*tfd));
@@ -1061,9 +1113,13 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
out_cmd->hdr.sequence |= SEQ_HUGE_FRAME;
len = (idx == TFD_CMD_SLOTS) ?
IWL_MAX_SCAN_SIZE : sizeof(struct iwl_cmd);
- phys_addr = pci_map_single(priv->pci_dev, out_cmd, len,
- PCI_DMA_TODEVICE);
+
+ phys_addr = pci_map_single(priv->pci_dev, out_cmd,
+ len, PCI_DMA_TODEVICE);
+ pci_unmap_addr_set(&out_cmd->meta, mapping, phys_addr);
+ pci_unmap_len_set(&out_cmd->meta, len, len);
phys_addr += offsetof(struct iwl_cmd, hdr);
+
iwl_hw_txq_attach_buf_to_tfd(priv, tfd, phys_addr, fix_size);
#ifdef CONFIG_IWLWIFI_DEBUG
@@ -1113,8 +1169,9 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
return 0;
}
- for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
- q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+ for (index = iwl_queue_inc_wrap(index, q->n_bd);
+ q->read_ptr != index;
+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
tx_info = &txq->txb[txq->q.read_ptr];
ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0]);
@@ -1138,44 +1195,34 @@ EXPORT_SYMBOL(iwl_tx_queue_reclaim);
* need to be reclaimed. As result, some free space forms. If there is
* enough free space (> low mark), wake the stack that feeds us.
*/
-static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
+static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id,
+ int idx, int cmd_idx)
{
struct iwl_tx_queue *txq = &priv->txq[txq_id];
struct iwl_queue *q = &txq->q;
- struct iwl_tfd_frame *bd = &txq->bd[index];
- dma_addr_t dma_addr;
- int is_odd, buf_len;
int nfreed = 0;
- if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) {
+ if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) {
IWL_ERROR("Read index for DMA queue txq id (%d), index %d, "
"is out of range [0-%d] %d %d.\n", txq_id,
- index, q->n_bd, q->write_ptr, q->read_ptr);
+ idx, q->n_bd, q->write_ptr, q->read_ptr);
return;
}
- for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
- q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+ pci_unmap_single(priv->pci_dev,
+ pci_unmap_addr(&txq->cmd[cmd_idx]->meta, mapping),
+ pci_unmap_len(&txq->cmd[cmd_idx]->meta, len),
+ PCI_DMA_TODEVICE);
+
+ for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
- if (nfreed > 1) {
- IWL_ERROR("HCMD skipped: index (%d) %d %d\n", index,
+ if (nfreed++ > 0) {
+ IWL_ERROR("HCMD skipped: index (%d) %d %d\n", idx,
q->write_ptr, q->read_ptr);
queue_work(priv->workqueue, &priv->restart);
}
- is_odd = (index/2) & 0x1;
- if (is_odd) {
- dma_addr = IWL_GET_BITS(bd->pa[index], tb2_addr_lo16) |
- (IWL_GET_BITS(bd->pa[index],
- tb2_addr_hi20) << 16);
- buf_len = IWL_GET_BITS(bd->pa[index], tb2_len);
- } else {
- dma_addr = le32_to_cpu(bd->pa[index].tb1_addr);
- buf_len = IWL_GET_BITS(bd->pa[index], tb1_len);
- }
- pci_unmap_single(priv->pci_dev, dma_addr, buf_len,
- PCI_DMA_TODEVICE);
- nfreed++;
}
}
@@ -1201,8 +1248,13 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
* command queue then there a command routing bug has been introduced
* in the queue management code. */
if (WARN(txq_id != IWL_CMD_QUEUE_NUM,
- "wrong command queue %d, command id 0x%X\n", txq_id, pkt->hdr.cmd))
+ "wrong command queue %d, sequence 0x%X readp=%d writep=%d\n",
+ txq_id, sequence,
+ priv->txq[IWL_CMD_QUEUE_NUM].q.read_ptr,
+ priv->txq[IWL_CMD_QUEUE_NUM].q.write_ptr)) {
+ iwl_print_hex_dump(priv, IWL_DL_INFO , rxb, 32);
return;
+ }
cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge);
cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index];
@@ -1215,7 +1267,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
!cmd->meta.u.callback(priv, cmd, rxb->skb))
rxb->skb = NULL;
- iwl_hcmd_queue_reclaim(priv, txq_id, index);
+ iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index);
if (!(cmd->meta.flags & CMD_ASYNC)) {
clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
@@ -1248,15 +1300,14 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn)
int ret;
unsigned long flags;
struct iwl_tid_data *tid_data;
- DECLARE_MAC_BUF(mac);
if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo)))
tx_fifo = default_tid_to_tx_fifo[tid];
else
return -EINVAL;
- IWL_WARNING("%s on ra = %s tid = %d\n",
- __func__, print_mac(mac, ra), tid);
+ IWL_WARNING("%s on ra = %pM tid = %d\n",
+ __func__, ra, tid);
sta_id = iwl_find_station(priv, ra);
if (sta_id == IWL_INVALID_STATION)
@@ -1301,7 +1352,6 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid)
struct iwl_tid_data *tid_data;
int ret, write_ptr, read_ptr;
unsigned long flags;
- DECLARE_MAC_BUF(mac);
if (!ra) {
IWL_ERROR("ra = NULL\n");
@@ -1362,8 +1412,8 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id)
case IWL_EMPTYING_HW_QUEUE_DELBA:
/* We are reclaiming the last packet of the */
/* aggregated HW queue */
- if (txq_id == tid_data->agg.txq_id &&
- q->read_ptr == q->write_ptr) {
+ if ((txq_id == tid_data->agg.txq_id) &&
+ (q->read_ptr == q->write_ptr)) {
u16 ssn = SEQ_TO_SN(tid_data->seq_number);
int tx_fifo = default_tid_to_tx_fifo[tid];
IWL_DEBUG_HT("HW queue empty: continue DELBA flow\n");
@@ -1414,7 +1464,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv,
IWL_DEBUG_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->seq_ctl);
/* Calculate shift to align block-ack bits with our Tx window bits */
- sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl>>4);
+ sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4);
if (sh < 0) /* tbw something is wrong with indices */
sh += 0x100;
@@ -1436,7 +1486,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv,
ack = bitmap & (1ULL << i);
successes += !!ack;
IWL_DEBUG_TX_REPLY("%s ON i=%d idx=%d raw=%d\n",
- ack? "ACK":"NACK", i, (agg->start_idx + i) & 0xff,
+ ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff,
agg->start_idx + i);
}
@@ -1464,10 +1514,11 @@ void iwl_rx_reply_compressed_ba(struct iwl_priv *priv,
{
struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
- int index;
struct iwl_tx_queue *txq = NULL;
struct iwl_ht_agg *agg;
- DECLARE_MAC_BUF(mac);
+ int index;
+ int sta_id;
+ int tid;
/* "flow" corresponds to Tx queue */
u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
@@ -1482,17 +1533,19 @@ void iwl_rx_reply_compressed_ba(struct iwl_priv *priv,
}
txq = &priv->txq[scd_flow];
- agg = &priv->stations[ba_resp->sta_id].tid[ba_resp->tid].agg;
+ sta_id = ba_resp->sta_id;
+ tid = ba_resp->tid;
+ agg = &priv->stations[sta_id].tid[tid].agg;
/* Find index just before block-ack window */
index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
/* TODO: Need to get this copy more safely - now good for debug */
- IWL_DEBUG_TX_REPLY("REPLY_COMPRESSED_BA [%d]Received from %s, "
+ IWL_DEBUG_TX_REPLY("REPLY_COMPRESSED_BA [%d] Received from %pM, "
"sta_id = %d\n",
agg->wait_for_ba,
- print_mac(mac, (u8 *) &ba_resp->sta_addr_lo32),
+ (u8 *) &ba_resp->sta_addr_lo32,
ba_resp->sta_id);
IWL_DEBUG_TX_REPLY("TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = "
"%d, scd_ssn = %d\n",
@@ -1513,18 +1566,15 @@ void iwl_rx_reply_compressed_ba(struct iwl_priv *priv,
* transmitted ... if not, it's too late anyway). */
if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) {
/* calculate mac80211 ampdu sw queue to wake */
- int ampdu_q =
- scd_flow - priv->hw_params.first_ampdu_q + priv->hw->queues;
int freed = iwl_tx_queue_reclaim(priv, scd_flow, index);
- priv->stations[ba_resp->sta_id].
- tid[ba_resp->tid].tfds_in_queue -= freed;
- if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
- priv->mac80211_registered &&
- agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)
- ieee80211_wake_queue(priv->hw, ampdu_q);
-
- iwl_txq_check_empty(priv, ba_resp->sta_id,
- ba_resp->tid, scd_flow);
+ priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
+
+ if ((iwl_queue_space(&txq->q) > txq->q.low_mark) &&
+ priv->mac80211_registered &&
+ (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA))
+ ieee80211_wake_queue(priv->hw, txq->swq_id);
+
+ iwl_txq_check_empty(priv, sta_id, tid, scd_flow);
}
}
EXPORT_SYMBOL(iwl_rx_reply_compressed_ba);
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 45a6b0c35695..d64580805d6e 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -22,7 +22,7 @@
* file called LICENSE.
*
* Contact Information:
- * James P. Ketrenos <ipw2100-admin@linux.intel.com>
+ * Intel Linux Wireless <ilw@linux.intel.com>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
*****************************************************************************/
@@ -41,6 +41,7 @@
#include <linux/if_arp.h>
#include <net/ieee80211_radiotap.h>
+#include <net/lib80211.h>
#include <net/mac80211.h>
#include <asm/div64.h>
@@ -64,11 +65,10 @@ static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv,
/* module parameters */
static int iwl3945_param_disable_hw_scan; /* def: 0 = use 3945's h/w scan */
-static int iwl3945_param_debug; /* def: 0 = minimal debug log messages */
+static u32 iwl3945_param_debug; /* def: 0 = minimal debug log messages */
static int iwl3945_param_disable; /* def: 0 = enable radio */
static int iwl3945_param_antenna; /* def: 0 = both antennas (use diversity) */
int iwl3945_param_hwcrypto; /* def: 0 = use software encryption */
-static int iwl3945_param_qos_enable = 1; /* def: 1 = use quality of service */
int iwl3945_param_queues_num = IWL39_MAX_NUM_QUEUES; /* def: 8 Tx queues */
/*
@@ -93,12 +93,13 @@ int iwl3945_param_queues_num = IWL39_MAX_NUM_QUEUES; /* def: 8 Tx queues */
#define IWLWIFI_VERSION "1.2.26k" VD VS
#define DRV_COPYRIGHT "Copyright(c) 2003-2008 Intel Corporation"
+#define DRV_AUTHOR "<ilw@linux.intel.com>"
#define DRV_VERSION IWLWIFI_VERSION
MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERSION);
-MODULE_AUTHOR(DRV_COPYRIGHT);
+MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");
static const struct ieee80211_supported_band *iwl3945_get_band(
@@ -107,46 +108,6 @@ static const struct ieee80211_supported_band *iwl3945_get_band(
return priv->hw->wiphy->bands[band];
}
-static int iwl3945_is_empty_essid(const char *essid, int essid_len)
-{
- /* Single white space is for Linksys APs */
- if (essid_len == 1 && essid[0] == ' ')
- return 1;
-
- /* Otherwise, if the entire essid is 0, we assume it is hidden */
- while (essid_len) {
- essid_len--;
- if (essid[essid_len] != '\0')
- return 0;
- }
-
- return 1;
-}
-
-static const char *iwl3945_escape_essid(const char *essid, u8 essid_len)
-{
- static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
- const char *s = essid;
- char *d = escaped;
-
- if (iwl3945_is_empty_essid(essid, essid_len)) {
- memcpy(escaped, "<hidden>", sizeof("<hidden>"));
- return escaped;
- }
-
- essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
- while (essid_len--) {
- if (*s == '\0') {
- *d++ = '\\';
- *d++ = '0';
- s++;
- } else
- *d++ = *s++;
- }
- *d = '\0';
- return escaped;
-}
-
/*************** DMA-QUEUE-GENERAL-FUNCTIONS *****
* DMA services
*
@@ -446,7 +407,6 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8
int index = IWL_INVALID_STATION;
struct iwl3945_station_entry *station;
unsigned long flags_spin;
- DECLARE_MAC_BUF(mac);
u8 rate;
spin_lock_irqsave(&priv->sta_lock, flags_spin);
@@ -480,7 +440,7 @@ u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *addr, int is_ap, u8
return index;
}
- IWL_DEBUG_ASSOC("Add STA ID %d: %s\n", index, print_mac(mac, addr));
+ IWL_DEBUG_ASSOC("Add STA ID %d: %pM\n", index, addr);
station = &priv->stations[index];
station->used = 1;
priv->num_stations++;
@@ -559,7 +519,7 @@ static inline int iwl3945_is_ready_rf(struct iwl3945_priv *priv)
/*************** HOST COMMAND QUEUE FUNCTIONS *****/
-#define IWL_CMD(x) case x : return #x
+#define IWL_CMD(x) case x: return #x
static const char *get_cmd_string(u8 cmd)
{
@@ -1063,7 +1023,6 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv)
/* cast away the const for active_rxon in this function */
struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon;
int rc = 0;
- DECLARE_MAC_BUF(mac);
if (!iwl3945_is_alive(priv))
return -1;
@@ -1124,11 +1083,11 @@ static int iwl3945_commit_rxon(struct iwl3945_priv *priv)
IWL_DEBUG_INFO("Sending RXON\n"
"* with%s RXON_FILTER_ASSOC_MSK\n"
"* channel = %d\n"
- "* bssid = %s\n",
+ "* bssid = %pM\n",
((priv->staging_rxon.filter_flags &
RXON_FILTER_ASSOC_MSK) ? "" : "out"),
le16_to_cpu(priv->staging_rxon.channel),
- print_mac(mac, priv->staging_rxon.bssid_addr));
+ priv->staging_rxon.bssid_addr);
/* Apply the new configuration */
rc = iwl3945_send_cmd_pdu(priv, REPLY_RXON,
@@ -1443,7 +1402,7 @@ static void iwl3945_free_frame(struct iwl3945_priv *priv, struct iwl3945_frame *
unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv,
struct ieee80211_hdr *hdr,
- const u8 *dest, int left)
+ int left)
{
if (!iwl3945_is_associated(priv) || !priv->ibss_beacon ||
@@ -1459,9 +1418,16 @@ unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv,
return priv->ibss_beacon->len;
}
-static u8 iwl3945_rate_get_lowest_plcp(int rate_mask)
+static u8 iwl3945_rate_get_lowest_plcp(struct iwl3945_priv *priv)
{
u8 i;
+ int rate_mask;
+
+ /* Set rate mask*/
+ if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
+ rate_mask = priv->active_rate_basic & IWL_CCK_RATES_MASK;
+ else
+ rate_mask = priv->active_rate_basic & IWL_OFDM_RATES_MASK;
for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID;
i = iwl3945_rates[i].next_ieee) {
@@ -1469,7 +1435,11 @@ static u8 iwl3945_rate_get_lowest_plcp(int rate_mask)
return iwl3945_rates[i].plcp;
}
- return IWL_RATE_INVALID;
+ /* No valid rate was found. Assign the lowest one */
+ if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)
+ return IWL_RATE_1M_PLCP;
+ else
+ return IWL_RATE_6M_PLCP;
}
static int iwl3945_send_beacon_cmd(struct iwl3945_priv *priv)
@@ -1487,16 +1457,7 @@ static int iwl3945_send_beacon_cmd(struct iwl3945_priv *priv)
return -ENOMEM;
}
- if (!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK)) {
- rate = iwl3945_rate_get_lowest_plcp(priv->active_rate_basic &
- 0xFF0);
- if (rate == IWL_INVALID_RATE)
- rate = IWL_RATE_6M_PLCP;
- } else {
- rate = iwl3945_rate_get_lowest_plcp(priv->active_rate_basic & 0xF);
- if (rate == IWL_INVALID_RATE)
- rate = IWL_RATE_1M_PLCP;
- }
+ rate = iwl3945_rate_get_lowest_plcp(priv);
frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate);
@@ -1544,10 +1505,8 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv)
{
u16 *e = (u16 *)&priv->eeprom;
u32 gp = iwl3945_read32(priv, CSR_EEPROM_GP);
- u32 r;
int sz = sizeof(priv->eeprom);
- int rc;
- int i;
+ int ret;
u16 addr;
/* The EEPROM structure has several padding buffers within it
@@ -1562,29 +1521,28 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv)
}
/* Make sure driver (instead of uCode) is allowed to read EEPROM */
- rc = iwl3945_eeprom_acquire_semaphore(priv);
- if (rc < 0) {
+ ret = iwl3945_eeprom_acquire_semaphore(priv);
+ if (ret < 0) {
IWL_ERROR("Failed to acquire EEPROM semaphore.\n");
return -ENOENT;
}
/* eeprom is an array of 16bit values */
for (addr = 0; addr < sz; addr += sizeof(u16)) {
- _iwl3945_write32(priv, CSR_EEPROM_REG, addr << 1);
- _iwl3945_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
-
- for (i = 0; i < IWL_EEPROM_ACCESS_TIMEOUT;
- i += IWL_EEPROM_ACCESS_DELAY) {
- r = _iwl3945_read_direct32(priv, CSR_EEPROM_REG);
- if (r & CSR_EEPROM_REG_READ_VALID_MSK)
- break;
- udelay(IWL_EEPROM_ACCESS_DELAY);
- }
+ u32 r;
- if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) {
+ _iwl3945_write32(priv, CSR_EEPROM_REG,
+ CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
+ _iwl3945_clear_bit(priv, CSR_EEPROM_REG, CSR_EEPROM_REG_BIT_CMD);
+ ret = iwl3945_poll_direct_bit(priv, CSR_EEPROM_REG,
+ CSR_EEPROM_REG_READ_VALID_MSK,
+ IWL_EEPROM_ACCESS_TIMEOUT);
+ if (ret < 0) {
IWL_ERROR("Time out reading EEPROM[%d]\n", addr);
- return -ETIMEDOUT;
+ return ret;
}
+
+ r = _iwl3945_read_direct32(priv, CSR_EEPROM_REG);
e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
}
@@ -1634,7 +1592,7 @@ static u16 iwl3945_supported_rate_to_ie(u8 *ie, u16 supported_rate,
*/
static u16 iwl3945_fill_probe_req(struct iwl3945_priv *priv,
struct ieee80211_mgmt *frame,
- int left, int is_direct)
+ int left)
{
int len = 0;
u8 *pos = NULL;
@@ -1664,20 +1622,6 @@ static u16 iwl3945_fill_probe_req(struct iwl3945_priv *priv,
*pos++ = WLAN_EID_SSID;
*pos++ = 0;
- /* fill in our direct SSID IE... */
- if (is_direct) {
- /* ...next IE... */
- left -= 2 + priv->essid_len;
- if (left < 0)
- return 0;
- /* ... fill it in... */
- *pos++ = WLAN_EID_SSID;
- *pos++ = priv->essid_len;
- memcpy(pos, priv->essid, priv->essid_len);
- pos += priv->essid_len;
- len += 2 + priv->essid_len;
- }
-
/* fill in supported rate */
/* ...next IE... */
left -= 2;
@@ -1746,17 +1690,21 @@ static void iwl3945_reset_qos(struct iwl3945_priv *priv)
spin_lock_irqsave(&priv->lock, flags);
priv->qos_data.qos_active = 0;
- if (priv->iw_mode == NL80211_IFTYPE_ADHOC) {
- if (priv->qos_data.qos_enable)
- priv->qos_data.qos_active = 1;
- if (!(priv->active_rate & 0xfff0)) {
- cw_min = 31;
- is_legacy = 1;
- }
- } else if (priv->iw_mode == NL80211_IFTYPE_AP) {
- if (priv->qos_data.qos_enable)
- priv->qos_data.qos_active = 1;
- } else if (!(priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK)) {
+ /* QoS always active in AP and ADHOC mode
+ * In STA mode wait for association
+ */
+ if (priv->iw_mode == NL80211_IFTYPE_ADHOC ||
+ priv->iw_mode == NL80211_IFTYPE_AP)
+ priv->qos_data.qos_active = 1;
+ else
+ priv->qos_data.qos_active = 0;
+
+
+ /* check for legacy mode */
+ if ((priv->iw_mode == NL80211_IFTYPE_ADHOC &&
+ (priv->active_rate & IWL_OFDM_RATES_MASK) == 0) ||
+ (priv->iw_mode == NL80211_IFTYPE_STATION &&
+ (priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK) == 0)) {
cw_min = 31;
is_legacy = 1;
}
@@ -1828,9 +1776,6 @@ static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force)
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- if (!priv->qos_data.qos_enable)
- return;
-
spin_lock_irqsave(&priv->lock, flags);
priv->qos_data.def_qos_parm.qos_flags = 0;
@@ -1846,7 +1791,7 @@ static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force)
spin_unlock_irqrestore(&priv->lock, flags);
if (force || iwl3945_is_associated(priv)) {
- IWL_DEBUG_QOS("send QoS cmd with Qos active %d \n",
+ IWL_DEBUG_QOS("send QoS cmd with QoS active %d \n",
priv->qos_data.qos_active);
iwl3945_send_qos_params_command(priv,
@@ -1870,7 +1815,7 @@ static void iwl3945_activate_qos(struct iwl3945_priv *priv, u8 force)
/* default power management (not Tx power) table values */
-/* for tim 0-10 */
+/* for TIM 0-10 */
static struct iwl3945_power_vec_entry range_0[IWL_POWER_AC] = {
{{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
@@ -1880,7 +1825,7 @@ static struct iwl3945_power_vec_entry range_0[IWL_POWER_AC] = {
{{SLP, SLP_TIMEOUT(25), SLP_TIMEOUT(25), SLP_VEC(4, 7, 10, 10, 10)}, 1}
};
-/* for tim > 10 */
+/* for TIM > 10 */
static struct iwl3945_power_vec_entry range_1[IWL_POWER_AC] = {
{{NOSLP, SLP_TIMEOUT(0), SLP_TIMEOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
{{SLP, SLP_TIMEOUT(200), SLP_TIMEOUT(500),
@@ -2156,11 +2101,6 @@ static void iwl3945_setup_rxon_timing(struct iwl3945_priv *priv)
static int iwl3945_scan_initiate(struct iwl3945_priv *priv)
{
- if (priv->iw_mode == NL80211_IFTYPE_AP) {
- IWL_ERROR("APs don't scan.\n");
- return 0;
- }
-
if (!iwl3945_is_ready_rf(priv)) {
IWL_DEBUG_SCAN("Aborting scan due to not ready.\n");
return -EIO;
@@ -2230,13 +2170,14 @@ static void iwl3945_set_flags_for_phymode(struct iwl3945_priv *priv,
/*
* initialize rxon structure with default values from eeprom
*/
-static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
+static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv,
+ int mode)
{
const struct iwl3945_channel_info *ch_info;
memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon));
- switch (priv->iw_mode) {
+ switch (mode) {
case NL80211_IFTYPE_AP:
priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP;
break;
@@ -2259,7 +2200,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
break;
default:
- IWL_ERROR("Unsupported interface type %d\n", priv->iw_mode);
+ IWL_ERROR("Unsupported interface type %d\n", mode);
break;
}
@@ -2282,8 +2223,7 @@ static void iwl3945_connection_init_rx_config(struct iwl3945_priv *priv)
* in some case A channels are all non IBSS
* in this case force B/G channel
*/
- if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) &&
- !(is_channel_ibss(ch_info)))
+ if ((mode == NL80211_IFTYPE_ADHOC) && !(is_channel_ibss(ch_info)))
ch_info = &priv->channel_info[0];
priv->staging_rxon.channel = cpu_to_le16(ch_info->channel);
@@ -2316,14 +2256,12 @@ static int iwl3945_set_mode(struct iwl3945_priv *priv, int mode)
}
}
- priv->iw_mode = mode;
-
- iwl3945_connection_init_rx_config(priv);
+ iwl3945_connection_init_rx_config(priv, mode);
memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
iwl3945_clear_stations_table(priv);
- /* dont commit rxon if rf-kill is on*/
+ /* don't commit rxon if rf-kill is on*/
if (!iwl3945_is_ready_rf(priv))
return -EAGAIN;
@@ -2352,7 +2290,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl3945_priv *priv,
case ALG_CCMP:
cmd->cmd.tx.sec_ctl = TX_CMD_SEC_CCM;
memcpy(cmd->cmd.tx.key, keyinfo->key, keyinfo->keylen);
- IWL_DEBUG_TX("tx_cmd with aes hwcrypto\n");
+ IWL_DEBUG_TX("tx_cmd with AES hwcrypto\n");
break;
case ALG_TKIP:
@@ -2397,6 +2335,7 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv,
{
__le16 fc = hdr->frame_control;
__le32 tx_flags = cmd->cmd.tx.tx_flags;
+ u8 rc_flags = info->control.rates[0].flags;
cmd->cmd.tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
@@ -2423,10 +2362,10 @@ static void iwl3945_build_tx_cmd_basic(struct iwl3945_priv *priv,
tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
}
- if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
+ if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
tx_flags |= TX_CMD_FLG_RTS_MSK;
tx_flags &= ~TX_CMD_FLG_CTS_MSK;
- } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
+ } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
tx_flags &= ~TX_CMD_FLG_RTS_MSK;
tx_flags |= TX_CMD_FLG_CTS_MSK;
}
@@ -2482,8 +2421,6 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
/* If this frame is going out to an IBSS network, find the station,
* or create a new station table entry */
case NL80211_IFTYPE_ADHOC: {
- DECLARE_MAC_BUF(mac);
-
/* Create new station table entry */
sta_id = iwl3945_hw_find_station(priv, hdr->addr1);
if (sta_id != IWL_INVALID_STATION)
@@ -2494,9 +2431,9 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h
if (sta_id != IWL_INVALID_STATION)
return sta_id;
- IWL_DEBUG_DROP("Station %s not in station map. "
+ IWL_DEBUG_DROP("Station %pM not in station map. "
"Defaulting to broadcast...\n",
- print_mac(mac, hdr->addr1));
+ hdr->addr1);
iwl3945_print_hex_dump(IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr));
return priv->hw_setting.bcast_sta_id;
}
@@ -2579,10 +2516,8 @@ static int iwl3945_tx_skb(struct iwl3945_priv *priv, struct sk_buff *skb)
/* Find (or create) index into station table for destination station */
sta_id = iwl3945_get_sta_id(priv, hdr);
if (sta_id == IWL_INVALID_STATION) {
- DECLARE_MAC_BUF(mac);
-
- IWL_DEBUG_DROP("Dropping - INVALID STATION: %s\n",
- print_mac(mac, hdr->addr1));
+ IWL_DEBUG_DROP("Dropping - INVALID STATION: %pM\n",
+ hdr->addr1);
goto drop;
}
@@ -4019,8 +3954,6 @@ static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv,
#ifdef CONFIG_IWL3945_DEBUG
static void iwl3945_print_rx_config_cmd(struct iwl3945_rxon_cmd *rxon)
{
- DECLARE_MAC_BUF(mac);
-
IWL_DEBUG_RADIO("RX CONFIG:\n");
iwl3945_print_hex_dump(IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
IWL_DEBUG_RADIO("u16 channel: 0x%x\n", le16_to_cpu(rxon->channel));
@@ -4031,10 +3964,8 @@ static void iwl3945_print_rx_config_cmd(struct iwl3945_rxon_cmd *rxon)
IWL_DEBUG_RADIO("u8 ofdm_basic_rates: 0x%02x\n",
rxon->ofdm_basic_rates);
IWL_DEBUG_RADIO("u8 cck_basic_rates: 0x%02x\n", rxon->cck_basic_rates);
- IWL_DEBUG_RADIO("u8[6] node_addr: %s\n",
- print_mac(mac, rxon->node_addr));
- IWL_DEBUG_RADIO("u8[6] bssid_addr: %s\n",
- print_mac(mac, rxon->bssid_addr));
+ IWL_DEBUG_RADIO("u8[6] node_addr: %pM\n", rxon->node_addr);
+ IWL_DEBUG_RADIO("u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
IWL_DEBUG_RADIO("u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
}
#endif
@@ -4050,7 +3981,7 @@ static void iwl3945_enable_interrupts(struct iwl3945_priv *priv)
/* call this function to flush any scheduled tasklet */
static inline void iwl_synchronize_irq(struct iwl3945_priv *priv)
{
- /* wait to make sure we flush pedding tasklet*/
+ /* wait to make sure we flush pending tasklet*/
synchronize_irq(priv->pci_dev->irq);
tasklet_kill(&priv->irq_tasklet);
}
@@ -4373,35 +4304,6 @@ static void iwl3945_irq_tasklet(struct iwl3945_priv *priv)
/* Safely ignore these bits for debug checks below */
inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
- /* HW RF KILL switch toggled (4965 only) */
- if (inta & CSR_INT_BIT_RF_KILL) {
- int hw_rf_kill = 0;
- if (!(iwl3945_read32(priv, CSR_GP_CNTRL) &
- CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
- hw_rf_kill = 1;
-
- IWL_DEBUG(IWL_DL_INFO | IWL_DL_RF_KILL | IWL_DL_ISR,
- "RF_KILL bit toggled to %s.\n",
- hw_rf_kill ? "disable radio":"enable radio");
-
- /* Queue restart only if RF_KILL switch was set to "kill"
- * when we loaded driver, and is now set to "enable".
- * After we're Alive, RF_KILL gets handled by
- * iwl3945_rx_card_state_notif() */
- if (!hw_rf_kill && !test_bit(STATUS_ALIVE, &priv->status)) {
- clear_bit(STATUS_RF_KILL_HW, &priv->status);
- queue_work(priv->workqueue, &priv->restart);
- }
-
- handled |= CSR_INT_BIT_RF_KILL;
- }
-
- /* Chip got too hot and stopped itself (4965 only) */
- if (inta & CSR_INT_BIT_CT_KILL) {
- IWL_ERROR("Microcode CT kill error detected.\n");
- handled |= CSR_INT_BIT_CT_KILL;
- }
-
/* Error detected by uCode */
if (inta & CSR_INT_BIT_SW_ERR) {
IWL_ERROR("Microcode SW error detected. Restarting 0x%X.\n",
@@ -4502,7 +4404,7 @@ static irqreturn_t iwl3945_isr(int irq, void *data)
if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
/* Hardware disappeared */
- IWL_WARNING("HARDWARE GONE?? INTA == 0x%080x\n", inta);
+ IWL_WARNING("HARDWARE GONE?? INTA == 0x%08x\n", inta);
goto unplugged;
}
@@ -4805,7 +4707,7 @@ static void iwl3945_free_channel_map(struct iwl3945_priv *priv)
#define IWL_PASSIVE_DWELL_BASE (100)
#define IWL_CHANNEL_TUNE_TIME 5
-#define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1))))
+#define IWL_SCAN_PROBE_MASK(n) (BIT(n) | (BIT(n) - BIT(1)))
static inline u16 iwl3945_get_active_dwell_time(struct iwl3945_priv *priv,
enum ieee80211_band band,
@@ -4876,17 +4778,33 @@ static int iwl3945_get_channels_for_scan(struct iwl3945_priv *priv,
continue;
}
+ scan_ch->active_dwell = cpu_to_le16(active_dwell);
+ scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+ /* If passive , set up for auto-switch
+ * and use long active_dwell time.
+ */
if (!is_active || is_channel_passive(ch_info) ||
- (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN))
+ (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
scan_ch->type = 0; /* passive */
- else
+ if (IWL_UCODE_API(priv->ucode_ver) == 1)
+ scan_ch->active_dwell = cpu_to_le16(passive_dwell - 1);
+ } else {
scan_ch->type = 1; /* active */
+ }
- if ((scan_ch->type & 1) && n_probes)
- scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
-
- scan_ch->active_dwell = cpu_to_le16(active_dwell);
- scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+ /* Set direct probe bits. These may be used both for active
+ * scan channels (probes gets sent right away),
+ * or for passive channels (probes get se sent only after
+ * hearing clear Rx packet).*/
+ if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
+ if (n_probes)
+ scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
+ } else {
+ /* uCode v1 does not allow setting direct probe bits on
+ * passive channel. */
+ if ((scan_ch->type & 1) && n_probes)
+ scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
+ }
/* Set txpower levels to defaults */
scan_ch->tpc.dsp_atten = 110;
@@ -5387,25 +5305,41 @@ static void iwl3945_nic_start(struct iwl3945_priv *priv)
static int iwl3945_read_ucode(struct iwl3945_priv *priv)
{
struct iwl3945_ucode *ucode;
- int ret = 0;
+ int ret = -EINVAL, index;
const struct firmware *ucode_raw;
/* firmware file name contains uCode/driver compatibility version */
- const char *name = priv->cfg->fw_name;
+ const char *name_pre = priv->cfg->fw_name_pre;
+ const unsigned int api_max = priv->cfg->ucode_api_max;
+ const unsigned int api_min = priv->cfg->ucode_api_min;
+ char buf[25];
u8 *src;
size_t len;
- u32 ver, inst_size, data_size, init_size, init_data_size, boot_size;
+ u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size;
/* Ask kernel firmware_class module to get the boot firmware off disk.
* request_firmware() is synchronous, file is in memory on return. */
- ret = request_firmware(&ucode_raw, name, &priv->pci_dev->dev);
- if (ret < 0) {
- IWL_ERROR("%s firmware file req failed: Reason %d\n",
- name, ret);
- goto error;
+ for (index = api_max; index >= api_min; index--) {
+ sprintf(buf, "%s%u%s", name_pre, index, ".ucode");
+ ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev);
+ if (ret < 0) {
+ IWL_ERROR("%s firmware file req failed: Reason %d\n",
+ buf, ret);
+ if (ret == -ENOENT)
+ continue;
+ else
+ goto error;
+ } else {
+ if (index < api_max)
+ IWL_ERROR("Loaded firmware %s, which is deprecated. Please use API v%u instead.\n",
+ buf, api_max);
+ IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n",
+ buf, ucode_raw->size);
+ break;
+ }
}
- IWL_DEBUG_INFO("Got firmware '%s' file (%zd bytes) from disk\n",
- name, ucode_raw->size);
+ if (ret < 0)
+ goto error;
/* Make sure that we got at least our header! */
if (ucode_raw->size < sizeof(*ucode)) {
@@ -5417,20 +5351,46 @@ static int iwl3945_read_ucode(struct iwl3945_priv *priv)
/* Data from ucode file: header followed by uCode images */
ucode = (void *)ucode_raw->data;
- ver = le32_to_cpu(ucode->ver);
+ priv->ucode_ver = le32_to_cpu(ucode->ver);
+ api_ver = IWL_UCODE_API(priv->ucode_ver);
inst_size = le32_to_cpu(ucode->inst_size);
data_size = le32_to_cpu(ucode->data_size);
init_size = le32_to_cpu(ucode->init_size);
init_data_size = le32_to_cpu(ucode->init_data_size);
boot_size = le32_to_cpu(ucode->boot_size);
- IWL_DEBUG_INFO("f/w package hdr ucode version = 0x%x\n", ver);
+ /* api_ver should match the api version forming part of the
+ * firmware filename ... but we don't check for that and only rely
+ * on the API version read from firware header from here on forward */
+
+ if (api_ver < api_min || api_ver > api_max) {
+ IWL_ERROR("Driver unable to support your firmware API. "
+ "Driver supports v%u, firmware is v%u.\n",
+ api_max, api_ver);
+ priv->ucode_ver = 0;
+ ret = -EINVAL;
+ goto err_release;
+ }
+ if (api_ver != api_max)
+ IWL_ERROR("Firmware has old API version. Expected %u, "
+ "got %u. New firmware can be obtained "
+ "from http://www.intellinuxwireless.org.\n",
+ api_max, api_ver);
+
+ printk(KERN_INFO DRV_NAME " loaded firmware version %u.%u.%u.%u\n",
+ IWL_UCODE_MAJOR(priv->ucode_ver),
+ IWL_UCODE_MINOR(priv->ucode_ver),
+ IWL_UCODE_API(priv->ucode_ver),
+ IWL_UCODE_SERIAL(priv->ucode_ver));
+ IWL_DEBUG_INFO("f/w package hdr ucode version raw = 0x%x\n",
+ priv->ucode_ver);
IWL_DEBUG_INFO("f/w package hdr runtime inst size = %u\n", inst_size);
IWL_DEBUG_INFO("f/w package hdr runtime data size = %u\n", data_size);
IWL_DEBUG_INFO("f/w package hdr init inst size = %u\n", init_size);
IWL_DEBUG_INFO("f/w package hdr init data size = %u\n", init_data_size);
IWL_DEBUG_INFO("f/w package hdr boot inst size = %u\n", boot_size);
+
/* Verify size of file vs. image size info in file's header */
if (ucode_raw->size < sizeof(*ucode) +
inst_size + data_size + init_size +
@@ -5607,7 +5567,7 @@ static int iwl3945_set_ucode_ptrs(struct iwl3945_priv *priv)
iwl3945_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
priv->ucode_data.len);
- /* Inst bytecount must be last to set up, bit 31 signals uCode
+ /* Inst byte count must be last to set up, bit 31 signals uCode
* that all new ptr/size info is in place */
iwl3945_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
priv->ucode_code.len | BSM_DRAM_INST_LOAD);
@@ -5665,6 +5625,10 @@ static void iwl3945_init_alive_start(struct iwl3945_priv *priv)
}
+/* temporary */
+static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw,
+ struct sk_buff *skb);
+
/**
* iwl3945_alive_start - called after REPLY_ALIVE notification received
* from protocol/runtime uCode (initialization uCode's
@@ -5699,7 +5663,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
rc = iwl3945_grab_nic_access(priv);
if (rc) {
- IWL_WARNING("Can not read rfkill status from adapter\n");
+ IWL_WARNING("Can not read RFKILL status from adapter\n");
return;
}
@@ -5709,7 +5673,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
if (rfkill & 0x1) {
clear_bit(STATUS_RF_KILL_HW, &priv->status);
- /* if rfkill is not on, then wait for thermal
+ /* if RFKILL is not on, then wait for thermal
* sensor in adapter to kick in */
while (iwl3945_hw_get_temperature(priv) == 0) {
thermal_spin++;
@@ -5747,7 +5711,7 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
} else {
/* Initialize our rx_config data */
- iwl3945_connection_init_rx_config(priv);
+ iwl3945_connection_init_rx_config(priv, priv->iw_mode);
memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
}
@@ -5768,6 +5732,14 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
if (priv->error_recovering)
iwl3945_error_recovery(priv);
+ /* reassociate for ADHOC mode */
+ if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) {
+ struct sk_buff *beacon = ieee80211_beacon_get(priv->hw,
+ priv->vif);
+ if (beacon)
+ iwl3945_mac_beacon_update(priv->hw, beacon);
+ }
+
return;
restart:
@@ -5902,7 +5874,7 @@ static int __iwl3945_up(struct iwl3945_priv *priv)
}
if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
- IWL_ERROR("ucode not available for device bringup\n");
+ IWL_ERROR("ucode not available for device bring up\n");
return -EIO;
}
@@ -6046,24 +6018,6 @@ static void iwl3945_bg_rf_kill(struct work_struct *work)
iwl3945_rfkill_set_hw_state(priv);
}
-static void iwl3945_bg_set_monitor(struct work_struct *work)
-{
- struct iwl3945_priv *priv = container_of(work,
- struct iwl3945_priv, set_monitor);
-
- IWL_DEBUG(IWL_DL_STATE, "setting monitor mode\n");
-
- mutex_lock(&priv->mutex);
-
- if (!iwl3945_is_ready(priv))
- IWL_DEBUG(IWL_DL_STATE, "leave - not ready\n");
- else
- if (iwl3945_set_mode(priv, NL80211_IFTYPE_MONITOR) != 0)
- IWL_ERROR("iwl3945_set_mode() failed\n");
-
- mutex_unlock(&priv->mutex);
-}
-
#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ)
static void iwl3945_bg_scan_check(struct work_struct *data)
@@ -6101,6 +6055,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
struct ieee80211_conf *conf = NULL;
u8 n_probes = 2;
enum ieee80211_band band;
+ DECLARE_SSID_BUF(ssid);
conf = ieee80211_get_hw_conf(priv->hw);
@@ -6111,7 +6066,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
goto done;
}
- /* Make sure the scan wasn't cancelled before this queued work
+ /* Make sure the scan wasn't canceled before this queued work
* was given the chance to run... */
if (!test_bit(STATUS_SCANNING, &priv->status))
goto done;
@@ -6201,21 +6156,13 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
if (priv->one_direct_scan) {
IWL_DEBUG_SCAN
("Kicking off one direct scan for '%s'\n",
- iwl3945_escape_essid(priv->direct_ssid,
- priv->direct_ssid_len));
+ print_ssid(ssid, priv->direct_ssid,
+ priv->direct_ssid_len));
scan->direct_scan[0].id = WLAN_EID_SSID;
scan->direct_scan[0].len = priv->direct_ssid_len;
memcpy(scan->direct_scan[0].ssid,
priv->direct_ssid, priv->direct_ssid_len);
n_probes++;
- } else if (!iwl3945_is_associated(priv) && priv->essid_len) {
- IWL_DEBUG_SCAN
- ("Kicking off one direct scan for '%s' when not associated\n",
- iwl3945_escape_essid(priv->essid, priv->essid_len));
- scan->direct_scan[0].id = WLAN_EID_SSID;
- scan->direct_scan[0].len = priv->essid_len;
- memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
- n_probes++;
} else
IWL_DEBUG_SCAN("Kicking off one indirect scan.\n");
@@ -6223,7 +6170,7 @@ static void iwl3945_bg_request_scan(struct work_struct *data)
* that based on the direct_mask added to each channel entry */
scan->tx_cmd.len = cpu_to_le16(
iwl3945_fill_probe_req(priv, (struct ieee80211_mgmt *)scan->data,
- IWL_MAX_SCAN_SIZE - sizeof(*scan), 0));
+ IWL_MAX_SCAN_SIZE - sizeof(*scan)));
scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
scan->tx_cmd.sta_id = priv->hw_setting.bcast_sta_id;
scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
@@ -6333,7 +6280,6 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv)
{
int rc = 0;
struct ieee80211_conf *conf = NULL;
- DECLARE_MAC_BUF(mac);
if (priv->iw_mode == NL80211_IFTYPE_AP) {
IWL_ERROR("%s Should not be called in AP mode\n", __func__);
@@ -6341,9 +6287,8 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv)
}
- IWL_DEBUG_ASSOC("Associated as %d to: %s\n",
- priv->assoc_id,
- print_mac(mac, priv->active_rxon.bssid_addr));
+ IWL_DEBUG_ASSOC("Associated as %d to: %pM\n",
+ priv->assoc_id, priv->active_rxon.bssid_addr);
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
@@ -6398,10 +6343,7 @@ static void iwl3945_post_associate(struct iwl3945_priv *priv)
case NL80211_IFTYPE_ADHOC:
- /* clear out the station table */
- iwl3945_clear_stations_table(priv);
-
- iwl3945_add_station(priv, iwl3945_broadcast_addr, 0, 0);
+ priv->assoc_id = 1;
iwl3945_add_station(priv, priv->bssid, 0, 0);
iwl3945_sync_sta(priv, IWL_STA_ID,
(priv->band == IEEE80211_BAND_5GHZ) ?
@@ -6439,7 +6381,7 @@ static void iwl3945_bg_abort_scan(struct work_struct *work)
mutex_unlock(&priv->mutex);
}
-static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
+static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed);
static void iwl3945_bg_scan_completed(struct work_struct *work)
{
@@ -6452,7 +6394,7 @@ static void iwl3945_bg_scan_completed(struct work_struct *work)
return;
if (test_bit(STATUS_CONF_PENDING, &priv->status))
- iwl3945_mac_config(priv->hw, ieee80211_get_hw_conf(priv->hw));
+ iwl3945_mac_config(priv->hw, 0);
ieee80211_scan_completed(priv->hw);
@@ -6604,7 +6546,6 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
{
struct iwl3945_priv *priv = hw->priv;
unsigned long flags;
- DECLARE_MAC_BUF(mac);
IWL_DEBUG_MAC80211("enter: type %d\n", conf->type);
@@ -6615,13 +6556,14 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
spin_lock_irqsave(&priv->lock, flags);
priv->vif = conf->vif;
+ priv->iw_mode = conf->type;
spin_unlock_irqrestore(&priv->lock, flags);
mutex_lock(&priv->mutex);
if (conf->mac_addr) {
- IWL_DEBUG_MAC80211("Set: %s\n", print_mac(mac, conf->mac_addr));
+ IWL_DEBUG_MAC80211("Set: %pM\n", conf->mac_addr);
memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
}
@@ -6641,10 +6583,11 @@ static int iwl3945_mac_add_interface(struct ieee80211_hw *hw,
* be set inappropriately and the driver currently sets the hardware up to
* use it whenever needed.
*/
-static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+static int iwl3945_mac_config(struct ieee80211_hw *hw, u32 changed)
{
struct iwl3945_priv *priv = hw->priv;
const struct iwl3945_channel_info *ch_info;
+ struct ieee80211_conf *conf = &hw->conf;
unsigned long flags;
int ret = 0;
@@ -6782,16 +6725,11 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv)
* clear sta table, add BCAST sta... */
}
-/* temporary */
-static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb);
-
static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_if_conf *conf)
{
struct iwl3945_priv *priv = hw->priv;
- DECLARE_MAC_BUF(mac);
- unsigned long flags;
int rc;
if (conf == NULL)
@@ -6808,28 +6746,20 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
if (!beacon)
return -ENOMEM;
+ mutex_lock(&priv->mutex);
rc = iwl3945_mac_beacon_update(hw, beacon);
+ mutex_unlock(&priv->mutex);
if (rc)
return rc;
}
- /* XXX: this MUST use conf->mac_addr */
-
- if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
- (!conf->ssid_len)) {
- IWL_DEBUG_MAC80211
- ("Leaving in AP mode because HostAPD is not ready.\n");
- return 0;
- }
-
if (!iwl3945_is_alive(priv))
return -EAGAIN;
mutex_lock(&priv->mutex);
if (conf->bssid)
- IWL_DEBUG_MAC80211("bssid: %s\n",
- print_mac(mac, conf->bssid));
+ IWL_DEBUG_MAC80211("bssid: %pM\n", conf->bssid);
/*
* very dubious code was here; the probe filtering flag is never set:
@@ -6842,8 +6772,8 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
if (!conf->bssid) {
conf->bssid = priv->mac_addr;
memcpy(priv->bssid, priv->mac_addr, ETH_ALEN);
- IWL_DEBUG_MAC80211("bssid was set to: %s\n",
- print_mac(mac, conf->bssid));
+ IWL_DEBUG_MAC80211("bssid was set to: %pM\n",
+ conf->bssid);
}
if (priv->ibss_beacon)
dev_kfree_skb(priv->ibss_beacon);
@@ -6889,15 +6819,6 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
}
done:
- spin_lock_irqsave(&priv->lock, flags);
- if (!conf->ssid_len)
- memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
- else
- memcpy(priv->essid, conf->ssid, conf->ssid_len);
-
- priv->essid_len = conf->ssid_len;
- spin_unlock_irqrestore(&priv->lock, flags);
-
IWL_DEBUG_MAC80211("leave\n");
mutex_unlock(&priv->mutex);
@@ -6910,16 +6831,43 @@ static void iwl3945_configure_filter(struct ieee80211_hw *hw,
int mc_count, struct dev_addr_list *mc_list)
{
struct iwl3945_priv *priv = hw->priv;
+ __le32 *filter_flags = &priv->staging_rxon.filter_flags;
- if (changed_flags & (*total_flags) & FIF_OTHER_BSS) {
- IWL_DEBUG_MAC80211("Enter: type %d (0x%x, 0x%x)\n",
- NL80211_IFTYPE_MONITOR,
- changed_flags, *total_flags);
- /* queue work 'cuz mac80211 is holding a lock which
- * prevents us from issuing (synchronous) f/w cmds */
- queue_work(priv->workqueue, &priv->set_monitor);
+ IWL_DEBUG_MAC80211("Enter: changed: 0x%x, total: 0x%x\n",
+ changed_flags, *total_flags);
+
+ if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) {
+ if (*total_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS))
+ *filter_flags |= RXON_FILTER_PROMISC_MSK;
+ else
+ *filter_flags &= ~RXON_FILTER_PROMISC_MSK;
}
- *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI |
+ if (changed_flags & FIF_ALLMULTI) {
+ if (*total_flags & FIF_ALLMULTI)
+ *filter_flags |= RXON_FILTER_ACCEPT_GRP_MSK;
+ else
+ *filter_flags &= ~RXON_FILTER_ACCEPT_GRP_MSK;
+ }
+ if (changed_flags & FIF_CONTROL) {
+ if (*total_flags & FIF_CONTROL)
+ *filter_flags |= RXON_FILTER_CTL2HOST_MSK;
+ else
+ *filter_flags &= ~RXON_FILTER_CTL2HOST_MSK;
+ }
+ if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
+ if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
+ *filter_flags |= RXON_FILTER_BCON_AWARE_MSK;
+ else
+ *filter_flags &= ~RXON_FILTER_BCON_AWARE_MSK;
+ }
+
+ /* We avoid iwl_commit_rxon here to commit the new filter flags
+ * since mac80211 will call ieee80211_hw_config immediately.
+ * (mc_list is not supported at this time). Otherwise, we need to
+ * queue a background iwl_commit_rxon work.
+ */
+
+ *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
}
@@ -6940,8 +6888,6 @@ static void iwl3945_mac_remove_interface(struct ieee80211_hw *hw,
if (priv->vif == conf->vif) {
priv->vif = NULL;
memset(priv->bssid, 0, ETH_ALEN);
- memset(priv->essid, 0, IW_ESSID_MAX_SIZE);
- priv->essid_len = 0;
}
mutex_unlock(&priv->mutex);
@@ -7010,6 +6956,7 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
int rc = 0;
unsigned long flags;
struct iwl3945_priv *priv = hw->priv;
+ DECLARE_SSID_BUF(ssid_buf);
IWL_DEBUG_MAC80211("enter\n");
@@ -7022,12 +6969,6 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
goto out_unlock;
}
- if (priv->iw_mode == NL80211_IFTYPE_AP) { /* APs don't scan */
- rc = -EIO;
- IWL_ERROR("ERROR: APs don't scan\n");
- goto out_unlock;
- }
-
/* we don't schedule scan within next_scan_jiffies period */
if (priv->next_scan_jiffies &&
time_after(priv->next_scan_jiffies, jiffies)) {
@@ -7043,7 +6984,7 @@ static int iwl3945_mac_hw_scan(struct ieee80211_hw *hw, u8 *ssid, size_t len)
}
if (len) {
IWL_DEBUG_SCAN("direct scan for %s [%d]\n ",
- iwl3945_escape_essid(ssid, len), (int)len);
+ print_ssid(ssid_buf, ssid, len), (int)len);
priv->one_direct_scan = 1;
priv->direct_ssid_len = (u8)
@@ -7084,10 +7025,8 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
sta_id = iwl3945_hw_find_station(priv, addr);
if (sta_id == IWL_INVALID_STATION) {
- DECLARE_MAC_BUF(mac);
-
- IWL_DEBUG_MAC80211("leave - %s not in station map.\n",
- print_mac(mac, addr));
+ IWL_DEBUG_MAC80211("leave - %pM not in station map.\n",
+ addr);
return -EINVAL;
}
@@ -7143,11 +7082,6 @@ static int iwl3945_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
return 0;
}
- if (!priv->qos_data.qos_enable) {
- priv->qos_data.qos_active = 0;
- IWL_DEBUG_MAC80211("leave - qos not enabled\n");
- return 0;
- }
q = AC_NUM - 1 - queue;
spin_lock_irqsave(&priv->lock, flags);
@@ -7219,14 +7153,6 @@ static int iwl3945_mac_get_stats(struct ieee80211_hw *hw,
return 0;
}
-static u64 iwl3945_mac_get_tsf(struct ieee80211_hw *hw)
-{
- IWL_DEBUG_MAC80211("enter\n");
- IWL_DEBUG_MAC80211("leave\n");
-
- return 0;
-}
-
static void iwl3945_mac_reset_tsf(struct ieee80211_hw *hw)
{
struct iwl3945_priv *priv = hw->priv;
@@ -7292,18 +7218,15 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
struct iwl3945_priv *priv = hw->priv;
unsigned long flags;
- mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211("enter\n");
if (!iwl3945_is_ready_rf(priv)) {
IWL_DEBUG_MAC80211("leave - RF not ready\n");
- mutex_unlock(&priv->mutex);
return -EIO;
}
if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
IWL_DEBUG_MAC80211("leave - not IBSS\n");
- mutex_unlock(&priv->mutex);
return -EIO;
}
@@ -7323,7 +7246,6 @@ static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *sk
iwl3945_post_associate(priv);
- mutex_unlock(&priv->mutex);
return 0;
}
@@ -7792,7 +7714,7 @@ static DEVICE_ATTR(dump_events, S_IWUSR, NULL, dump_event_log);
/*****************************************************************************
*
- * driver setup and teardown
+ * driver setup and tear down
*
*****************************************************************************/
@@ -7810,7 +7732,6 @@ static void iwl3945_setup_deferred_work(struct iwl3945_priv *priv)
INIT_WORK(&priv->abort_scan, iwl3945_bg_abort_scan);
INIT_WORK(&priv->rf_kill, iwl3945_bg_rf_kill);
INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update);
- INIT_WORK(&priv->set_monitor, iwl3945_bg_set_monitor);
INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
INIT_DELAYED_WORK(&priv->scan_check, iwl3945_bg_scan_check);
@@ -7869,7 +7790,6 @@ static struct ieee80211_ops iwl3945_hw_ops = {
.get_stats = iwl3945_mac_get_stats,
.get_tx_stats = iwl3945_mac_get_tx_stats,
.conf_tx = iwl3945_mac_conf_tx,
- .get_tsf = iwl3945_mac_get_tsf,
.reset_tsf = iwl3945_mac_reset_tsf,
.bss_info_changed = iwl3945_bss_info_changed,
.hw_scan = iwl3945_mac_hw_scan
@@ -7882,7 +7802,10 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
struct ieee80211_hw *hw;
struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data);
unsigned long flags;
- DECLARE_MAC_BUF(mac);
+
+ /***********************
+ * 1. Allocating HW data
+ * ********************/
/* Disabling hardware scan means that mac80211 will perform scans
* "the hard way", rather than using device's scan. */
@@ -7907,48 +7830,41 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
err = -ENOMEM;
goto out;
}
- SET_IEEE80211_DEV(hw, &pdev->dev);
- hw->rate_control_algorithm = "iwl-3945-rs";
- hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
+ SET_IEEE80211_DEV(hw, &pdev->dev);
- IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
priv = hw->priv;
priv->hw = hw;
-
priv->pci_dev = pdev;
priv->cfg = cfg;
+ IWL_DEBUG_INFO("*** LOAD DRIVER ***\n");
+ hw->rate_control_algorithm = "iwl-3945-rs";
+ hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
+
/* Select antenna (may be helpful if only one antenna is connected) */
priv->antenna = (enum iwl3945_antenna)iwl3945_param_antenna;
#ifdef CONFIG_IWL3945_DEBUG
iwl3945_debug_level = iwl3945_param_debug;
atomic_set(&priv->restrict_refcnt, 0);
#endif
- priv->retry_rate = 1;
-
- priv->ibss_beacon = NULL;
/* Tell mac80211 our characteristics */
hw->flags = IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM;
hw->wiphy->interface_modes =
- BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC);
+ hw->wiphy->fw_handles_regulatory = true;
+
/* 4 EDCA QOS priorities */
hw->queues = 4;
- spin_lock_init(&priv->lock);
- spin_lock_init(&priv->power_data.lock);
- spin_lock_init(&priv->sta_lock);
- spin_lock_init(&priv->hcmd_lock);
-
- INIT_LIST_HEAD(&priv->free_frames);
-
- mutex_init(&priv->mutex);
+ /***************************
+ * 2. Initializing PCI bus
+ * *************************/
if (pci_enable_device(pdev)) {
err = -ENODEV;
goto out_ieee80211_free_hw;
@@ -7956,14 +7872,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
pci_set_master(pdev);
- /* Clear the driver's (not device's) station table */
- iwl3945_clear_stations_table(priv);
-
- priv->data_retry_limit = -1;
- priv->ieee_channels = NULL;
- priv->ieee_rates = NULL;
- priv->band = IEEE80211_BAND_2GHZ;
-
err = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (!err)
err = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
@@ -7977,10 +7885,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
if (err)
goto out_pci_disable_device;
- /* We disable the RETRY_TIMEOUT register (0x41) to keep
- * PCI Tx retries from interfering with C3 CPU state */
- pci_write_config_byte(pdev, 0x41, 0x00);
-
+ /***********************
+ * 3. Read REV Register
+ * ********************/
priv->hw_base = pci_iomap(pdev, 0, 0);
if (!priv->hw_base) {
err = -ENODEV;
@@ -7991,97 +7898,144 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
(unsigned long long) pci_resource_len(pdev, 0));
IWL_DEBUG_INFO("pci_resource_base = %p\n", priv->hw_base);
- /* Initialize module parameter values here */
+ /* We disable the RETRY_TIMEOUT register (0x41) to keep
+ * PCI Tx retries from interfering with C3 CPU state */
+ pci_write_config_byte(pdev, 0x41, 0x00);
- /* Disable radio (SW RF KILL) via parameter when loading driver */
- if (iwl3945_param_disable) {
- set_bit(STATUS_RF_KILL_SW, &priv->status);
- IWL_DEBUG_INFO("Radio disabled.\n");
- }
+ /* nic init */
+ iwl3945_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+ CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
- priv->iw_mode = NL80211_IFTYPE_STATION;
+ iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+ err = iwl3945_poll_direct_bit(priv, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+ if (err < 0) {
+ IWL_DEBUG_INFO("Failed to init the card\n");
+ goto out_remove_sysfs;
+ }
- printk(KERN_INFO DRV_NAME
- ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name);
+ /***********************
+ * 4. Read EEPROM
+ * ********************/
+ /* Read the EEPROM */
+ err = iwl3945_eeprom_init(priv);
+ if (err) {
+ IWL_ERROR("Unable to init EEPROM\n");
+ goto out_remove_sysfs;
+ }
+ /* MAC Address location in EEPROM same for 3945/4965 */
+ get_eeprom_mac(priv, priv->mac_addr);
+ IWL_DEBUG_INFO("MAC address: %pM\n", priv->mac_addr);
+ SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
+ /***********************
+ * 5. Setup HW Constants
+ * ********************/
/* Device-specific setup */
if (iwl3945_hw_set_hw_setting(priv)) {
IWL_ERROR("failed to set hw settings\n");
goto out_iounmap;
}
- if (iwl3945_param_qos_enable)
- priv->qos_data.qos_enable = 1;
+ /***********************
+ * 6. Setup priv
+ * ********************/
+ priv->retry_rate = 1;
+ priv->ibss_beacon = NULL;
+
+ spin_lock_init(&priv->lock);
+ spin_lock_init(&priv->power_data.lock);
+ spin_lock_init(&priv->sta_lock);
+ spin_lock_init(&priv->hcmd_lock);
+
+ INIT_LIST_HEAD(&priv->free_frames);
+ mutex_init(&priv->mutex);
+
+ /* Clear the driver's (not device's) station table */
+ iwl3945_clear_stations_table(priv);
+
+ priv->data_retry_limit = -1;
+ priv->ieee_channels = NULL;
+ priv->ieee_rates = NULL;
+ priv->band = IEEE80211_BAND_2GHZ;
+
+ priv->iw_mode = NL80211_IFTYPE_STATION;
iwl3945_reset_qos(priv);
priv->qos_data.qos_active = 0;
priv->qos_data.qos_cap.val = 0;
- iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
- iwl3945_setup_deferred_work(priv);
- iwl3945_setup_rx_handlers(priv);
priv->rates_mask = IWL_RATES_MASK;
/* If power management is turned on, default to AC mode */
priv->power_mode = IWL_POWER_AC;
priv->user_txpower_limit = IWL_DEFAULT_TX_POWER;
- spin_lock_irqsave(&priv->lock, flags);
- iwl3945_disable_interrupts(priv);
- spin_unlock_irqrestore(&priv->lock, flags);
-
- err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
+ err = iwl3945_init_channel_map(priv);
if (err) {
- IWL_ERROR("failed to create sysfs device attributes\n");
+ IWL_ERROR("initializing regulatory failed: %d\n", err);
goto out_release_irq;
}
- /* nic init */
- iwl3945_set_bit(priv, CSR_GIO_CHICKEN_BITS,
- CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
-
- iwl3945_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
- err = iwl3945_poll_bit(priv, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
- CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
- if (err < 0) {
- IWL_DEBUG_INFO("Failed to init the card\n");
- goto out_remove_sysfs;
- }
- /* Read the EEPROM */
- err = iwl3945_eeprom_init(priv);
+ err = iwl3945_init_geos(priv);
if (err) {
- IWL_ERROR("Unable to init EEPROM\n");
- goto out_remove_sysfs;
+ IWL_ERROR("initializing geos failed: %d\n", err);
+ goto out_free_channel_map;
}
- /* MAC Address location in EEPROM same for 3945/4965 */
- get_eeprom_mac(priv, priv->mac_addr);
- IWL_DEBUG_INFO("MAC address: %s\n", print_mac(mac, priv->mac_addr));
- SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr);
- err = iwl3945_init_channel_map(priv);
- if (err) {
- IWL_ERROR("initializing regulatory failed: %d\n", err);
- goto out_remove_sysfs;
+ printk(KERN_INFO DRV_NAME
+ ": Detected Intel Wireless WiFi Link %s\n", priv->cfg->name);
+
+ /***********************************
+ * 7. Initialize Module Parameters
+ * **********************************/
+
+ /* Initialize module parameter values here */
+ /* Disable radio (SW RF KILL) via parameter when loading driver */
+ if (iwl3945_param_disable) {
+ set_bit(STATUS_RF_KILL_SW, &priv->status);
+ IWL_DEBUG_INFO("Radio disabled.\n");
}
- err = iwl3945_init_geos(priv);
+
+ /***********************
+ * 8. Setup Services
+ * ********************/
+
+ spin_lock_irqsave(&priv->lock, flags);
+ iwl3945_disable_interrupts(priv);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
if (err) {
- IWL_ERROR("initializing geos failed: %d\n", err);
- goto out_free_channel_map;
+ IWL_ERROR("failed to create sysfs device attributes\n");
+ goto out_free_geos;
}
+ iwl3945_set_rxon_channel(priv, IEEE80211_BAND_2GHZ, 6);
+ iwl3945_setup_deferred_work(priv);
+ iwl3945_setup_rx_handlers(priv);
+
+ /***********************
+ * 9. Conclude
+ * ********************/
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+
+ /*********************************
+ * 10. Setup and Register mac80211
+ * *******************************/
+
err = ieee80211_register_hw(priv->hw);
if (err) {
IWL_ERROR("Failed to register network device (error %d)\n", err);
- goto out_free_geos;
+ goto out_remove_sysfs;
}
priv->hw->conf.beacon_int = 100;
priv->mac80211_registered = 1;
- pci_save_state(pdev);
- pci_disable_device(pdev);
+
err = iwl3945_rfkill_init(priv);
if (err)
@@ -8090,12 +8044,13 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
return 0;
+ out_remove_sysfs:
+ sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
out_free_geos:
iwl3945_free_geos(priv);
out_free_channel_map:
iwl3945_free_channel_map(priv);
- out_remove_sysfs:
- sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
+
out_release_irq:
destroy_workqueue(priv->workqueue);
@@ -8222,7 +8177,7 @@ static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return 0;
- IWL_DEBUG_RF_KILL("we recieved soft RFKILL set to state %d\n", state);
+ IWL_DEBUG_RF_KILL("we received soft RFKILL set to state %d\n", state);
mutex_lock(&priv->mutex);
switch (state) {
@@ -8237,7 +8192,7 @@ static int iwl3945_rfkill_soft_rf_kill(void *data, enum rfkill_state state)
iwl3945_radio_kill_sw(priv, 1);
break;
default:
- IWL_WARNING("we recieved unexpected RFKILL state %d\n", state);
+ IWL_WARNING("we received unexpected RFKILL state %d\n", state);
break;
}
out_unlock:
@@ -8379,7 +8334,7 @@ static void __exit iwl3945_exit(void)
iwl3945_rate_control_unregister();
}
-MODULE_FIRMWARE("iwlwifi-3945" IWL3945_UCODE_API ".ucode");
+MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX));
module_param_named(antenna, iwl3945_param_antenna, int, 0444);
MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
@@ -8388,7 +8343,7 @@ MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])");
module_param_named(hwcrypto, iwl3945_param_hwcrypto, int, 0444);
MODULE_PARM_DESC(hwcrypto,
"using hardware crypto engine (default 0 [software])\n");
-module_param_named(debug, iwl3945_param_debug, int, 0444);
+module_param_named(debug, iwl3945_param_debug, uint, 0444);
MODULE_PARM_DESC(debug, "debug output mask");
module_param_named(disable_hw_scan, iwl3945_param_disable_hw_scan, int, 0444);
MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
@@ -8396,9 +8351,5 @@ MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)");
module_param_named(queues_num, iwl3945_param_queues_num, int, 0444);
MODULE_PARM_DESC(queues_num, "number of hw queues.");
-/* QoS */
-module_param_named(qos_enable, iwl3945_param_qos_enable, int, 0444);
-MODULE_PARM_DESC(qos_enable, "enable all QoS functionality");
-
module_exit(iwl3945_exit);
module_init(iwl3945_init);
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c
index 92be60415d04..a0e440cd8967 100644
--- a/drivers/net/wireless/libertas/assoc.c
+++ b/drivers/net/wireless/libertas/assoc.c
@@ -1,6 +1,10 @@
/* Copyright (C) 2006, Red Hat, Inc. */
+#include <linux/types.h>
#include <linux/etherdevice.h>
+#include <linux/ieee80211.h>
+#include <linux/if_arp.h>
+#include <net/lib80211.h>
#include "assoc.h"
#include "decl.h"
@@ -151,18 +155,18 @@ static int lbs_adhoc_join(struct lbs_private *priv,
struct cmd_ds_802_11_ad_hoc_join cmd;
struct bss_descriptor *bss = &assoc_req->bss;
u8 preamble = RADIO_PREAMBLE_LONG;
- DECLARE_MAC_BUF(mac);
+ DECLARE_SSID_BUF(ssid);
u16 ratesize = 0;
int ret = 0;
lbs_deb_enter(LBS_DEB_ASSOC);
lbs_deb_join("current SSID '%s', ssid length %u\n",
- escape_essid(priv->curbssparams.ssid,
+ print_ssid(ssid, priv->curbssparams.ssid,
priv->curbssparams.ssid_len),
priv->curbssparams.ssid_len);
lbs_deb_join("requested ssid '%s', ssid length %u\n",
- escape_essid(bss->ssid, bss->ssid_len),
+ print_ssid(ssid, bss->ssid, bss->ssid_len),
bss->ssid_len);
/* check if the requested SSID is already joined */
@@ -226,8 +230,8 @@ static int lbs_adhoc_join(struct lbs_private *priv,
bss->capability, CAPINFO_MASK);
/* information on BSSID descriptor passed to FW */
- lbs_deb_join("ADHOC_J_CMD: BSSID = %s, SSID = '%s'\n",
- print_mac(mac, cmd.bss.bssid), cmd.bss.ssid);
+ lbs_deb_join("ADHOC_J_CMD: BSSID = %pM, SSID = '%s'\n",
+ cmd.bss.bssid, cmd.bss.ssid);
/* Only v8 and below support setting these */
if (priv->fwrelease < 0x09000000) {
@@ -307,6 +311,7 @@ static int lbs_adhoc_start(struct lbs_private *priv,
size_t ratesize = 0;
u16 tmpcap = 0;
int ret = 0;
+ DECLARE_SSID_BUF(ssid);
lbs_deb_enter(LBS_DEB_ASSOC);
@@ -326,7 +331,7 @@ static int lbs_adhoc_start(struct lbs_private *priv,
memcpy(cmd.ssid, assoc_req->ssid, assoc_req->ssid_len);
lbs_deb_join("ADHOC_START: SSID '%s', ssid length %u\n",
- escape_essid(assoc_req->ssid, assoc_req->ssid_len),
+ print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len),
assoc_req->ssid_len);
cmd.bsstype = CMD_BSS_TYPE_IBSS;
@@ -338,12 +343,12 @@ static int lbs_adhoc_start(struct lbs_private *priv,
WARN_ON(!assoc_req->channel);
/* set Physical parameter set */
- cmd.phyparamset.dsparamset.elementid = MFIE_TYPE_DS_SET;
+ cmd.phyparamset.dsparamset.elementid = WLAN_EID_DS_PARAMS;
cmd.phyparamset.dsparamset.len = 1;
cmd.phyparamset.dsparamset.currentchan = assoc_req->channel;
/* set IBSS parameter set */
- cmd.ssparamset.ibssparamset.elementid = MFIE_TYPE_IBSS_SET;
+ cmd.ssparamset.ibssparamset.elementid = WLAN_EID_IBSS_PARAMS;
cmd.ssparamset.ibssparamset.len = 2;
cmd.ssparamset.ibssparamset.atimwindow = 0;
@@ -427,8 +432,8 @@ static inline int match_bss_no_security(struct lbs_802_11_security *secinfo,
{
if (!secinfo->wep_enabled && !secinfo->WPAenabled
&& !secinfo->WPA2enabled
- && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC
- && match_bss->rsn_ie[0] != MFIE_TYPE_RSN
+ && match_bss->wpa_ie[0] != WLAN_EID_GENERIC
+ && match_bss->rsn_ie[0] != WLAN_EID_RSN
&& !(match_bss->capability & WLAN_CAPABILITY_PRIVACY))
return 1;
else
@@ -450,7 +455,7 @@ static inline int match_bss_wpa(struct lbs_802_11_security *secinfo,
struct bss_descriptor *match_bss)
{
if (!secinfo->wep_enabled && secinfo->WPAenabled
- && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC)
+ && (match_bss->wpa_ie[0] == WLAN_EID_GENERIC)
/* privacy bit may NOT be set in some APs like LinkSys WRT54G
&& (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
)
@@ -463,7 +468,7 @@ static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo,
struct bss_descriptor *match_bss)
{
if (!secinfo->wep_enabled && secinfo->WPA2enabled &&
- (match_bss->rsn_ie[0] == MFIE_TYPE_RSN)
+ (match_bss->rsn_ie[0] == WLAN_EID_RSN)
/* privacy bit may NOT be set in some APs like LinkSys WRT54G
(match_bss->capability & WLAN_CAPABILITY_PRIVACY) */
)
@@ -477,8 +482,8 @@ static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo,
{
if (!secinfo->wep_enabled && !secinfo->WPAenabled
&& !secinfo->WPA2enabled
- && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC)
- && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN)
+ && (match_bss->wpa_ie[0] != WLAN_EID_GENERIC)
+ && (match_bss->rsn_ie[0] != WLAN_EID_RSN)
&& (match_bss->capability & WLAN_CAPABILITY_PRIVACY))
return 1;
else
@@ -694,6 +699,7 @@ static int assoc_helper_essid(struct lbs_private *priv,
int ret = 0;
struct bss_descriptor * bss;
int channel = -1;
+ DECLARE_SSID_BUF(ssid);
lbs_deb_enter(LBS_DEB_ASSOC);
@@ -705,7 +711,7 @@ static int assoc_helper_essid(struct lbs_private *priv,
channel = assoc_req->channel;
lbs_deb_assoc("SSID '%s' requested\n",
- escape_essid(assoc_req->ssid, assoc_req->ssid_len));
+ print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len));
if (assoc_req->mode == IW_MODE_INFRA) {
lbs_send_specific_ssid_scan(priv, assoc_req->ssid,
assoc_req->ssid_len);
@@ -752,17 +758,15 @@ static int assoc_helper_bssid(struct lbs_private *priv,
{
int ret = 0;
struct bss_descriptor * bss;
- DECLARE_MAC_BUF(mac);
- lbs_deb_enter_args(LBS_DEB_ASSOC, "BSSID %s",
- print_mac(mac, assoc_req->bssid));
+ lbs_deb_enter_args(LBS_DEB_ASSOC, "BSSID %pM", assoc_req->bssid);
/* Search for index position in list for requested MAC */
bss = lbs_find_bssid_in_list(priv, assoc_req->bssid,
assoc_req->mode);
if (bss == NULL) {
- lbs_deb_assoc("ASSOC: WAP: BSSID %s not found, "
- "cannot associate.\n", print_mac(mac, assoc_req->bssid));
+ lbs_deb_assoc("ASSOC: WAP: BSSID %pM not found, "
+ "cannot associate.\n", assoc_req->bssid);
goto out;
}
@@ -1208,7 +1212,7 @@ void lbs_association_worker(struct work_struct *work)
struct assoc_request * assoc_req = NULL;
int ret = 0;
int find_any_ssid = 0;
- DECLARE_MAC_BUF(mac);
+ DECLARE_SSID_BUF(ssid);
lbs_deb_enter(LBS_DEB_ASSOC);
@@ -1228,13 +1232,13 @@ void lbs_association_worker(struct work_struct *work)
" chann: %d\n"
" band: %d\n"
" mode: %d\n"
- " BSSID: %s\n"
+ " BSSID: %pM\n"
" secinfo: %s%s%s\n"
" auth_mode: %d\n",
assoc_req->flags,
- escape_essid(assoc_req->ssid, assoc_req->ssid_len),
+ print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len),
assoc_req->channel, assoc_req->band, assoc_req->mode,
- print_mac(mac, assoc_req->bssid),
+ assoc_req->bssid,
assoc_req->secinfo.WPAenabled ? " WPA" : "",
assoc_req->secinfo.WPA2enabled ? " WPA2" : "",
assoc_req->secinfo.wep_enabled ? " WEP" : "",
@@ -1357,8 +1361,8 @@ void lbs_association_worker(struct work_struct *work)
}
if (success) {
- lbs_deb_assoc("associated to %s\n",
- print_mac(mac, priv->curbssparams.bssid));
+ lbs_deb_assoc("associated to %pM\n",
+ priv->curbssparams.bssid);
lbs_prepare_and_send_command(priv,
CMD_802_11_RSSI,
0, CMD_OPTION_WAITFORRSP, 0, NULL);
@@ -1478,7 +1482,6 @@ int lbs_cmd_80211_authenticate(struct lbs_private *priv,
struct cmd_ds_802_11_authenticate *pauthenticate = &cmd->params.auth;
int ret = -1;
u8 *bssid = pdata_buf;
- DECLARE_MAC_BUF(mac);
lbs_deb_enter(LBS_DEB_JOIN);
@@ -1505,8 +1508,8 @@ int lbs_cmd_80211_authenticate(struct lbs_private *priv,
memcpy(pauthenticate->macaddr, bssid, ETH_ALEN);
- lbs_deb_join("AUTH_CMD: BSSID %s, auth 0x%x\n",
- print_mac(mac, bssid), pauthenticate->authtype);
+ lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n",
+ bssid, pauthenticate->authtype);
ret = 0;
out:
@@ -1770,7 +1773,7 @@ static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp)
struct cmd_ds_802_11_ad_hoc_result *adhoc_resp;
union iwreq_data wrqu;
struct bss_descriptor *bss;
- DECLARE_MAC_BUF(mac);
+ DECLARE_SSID_BUF(ssid);
lbs_deb_enter(LBS_DEB_JOIN);
@@ -1819,9 +1822,9 @@ static int lbs_adhoc_post(struct lbs_private *priv, struct cmd_header *resp)
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL);
- lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %s, channel %d\n",
- escape_essid(bss->ssid, bss->ssid_len),
- print_mac(mac, priv->curbssparams.bssid),
+ lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n",
+ print_ssid(ssid, bss->ssid, bss->ssid_len),
+ priv->curbssparams.bssid,
priv->curbssparams.channel);
done:
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 8265c7d25edc..639dd02d3d31 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -4,7 +4,7 @@
*/
#include <net/iw_handler.h>
-#include <net/ieee80211.h>
+#include <net/lib80211.h>
#include <linux/kfifo.h>
#include "host.h"
#include "hostcmd.h"
@@ -87,7 +87,6 @@ int lbs_update_hw_spec(struct lbs_private *priv)
struct cmd_ds_get_hw_spec cmd;
int ret = -1;
u32 i;
- DECLARE_MAC_BUF(mac);
lbs_deb_enter(LBS_DEB_CMD);
@@ -110,8 +109,8 @@ int lbs_update_hw_spec(struct lbs_private *priv)
* CF card firmware 5.0.16p0: cap 0x00000303
* USB dongle firmware 5.110.17p2: cap 0x00000303
*/
- lbs_pr_info("%s, fw %u.%u.%up%u, cap 0x%08x\n",
- print_mac(mac, cmd.permanentaddr),
+ lbs_pr_info("%pM, fw %u.%u.%up%u, cap 0x%08x\n",
+ cmd.permanentaddr,
priv->fwrelease >> 24 & 0xff,
priv->fwrelease >> 16 & 0xff,
priv->fwrelease >> 8 & 0xff,
@@ -160,7 +159,8 @@ out:
return ret;
}
-int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria)
+int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
+ struct wol_config *p_wol_config)
{
struct cmd_ds_host_sleep cmd_config;
int ret;
@@ -170,10 +170,21 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria)
cmd_config.gpio = priv->wol_gpio;
cmd_config.gap = priv->wol_gap;
+ if (p_wol_config != NULL)
+ memcpy((uint8_t *)&cmd_config.wol_conf, (uint8_t *)p_wol_config,
+ sizeof(struct wol_config));
+ else
+ cmd_config.wol_conf.action = CMD_ACT_ACTION_NONE;
+
ret = lbs_cmd_with_response(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config);
if (!ret) {
- lbs_deb_cmd("Set WOL criteria to %x\n", criteria);
- priv->wol_criteria = criteria;
+ if (criteria) {
+ lbs_deb_cmd("Set WOL criteria to %x\n", criteria);
+ priv->wol_criteria = criteria;
+ } else
+ memcpy((uint8_t *) p_wol_config,
+ (uint8_t *)&cmd_config.wol_conf,
+ sizeof(struct wol_config));
} else {
lbs_pr_info("HOST_SLEEP_CFG failed %d\n", ret);
}
@@ -1063,6 +1074,7 @@ int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan)
{
struct cmd_ds_mesh_config cmd;
struct mrvl_meshie *ie;
+ DECLARE_SSID_BUF(ssid);
memset(&cmd, 0, sizeof(cmd));
cmd.channel = cpu_to_le16(chan);
@@ -1070,7 +1082,7 @@ int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan)
switch (action) {
case CMD_ACT_MESH_CONFIG_START:
- ie->hdr.id = MFIE_TYPE_GENERIC;
+ ie->id = WLAN_EID_GENERIC;
ie->val.oui[0] = 0x00;
ie->val.oui[1] = 0x50;
ie->val.oui[2] = 0x43;
@@ -1082,7 +1094,7 @@ int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan)
ie->val.mesh_capability = MARVELL_MESH_CAPABILITY;
ie->val.mesh_id_len = priv->mesh_ssid_len;
memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len);
- ie->hdr.len = sizeof(struct mrvl_meshie_val) -
+ ie->len = sizeof(struct mrvl_meshie_val) -
IW_ESSID_MAX_SIZE + priv->mesh_ssid_len;
cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val));
break;
@@ -1093,7 +1105,7 @@ int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan)
}
lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
action, priv->mesh_tlv, chan,
- escape_essid(priv->mesh_ssid, priv->mesh_ssid_len));
+ print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len));
return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
}
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h
index 36be4c9703e0..392e578ca095 100644
--- a/drivers/net/wireless/libertas/cmd.h
+++ b/drivers/net/wireless/libertas/cmd.h
@@ -56,7 +56,8 @@ int lbs_mesh_config_send(struct lbs_private *priv,
uint16_t action, uint16_t type);
int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan);
-int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria);
+int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
+ struct wol_config *p_wol_config);
int lbs_suspend(struct lbs_private *priv);
void lbs_resume(struct lbs_private *priv);
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c
index 0aa0ce3b2c42..ec4efd7ff3c8 100644
--- a/drivers/net/wireless/libertas/debugfs.c
+++ b/drivers/net/wireless/libertas/debugfs.c
@@ -5,6 +5,7 @@
#include <linux/mm.h>
#include <linux/string.h>
#include <net/iw_handler.h>
+#include <net/lib80211.h>
#include "dev.h"
#include "decl.h"
@@ -65,7 +66,7 @@ static ssize_t lbs_getscantable(struct file *file, char __user *userbuf,
int numscansdone = 0, res;
unsigned long addr = get_zeroed_page(GFP_KERNEL);
char *buf = (char *)addr;
- DECLARE_MAC_BUF(mac);
+ DECLARE_SSID_BUF(ssid);
struct bss_descriptor * iter_bss;
pos += snprintf(buf+pos, len-pos,
@@ -77,17 +78,17 @@ static ssize_t lbs_getscantable(struct file *file, char __user *userbuf,
u16 privacy = (iter_bss->capability & WLAN_CAPABILITY_PRIVACY);
u16 spectrum_mgmt = (iter_bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT);
- pos += snprintf(buf+pos, len-pos,
- "%02u| %03d | %04d | %s |",
+ pos += snprintf(buf+pos, len-pos, "%02u| %03d | %04d | %pM |",
numscansdone, iter_bss->channel, iter_bss->rssi,
- print_mac(mac, iter_bss->bssid));
+ iter_bss->bssid);
pos += snprintf(buf+pos, len-pos, " %04x-", iter_bss->capability);
pos += snprintf(buf+pos, len-pos, "%c%c%c |",
ibss ? 'A' : 'I', privacy ? 'P' : ' ',
spectrum_mgmt ? 'S' : ' ');
pos += snprintf(buf+pos, len-pos, " %04d |", SCAN_RSSI(iter_bss->rssi));
pos += snprintf(buf+pos, len-pos, " %s\n",
- escape_essid(iter_bss->ssid, iter_bss->ssid_len));
+ print_ssid(ssid, iter_bss->ssid,
+ iter_bss->ssid_len));
numscansdone++;
}
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index 1a8888cceadc..0b84bdca0726 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -74,8 +74,4 @@ void lbs_host_to_card_done(struct lbs_private *priv);
int lbs_update_channel(struct lbs_private *priv);
-#ifndef CONFIG_IEEE80211
-const char *escape_essid(const char *essid, u8 essid_len);
-#endif
-
#endif
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index 076a636e8f62..c364e4c01d1b 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -79,7 +79,7 @@ do { if ((lbs_debug & (grp)) == (grp)) \
#define lbs_deb_tx(fmt, args...) LBS_DEB_LL(LBS_DEB_TX, " tx", fmt, ##args)
#define lbs_deb_fw(fmt, args...) LBS_DEB_LL(LBS_DEB_FW, " fw", fmt, ##args)
#define lbs_deb_usb(fmt, args...) LBS_DEB_LL(LBS_DEB_USB, " usb", fmt, ##args)
-#define lbs_deb_usbd(dev, fmt, args...) LBS_DEB_LL(LBS_DEB_USB, " usbd", "%s:" fmt, (dev)->bus_id, ##args)
+#define lbs_deb_usbd(dev, fmt, args...) LBS_DEB_LL(LBS_DEB_USB, " usbd", "%s:" fmt, dev_name(dev), ##args)
#define lbs_deb_cs(fmt, args...) LBS_DEB_LL(LBS_DEB_CS, " cs", fmt, ##args)
#define lbs_deb_thread(fmt, args...) LBS_DEB_LL(LBS_DEB_THREAD, " thread", fmt, ##args)
#define lbs_deb_sdio(fmt, args...) LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args)
@@ -149,6 +149,18 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
#define EHS_WAKE_ON_MAC_EVENT 0x0004
#define EHS_WAKE_ON_MULTICAST_DATA 0x0008
#define EHS_REMOVE_WAKEUP 0xFFFFFFFF
+/* Wake rules for Host_Sleep_CFG command */
+#define WOL_RULE_NET_TYPE_INFRA_OR_IBSS 0x00
+#define WOL_RULE_NET_TYPE_MESH 0x10
+#define WOL_RULE_ADDR_TYPE_BCAST 0x01
+#define WOL_RULE_ADDR_TYPE_MCAST 0x08
+#define WOL_RULE_ADDR_TYPE_UCAST 0x02
+#define WOL_RULE_OP_AND 0x01
+#define WOL_RULE_OP_OR 0x02
+#define WOL_RULE_OP_INVALID 0xFF
+#define WOL_RESULT_VALID_CMD 0
+#define WOL_RESULT_NOSPC_ERR 1
+#define WOL_RESULT_EEXIST_ERR 2
/** Misc constants */
/* This section defines 802.11 specific contants */
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index f6f3753da303..dd682c4cfde8 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -10,7 +10,6 @@
#include <linux/wireless.h>
#include <linux/ethtool.h>
#include <linux/debugfs.h>
-#include <net/ieee80211.h>
#include "defs.h"
#include "hostcmd.h"
@@ -278,6 +277,12 @@ struct lbs_private {
struct enc_key wpa_mcast_key;
struct enc_key wpa_unicast_key;
+/*
+ * In theory, the IE is limited to the IE length, 255,
+ * but in practice 64 bytes are enough.
+ */
+#define MAX_WPA_IE_LEN 64
+
/** WPA Information Elements*/
u8 wpa_ie[MAX_WPA_IE_LEN];
u8 wpa_ie_len;
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
index 688d60de55cb..61d2f50470c8 100644
--- a/drivers/net/wireless/libertas/ethtool.c
+++ b/drivers/net/wireless/libertas/ethtool.c
@@ -23,7 +23,7 @@ static const char * mesh_stat_strings[]= {
static void lbs_ethtool_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
- struct lbs_private *priv = (struct lbs_private *) dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
snprintf(info->fw_version, 32, "%u.%u.%u.p%u",
priv->fwrelease >> 24 & 0xff,
@@ -47,7 +47,7 @@ static int lbs_ethtool_get_eeprom_len(struct net_device *dev)
static int lbs_ethtool_get_eeprom(struct net_device *dev,
struct ethtool_eeprom *eeprom, u8 * bytes)
{
- struct lbs_private *priv = (struct lbs_private *) dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
struct cmd_ds_802_11_eeprom_access cmd;
int ret;
@@ -76,7 +76,7 @@ out:
static void lbs_ethtool_get_stats(struct net_device *dev,
struct ethtool_stats *stats, uint64_t *data)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
struct cmd_ds_mesh_access mesh_access;
int ret;
@@ -113,7 +113,7 @@ static void lbs_ethtool_get_stats(struct net_device *dev,
static int lbs_ethtool_get_sset_count(struct net_device *dev, int sset)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
if (sset == ETH_SS_STATS && dev == priv->mesh_dev)
return MESH_STATS_NUM;
@@ -143,7 +143,7 @@ static void lbs_ethtool_get_strings(struct net_device *dev,
static void lbs_ethtool_get_wol(struct net_device *dev,
struct ethtool_wolinfo *wol)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
if (priv->wol_criteria == 0xffffffff) {
/* Interface driver didn't configure wake */
@@ -166,7 +166,7 @@ static void lbs_ethtool_get_wol(struct net_device *dev,
static int lbs_ethtool_set_wol(struct net_device *dev,
struct ethtool_wolinfo *wol)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
uint32_t criteria = 0;
if (priv->wol_criteria == 0xffffffff && wol->wolopts)
@@ -180,7 +180,7 @@ static int lbs_ethtool_set_wol(struct net_device *dev,
if (wol->wolopts & WAKE_BCAST) criteria |= EHS_WAKE_ON_BROADCAST_DATA;
if (wol->wolopts & WAKE_PHY) criteria |= EHS_WAKE_ON_MAC_EVENT;
- return lbs_host_sleep_cfg(priv, criteria);
+ return lbs_host_sleep_cfg(priv, criteria, (struct wol_config *)NULL);
}
struct ethtool_ops lbs_ethtool_ops = {
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index 5004d7679c02..277ff1975bde 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -220,6 +220,14 @@ enum cmd_fwt_access_opts {
CMD_ACT_FWT_ACCESS_TIME,
};
+/* Define action or option for CMD_802_11_HOST_SLEEP_CFG */
+enum cmd_wol_cfg_opts {
+ CMD_ACT_ACTION_NONE = 0,
+ CMD_ACT_SET_WOL_RULE,
+ CMD_ACT_GET_WOL_RULE,
+ CMD_ACT_RESET_WOL_RULE,
+};
+
/* Define action or option for CMD_MESH_ACCESS */
enum cmd_mesh_access_opts {
CMD_ACT_MESH_GET_TTL = 1,
@@ -237,6 +245,7 @@ enum cmd_mesh_access_opts {
CMD_ACT_MESH_GET_ROUTE_EXP,
CMD_ACT_MESH_SET_AUTOSTART_ENABLED,
CMD_ACT_MESH_GET_AUTOSTART_ENABLED,
+ CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT = 17,
};
/* Define actions and types for CMD_MESH_CONFIG */
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
index d9f9a12a739e..e173b1b46c23 100644
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ b/drivers/net/wireless/libertas/hostcmd.h
@@ -580,13 +580,37 @@ struct MrvlIEtype_keyParamSet {
u8 key[32];
};
+#define MAX_WOL_RULES 16
+
+struct host_wol_rule {
+ uint8_t rule_no;
+ uint8_t rule_ops;
+ __le16 sig_offset;
+ __le16 sig_length;
+ __le16 reserve;
+ __be32 sig_mask;
+ __be32 signature;
+};
+
+struct wol_config {
+ uint8_t action;
+ uint8_t pattern;
+ uint8_t no_rules_in_cmd;
+ uint8_t result;
+ struct host_wol_rule rule[MAX_WOL_RULES];
+};
+
+
struct cmd_ds_host_sleep {
struct cmd_header hdr;
__le32 criteria;
uint8_t gpio;
- uint8_t gap;
+ uint16_t gap;
+ struct wol_config wol_conf;
} __attribute__ ((packed));
+
+
struct cmd_ds_802_11_key_material {
struct cmd_header hdr;
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index b54e2ea8346b..4519d7314f47 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -26,6 +26,7 @@
* if_sdio_card_to_host() to pad the data.
*/
+#include <linux/kernel.h>
#include <linux/moduleparam.h>
#include <linux/firmware.h>
#include <linux/netdevice.h>
@@ -581,7 +582,7 @@ static int if_sdio_prog_real(struct if_sdio_card *card)
chunk_size, (chunk_size + 31) / 32 * 32);
*/
ret = sdio_writesb(card->func, card->ioport,
- chunk_buffer, (chunk_size + 31) / 32 * 32);
+ chunk_buffer, roundup(chunk_size, 32));
if (ret)
goto release;
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index cafbccb74143..2fc637ad85c7 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -59,7 +59,7 @@ static int if_usb_reset_device(struct if_usb_card *cardp);
static ssize_t if_usb_firmware_set(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- struct lbs_private *priv = to_net_dev(dev)->priv;
+ struct lbs_private *priv = netdev_priv(to_net_dev(dev));
struct if_usb_card *cardp = priv->card;
char fwname[FIRMWARE_NAME_MAX];
int ret;
@@ -86,7 +86,7 @@ static DEVICE_ATTR(lbs_flash_fw, 0200, NULL, if_usb_firmware_set);
static ssize_t if_usb_boot2_set(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- struct lbs_private *priv = to_net_dev(dev)->priv;
+ struct lbs_private *priv = netdev_priv(to_net_dev(dev));
struct if_usb_card *cardp = priv->card;
char fwname[FIRMWARE_NAME_MAX];
int ret;
@@ -178,7 +178,8 @@ static void if_usb_setup_firmware(struct lbs_private *priv)
priv->wol_gpio = 2; /* Wake via GPIO2... */
priv->wol_gap = 20; /* ... after 20ms */
- lbs_host_sleep_cfg(priv, EHS_WAKE_ON_UNICAST_DATA);
+ lbs_host_sleep_cfg(priv, EHS_WAKE_ON_UNICAST_DATA,
+ (struct wol_config *) NULL);
wake_method.hdr.size = cpu_to_le16(sizeof(wake_method));
wake_method.action = cpu_to_le16(CMD_ACT_GET);
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 73dc8c72402a..3dba83679444 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -12,9 +12,8 @@
#include <linux/kthread.h>
#include <linux/kfifo.h>
#include <linux/stddef.h>
-
+#include <linux/ieee80211.h>
#include <net/iw_handler.h>
-#include <net/ieee80211.h>
#include "host.h"
#include "decl.h"
@@ -223,7 +222,7 @@ u8 lbs_data_rate_to_fw_index(u32 rate)
static ssize_t lbs_anycast_get(struct device *dev,
struct device_attribute *attr, char * buf)
{
- struct lbs_private *priv = to_net_dev(dev)->priv;
+ struct lbs_private *priv = netdev_priv(to_net_dev(dev));
struct cmd_ds_mesh_access mesh_access;
int ret;
@@ -242,7 +241,7 @@ static ssize_t lbs_anycast_get(struct device *dev,
static ssize_t lbs_anycast_set(struct device *dev,
struct device_attribute *attr, const char * buf, size_t count)
{
- struct lbs_private *priv = to_net_dev(dev)->priv;
+ struct lbs_private *priv = netdev_priv(to_net_dev(dev));
struct cmd_ds_mesh_access mesh_access;
uint32_t datum;
int ret;
@@ -258,6 +257,58 @@ static ssize_t lbs_anycast_set(struct device *dev,
return strlen(buf);
}
+/**
+ * @brief Get function for sysfs attribute prb_rsp_limit
+ */
+static ssize_t lbs_prb_rsp_limit_get(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct lbs_private *priv = netdev_priv(to_net_dev(dev));
+ struct cmd_ds_mesh_access mesh_access;
+ int ret;
+ u32 retry_limit;
+
+ memset(&mesh_access, 0, sizeof(mesh_access));
+ mesh_access.data[0] = cpu_to_le32(CMD_ACT_GET);
+
+ ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
+ &mesh_access);
+ if (ret)
+ return ret;
+
+ retry_limit = le32_to_cpu(mesh_access.data[1]);
+ return snprintf(buf, 10, "%d\n", retry_limit);
+}
+
+/**
+ * @brief Set function for sysfs attribute prb_rsp_limit
+ */
+static ssize_t lbs_prb_rsp_limit_set(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct lbs_private *priv = netdev_priv(to_net_dev(dev));
+ struct cmd_ds_mesh_access mesh_access;
+ int ret;
+ unsigned long retry_limit;
+
+ memset(&mesh_access, 0, sizeof(mesh_access));
+ mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET);
+
+ if (!strict_strtoul(buf, 10, &retry_limit))
+ return -ENOTSUPP;
+ if (retry_limit > 15)
+ return -ENOTSUPP;
+
+ mesh_access.data[1] = cpu_to_le32(retry_limit);
+
+ ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
+ &mesh_access);
+ if (ret)
+ return ret;
+
+ return strlen(buf);
+}
+
static int lbs_add_rtap(struct lbs_private *priv);
static void lbs_remove_rtap(struct lbs_private *priv);
static int lbs_add_mesh(struct lbs_private *priv);
@@ -270,7 +321,7 @@ static void lbs_remove_mesh(struct lbs_private *priv);
static ssize_t lbs_rtap_get(struct device *dev,
struct device_attribute *attr, char * buf)
{
- struct lbs_private *priv = to_net_dev(dev)->priv;
+ struct lbs_private *priv = netdev_priv(to_net_dev(dev));
return snprintf(buf, 5, "0x%X\n", priv->monitormode);
}
@@ -281,7 +332,7 @@ static ssize_t lbs_rtap_set(struct device *dev,
struct device_attribute *attr, const char * buf, size_t count)
{
int monitor_mode;
- struct lbs_private *priv = to_net_dev(dev)->priv;
+ struct lbs_private *priv = netdev_priv(to_net_dev(dev));
sscanf(buf, "%x", &monitor_mode);
if (monitor_mode) {
@@ -332,7 +383,7 @@ static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set );
static ssize_t lbs_mesh_get(struct device *dev,
struct device_attribute *attr, char * buf)
{
- struct lbs_private *priv = to_net_dev(dev)->priv;
+ struct lbs_private *priv = netdev_priv(to_net_dev(dev));
return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev);
}
@@ -342,7 +393,7 @@ static ssize_t lbs_mesh_get(struct device *dev,
static ssize_t lbs_mesh_set(struct device *dev,
struct device_attribute *attr, const char * buf, size_t count)
{
- struct lbs_private *priv = to_net_dev(dev)->priv;
+ struct lbs_private *priv = netdev_priv(to_net_dev(dev));
int enable;
int ret, action = CMD_ACT_MESH_CONFIG_STOP;
@@ -376,8 +427,16 @@ static DEVICE_ATTR(lbs_mesh, 0644, lbs_mesh_get, lbs_mesh_set);
*/
static DEVICE_ATTR(anycast_mask, 0644, lbs_anycast_get, lbs_anycast_set);
+/**
+ * prb_rsp_limit attribute to be exported per mshX interface
+ * through sysfs (/sys/class/net/mshX/prb_rsp_limit)
+ */
+static DEVICE_ATTR(prb_rsp_limit, 0644, lbs_prb_rsp_limit_get,
+ lbs_prb_rsp_limit_set);
+
static struct attribute *lbs_mesh_sysfs_entries[] = {
&dev_attr_anycast_mask.attr,
+ &dev_attr_prb_rsp_limit.attr,
NULL,
};
@@ -393,7 +452,7 @@ static struct attribute_group lbs_mesh_attr_group = {
*/
static int lbs_dev_open(struct net_device *dev)
{
- struct lbs_private *priv = (struct lbs_private *) dev->priv ;
+ struct lbs_private *priv = netdev_priv(dev) ;
int ret = 0;
lbs_deb_enter(LBS_DEB_NET);
@@ -435,7 +494,7 @@ static int lbs_dev_open(struct net_device *dev)
*/
static int lbs_mesh_stop(struct net_device *dev)
{
- struct lbs_private *priv = (struct lbs_private *) (dev->priv);
+ struct lbs_private *priv = dev->ml_priv;
lbs_deb_enter(LBS_DEB_MESH);
spin_lock_irq(&priv->driver_lock);
@@ -462,7 +521,7 @@ static int lbs_mesh_stop(struct net_device *dev)
*/
static int lbs_eth_stop(struct net_device *dev)
{
- struct lbs_private *priv = (struct lbs_private *) dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
lbs_deb_enter(LBS_DEB_NET);
@@ -479,7 +538,7 @@ static int lbs_eth_stop(struct net_device *dev)
static void lbs_tx_timeout(struct net_device *dev)
{
- struct lbs_private *priv = (struct lbs_private *) dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
lbs_deb_enter(LBS_DEB_TX);
@@ -531,7 +590,7 @@ EXPORT_SYMBOL_GPL(lbs_host_to_card_done);
*/
static struct net_device_stats *lbs_get_stats(struct net_device *dev)
{
- struct lbs_private *priv = (struct lbs_private *) dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
lbs_deb_enter(LBS_DEB_NET);
return &priv->stats;
@@ -540,7 +599,7 @@ static struct net_device_stats *lbs_get_stats(struct net_device *dev)
static int lbs_set_mac_address(struct net_device *dev, void *addr)
{
int ret = 0;
- struct lbs_private *priv = (struct lbs_private *) dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
struct sockaddr *phwaddr = addr;
struct cmd_ds_802_11_mac_address cmd;
@@ -588,7 +647,6 @@ static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd,
{
int i = nr_addrs;
struct dev_mc_list *mc_list;
- DECLARE_MAC_BUF(mac);
if ((dev->flags & (IFF_UP|IFF_MULTICAST)) != (IFF_UP|IFF_MULTICAST))
return nr_addrs;
@@ -596,16 +654,16 @@ static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd,
netif_addr_lock_bh(dev);
for (mc_list = dev->mc_list; mc_list; mc_list = mc_list->next) {
if (mac_in_list(cmd->maclist, nr_addrs, mc_list->dmi_addr)) {
- lbs_deb_net("mcast address %s:%s skipped\n", dev->name,
- print_mac(mac, mc_list->dmi_addr));
+ lbs_deb_net("mcast address %s:%pM skipped\n", dev->name,
+ mc_list->dmi_addr);
continue;
}
if (i == MRVDRV_MAX_MULTICAST_LIST_SIZE)
break;
memcpy(&cmd->maclist[6*i], mc_list->dmi_addr, ETH_ALEN);
- lbs_deb_net("mcast address %s:%s added to filter\n", dev->name,
- print_mac(mac, mc_list->dmi_addr));
+ lbs_deb_net("mcast address %s:%pM added to filter\n", dev->name,
+ mc_list->dmi_addr);
i++;
}
netif_addr_unlock_bh(dev);
@@ -674,7 +732,7 @@ static void lbs_set_mcast_worker(struct work_struct *work)
static void lbs_set_multicast_list(struct net_device *dev)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
schedule_work(&priv->mcast_work);
}
@@ -690,7 +748,7 @@ static void lbs_set_multicast_list(struct net_device *dev)
static int lbs_thread(void *data)
{
struct net_device *dev = data;
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
wait_queue_t wait;
lbs_deb_enter(LBS_DEB_THREAD);
@@ -1125,7 +1183,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
lbs_pr_err("init ethX device failed\n");
goto done;
}
- priv = dev->priv;
+ priv = netdev_priv(dev);
if (lbs_init_adapter(priv)) {
lbs_pr_err("failed to initialize adapter structure.\n");
@@ -1378,7 +1436,7 @@ static int lbs_add_mesh(struct lbs_private *priv)
ret = -ENOMEM;
goto done;
}
- mesh_dev->priv = priv;
+ mesh_dev->ml_priv = priv;
priv->mesh_dev = mesh_dev;
mesh_dev->open = lbs_dev_open;
@@ -1591,7 +1649,7 @@ static int lbs_rtap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
static struct net_device_stats *lbs_rtap_get_stats(struct net_device *dev)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = dev->ml_priv;
lbs_deb_enter(LBS_DEB_NET);
return &priv->stats;
}
@@ -1632,7 +1690,7 @@ static int lbs_add_rtap(struct lbs_private *priv)
rtap_dev->stop = lbs_rtap_stop;
rtap_dev->get_stats = lbs_rtap_get_stats;
rtap_dev->hard_start_xmit = lbs_rtap_hard_start_xmit;
- rtap_dev->priv = priv;
+ rtap_dev->ml_priv = priv;
SET_NETDEV_DEV(rtap_dev, priv->dev->dev.parent);
ret = register_netdev(rtap_dev);
@@ -1647,33 +1705,6 @@ out:
return ret;
}
-#ifndef CONFIG_IEEE80211
-const char *escape_essid(const char *essid, u8 essid_len)
-{
- static char escaped[IW_ESSID_MAX_SIZE * 2 + 1];
- const char *s = essid;
- char *d = escaped;
-
- if (ieee80211_is_empty_essid(essid, essid_len)) {
- memcpy(escaped, "<hidden>", sizeof("<hidden>"));
- return escaped;
- }
-
- essid_len = min(essid_len, (u8) IW_ESSID_MAX_SIZE);
- while (essid_len--) {
- if (*s == '\0') {
- *d++ = '\\';
- *d++ = '0';
- s++;
- } else {
- *d++ = *s++;
- }
- }
- *d = '\0';
- return escaped;
-}
-#endif
-
module_init(lbs_init_module);
module_exit(lbs_exit_module);
diff --git a/drivers/net/wireless/libertas/persistcfg.c b/drivers/net/wireless/libertas/persistcfg.c
index 3309a9c3cfef..d42b7a5a1b3f 100644
--- a/drivers/net/wireless/libertas/persistcfg.c
+++ b/drivers/net/wireless/libertas/persistcfg.c
@@ -18,7 +18,7 @@
static int mesh_get_default_parameters(struct device *dev,
struct mrvl_mesh_defaults *defs)
{
- struct lbs_private *priv = to_net_dev(dev)->priv;
+ struct lbs_private *priv = netdev_priv(to_net_dev(dev));
struct cmd_ds_mesh_config cmd;
int ret;
@@ -57,7 +57,7 @@ static ssize_t bootflag_get(struct device *dev,
static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct lbs_private *priv = to_net_dev(dev)->priv;
+ struct lbs_private *priv = netdev_priv(to_net_dev(dev));
struct cmd_ds_mesh_config cmd;
uint32_t datum;
int ret;
@@ -100,7 +100,7 @@ static ssize_t boottime_get(struct device *dev,
static ssize_t boottime_set(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- struct lbs_private *priv = to_net_dev(dev)->priv;
+ struct lbs_private *priv = netdev_priv(to_net_dev(dev));
struct cmd_ds_mesh_config cmd;
uint32_t datum;
int ret;
@@ -152,7 +152,7 @@ static ssize_t channel_get(struct device *dev,
static ssize_t channel_set(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
- struct lbs_private *priv = to_net_dev(dev)->priv;
+ struct lbs_private *priv = netdev_priv(to_net_dev(dev));
struct cmd_ds_mesh_config cmd;
uint32_t datum;
int ret;
@@ -210,7 +210,7 @@ static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr,
struct cmd_ds_mesh_config cmd;
struct mrvl_mesh_defaults defs;
struct mrvl_meshie *ie;
- struct lbs_private *priv = to_net_dev(dev)->priv;
+ struct lbs_private *priv = netdev_priv(to_net_dev(dev));
int len;
int ret;
@@ -233,7 +233,7 @@ static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr,
/* SSID len */
ie->val.mesh_id_len = len;
/* IE len */
- ie->hdr.len = sizeof(struct mrvl_meshie_val) - IW_ESSID_MAX_SIZE + len;
+ ie->len = sizeof(struct mrvl_meshie_val) - IW_ESSID_MAX_SIZE + len;
ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
CMD_TYPE_MESH_SET_MESH_IE);
@@ -269,7 +269,7 @@ static ssize_t protocol_id_set(struct device *dev,
struct cmd_ds_mesh_config cmd;
struct mrvl_mesh_defaults defs;
struct mrvl_meshie *ie;
- struct lbs_private *priv = to_net_dev(dev)->priv;
+ struct lbs_private *priv = netdev_priv(to_net_dev(dev));
uint32_t datum;
int ret;
@@ -323,7 +323,7 @@ static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr,
struct cmd_ds_mesh_config cmd;
struct mrvl_mesh_defaults defs;
struct mrvl_meshie *ie;
- struct lbs_private *priv = to_net_dev(dev)->priv;
+ struct lbs_private *priv = netdev_priv(to_net_dev(dev));
uint32_t datum;
int ret;
@@ -377,7 +377,7 @@ static ssize_t capability_set(struct device *dev, struct device_attribute *attr,
struct cmd_ds_mesh_config cmd;
struct mrvl_mesh_defaults defs;
struct mrvl_meshie *ie;
- struct lbs_private *priv = to_net_dev(dev)->priv;
+ struct lbs_private *priv = netdev_priv(to_net_dev(dev));
uint32_t datum;
int ret;
diff --git a/drivers/net/wireless/libertas/radiotap.h b/drivers/net/wireless/libertas/radiotap.h
index 5d118f40cfbc..f8eb9097ff0a 100644
--- a/drivers/net/wireless/libertas/radiotap.h
+++ b/drivers/net/wireless/libertas/radiotap.h
@@ -6,9 +6,6 @@ struct tx_radiotap_hdr {
u8 txpower;
u8 rts_retries;
u8 data_retries;
-#if 0
- u8 pad[IEEE80211_RADIOTAP_HDRLEN - 12];
-#endif
} __attribute__ ((packed));
#define TX_RADIOTAP_PRESENT ( \
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 22c4c6110521..57f6c12cda20 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -4,8 +4,11 @@
* IOCTL handlers as well as command preperation and response routines
* for sending scan commands to the firmware.
*/
+#include <linux/types.h>
#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
#include <asm/unaligned.h>
+#include <net/lib80211.h>
#include "host.h"
#include "decl.h"
@@ -52,6 +55,8 @@
//! Scan time specified in the channel TLV for each channel for active scans
#define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100
+#define DEFAULT_MAX_SCAN_AGE (15 * HZ)
+
static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
struct cmd_header *resp);
@@ -359,7 +364,7 @@ int lbs_scan_networks(struct lbs_private *priv, int full_scan)
#ifdef CONFIG_LIBERTAS_DEBUG
struct bss_descriptor *iter;
int i = 0;
- DECLARE_MAC_BUF(mac);
+ DECLARE_SSID_BUF(ssid);
#endif
lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", full_scan);
@@ -451,9 +456,9 @@ int lbs_scan_networks(struct lbs_private *priv, int full_scan)
mutex_lock(&priv->lock);
lbs_deb_scan("scan table:\n");
list_for_each_entry(iter, &priv->network_list, list)
- lbs_deb_scan("%02d: BSSID %s, RSSI %d, SSID '%s'\n",
- i++, print_mac(mac, iter->bssid), iter->rssi,
- escape_essid(iter->ssid, iter->ssid_len));
+ lbs_deb_scan("%02d: BSSID %pM, RSSI %d, SSID '%s'\n",
+ i++, iter->bssid, iter->rssi,
+ print_ssid(ssid, iter->ssid, iter->ssid_len));
mutex_unlock(&priv->lock);
#endif
@@ -512,7 +517,7 @@ static int lbs_process_bss(struct bss_descriptor *bss,
struct ieeetypes_dsparamset *pDS;
struct ieeetypes_cfparamset *pCF;
struct ieeetypes_ibssparamset *pibss;
- DECLARE_MAC_BUF(mac);
+ DECLARE_SSID_BUF(ssid);
struct ieeetypes_countryinfoset *pcountryinfo;
uint8_t *pos, *end, *p;
uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0;
@@ -544,7 +549,7 @@ static int lbs_process_bss(struct bss_descriptor *bss,
*bytesleft -= beaconsize;
memcpy(bss->bssid, pos, ETH_ALEN);
- lbs_deb_scan("process_bss: BSSID %s\n", print_mac(mac, bss->bssid));
+ lbs_deb_scan("process_bss: BSSID %pM\n", bss->bssid);
pos += ETH_ALEN;
if ((end - pos) < 12) {
@@ -588,38 +593,36 @@ static int lbs_process_bss(struct bss_descriptor *bss,
/* process variable IE */
while (pos <= end - 2) {
- struct ieee80211_info_element * elem = (void *)pos;
-
- if (pos + elem->len > end) {
+ if (pos + pos[1] > end) {
lbs_deb_scan("process_bss: error in processing IE, "
"bytes left < IE length\n");
break;
}
- switch (elem->id) {
- case MFIE_TYPE_SSID:
- bss->ssid_len = min_t(int, 32, elem->len);
- memcpy(bss->ssid, elem->data, bss->ssid_len);
+ switch (pos[0]) {
+ case WLAN_EID_SSID:
+ bss->ssid_len = min_t(int, IEEE80211_MAX_SSID_LEN, pos[1]);
+ memcpy(bss->ssid, pos + 2, bss->ssid_len);
lbs_deb_scan("got SSID IE: '%s', len %u\n",
- escape_essid(bss->ssid, bss->ssid_len),
+ print_ssid(ssid, bss->ssid, bss->ssid_len),
bss->ssid_len);
break;
- case MFIE_TYPE_RATES:
- n_basic_rates = min_t(uint8_t, MAX_RATES, elem->len);
- memcpy(bss->rates, elem->data, n_basic_rates);
+ case WLAN_EID_SUPP_RATES:
+ n_basic_rates = min_t(uint8_t, MAX_RATES, pos[1]);
+ memcpy(bss->rates, pos + 2, n_basic_rates);
got_basic_rates = 1;
lbs_deb_scan("got RATES IE\n");
break;
- case MFIE_TYPE_FH_SET:
+ case WLAN_EID_FH_PARAMS:
pFH = (struct ieeetypes_fhparamset *) pos;
memmove(&bss->phyparamset.fhparamset, pFH,
sizeof(struct ieeetypes_fhparamset));
lbs_deb_scan("got FH IE\n");
break;
- case MFIE_TYPE_DS_SET:
+ case WLAN_EID_DS_PARAMS:
pDS = (struct ieeetypes_dsparamset *) pos;
bss->channel = pDS->currentchan;
memcpy(&bss->phyparamset.dsparamset, pDS,
@@ -627,14 +630,14 @@ static int lbs_process_bss(struct bss_descriptor *bss,
lbs_deb_scan("got DS IE, channel %d\n", bss->channel);
break;
- case MFIE_TYPE_CF_SET:
+ case WLAN_EID_CF_PARAMS:
pCF = (struct ieeetypes_cfparamset *) pos;
memcpy(&bss->ssparamset.cfparamset, pCF,
sizeof(struct ieeetypes_cfparamset));
lbs_deb_scan("got CF IE\n");
break;
- case MFIE_TYPE_IBSS_SET:
+ case WLAN_EID_IBSS_PARAMS:
pibss = (struct ieeetypes_ibssparamset *) pos;
bss->atimwindow = le16_to_cpu(pibss->atimwindow);
memmove(&bss->ssparamset.ibssparamset, pibss,
@@ -642,7 +645,7 @@ static int lbs_process_bss(struct bss_descriptor *bss,
lbs_deb_scan("got IBSS IE\n");
break;
- case MFIE_TYPE_COUNTRY:
+ case WLAN_EID_COUNTRY:
pcountryinfo = (struct ieeetypes_countryinfoset *) pos;
lbs_deb_scan("got COUNTRY IE\n");
if (pcountryinfo->len < sizeof(pcountryinfo->countrycode)
@@ -659,7 +662,7 @@ static int lbs_process_bss(struct bss_descriptor *bss,
(int) (pcountryinfo->len + 2));
break;
- case MFIE_TYPE_RATES_EX:
+ case WLAN_EID_EXT_SUPP_RATES:
/* only process extended supported rate if data rate is
* already found. Data rate IE should come before
* extended supported rate IE
@@ -670,50 +673,51 @@ static int lbs_process_bss(struct bss_descriptor *bss,
break;
}
- n_ex_rates = elem->len;
+ n_ex_rates = pos[1];
if (n_basic_rates + n_ex_rates > MAX_RATES)
n_ex_rates = MAX_RATES - n_basic_rates;
p = bss->rates + n_basic_rates;
- memcpy(p, elem->data, n_ex_rates);
+ memcpy(p, pos + 2, n_ex_rates);
break;
- case MFIE_TYPE_GENERIC:
- if (elem->len >= 4 &&
- elem->data[0] == 0x00 && elem->data[1] == 0x50 &&
- elem->data[2] == 0xf2 && elem->data[3] == 0x01) {
- bss->wpa_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN);
- memcpy(bss->wpa_ie, elem, bss->wpa_ie_len);
+ case WLAN_EID_GENERIC:
+ if (pos[1] >= 4 &&
+ pos[2] == 0x00 && pos[3] == 0x50 &&
+ pos[4] == 0xf2 && pos[5] == 0x01) {
+ bss->wpa_ie_len = min(pos[1] + 2, MAX_WPA_IE_LEN);
+ memcpy(bss->wpa_ie, pos, bss->wpa_ie_len);
lbs_deb_scan("got WPA IE\n");
- lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie, elem->len);
- } else if (elem->len >= MARVELL_MESH_IE_LENGTH &&
- elem->data[0] == 0x00 && elem->data[1] == 0x50 &&
- elem->data[2] == 0x43 && elem->data[3] == 0x04) {
+ lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie,
+ bss->wpa_ie_len);
+ } else if (pos[1] >= MARVELL_MESH_IE_LENGTH &&
+ pos[2] == 0x00 && pos[3] == 0x50 &&
+ pos[4] == 0x43 && pos[4] == 0x04) {
lbs_deb_scan("got mesh IE\n");
bss->mesh = 1;
} else {
lbs_deb_scan("got generic IE: %02x:%02x:%02x:%02x, len %d\n",
- elem->data[0], elem->data[1],
- elem->data[2], elem->data[3],
- elem->len);
+ pos[2], pos[3],
+ pos[4], pos[5],
+ pos[1]);
}
break;
- case MFIE_TYPE_RSN:
+ case WLAN_EID_RSN:
lbs_deb_scan("got RSN IE\n");
- bss->rsn_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN);
- memcpy(bss->rsn_ie, elem, bss->rsn_ie_len);
+ bss->rsn_ie_len = min(pos[1] + 2, MAX_WPA_IE_LEN);
+ memcpy(bss->rsn_ie, pos, bss->rsn_ie_len);
lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE",
- bss->rsn_ie, elem->len);
+ bss->rsn_ie, bss->rsn_ie_len);
break;
default:
lbs_deb_scan("got IE 0x%04x, len %d\n",
- elem->id, elem->len);
+ pos[0], pos[1]);
break;
}
- pos += elem->len + 2;
+ pos += pos[1] + 2;
}
/* Timestamp */
@@ -741,10 +745,11 @@ done:
int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid,
uint8_t ssid_len)
{
+ DECLARE_SSID_BUF(ssid_buf);
int ret = 0;
lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s'\n",
- escape_essid(ssid, ssid_len));
+ print_ssid(ssid_buf, ssid, ssid_len));
if (!ssid_len)
goto out;
@@ -939,7 +944,8 @@ out:
int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ DECLARE_SSID_BUF(ssid);
+ struct lbs_private *priv = netdev_priv(dev);
int ret = 0;
lbs_deb_enter(LBS_DEB_WEXT);
@@ -968,7 +974,7 @@ int lbs_set_scan(struct net_device *dev, struct iw_request_info *info,
priv->scan_ssid_len = req->essid_len;
memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len);
lbs_deb_wext("set_scan, essid '%s'\n",
- escape_essid(priv->scan_ssid, priv->scan_ssid_len));
+ print_ssid(ssid, priv->scan_ssid, priv->scan_ssid_len));
} else {
priv->scan_ssid_len = 0;
}
@@ -1002,7 +1008,7 @@ int lbs_get_scan(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
{
#define SCAN_ITEM_SIZE 128
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
int err = 0;
char *ev = extra;
char *stop = ev + dwrq->length;
@@ -1151,7 +1157,6 @@ static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
struct bss_descriptor new;
struct bss_descriptor *found = NULL;
struct bss_descriptor *oldest = NULL;
- DECLARE_MAC_BUF(mac);
/* Process the data fields and IEs returned for this BSS */
memset(&new, 0, sizeof (struct bss_descriptor));
@@ -1190,7 +1195,7 @@ static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy,
continue;
}
- lbs_deb_scan("SCAN_RESP: BSSID %s\n", print_mac(mac, new.bssid));
+ lbs_deb_scan("SCAN_RESP: BSSID %pM\n", new.bssid);
/* Copy the locally created newbssentry to the scan table */
memcpy(found, &new, offsetof(struct bss_descriptor, list));
diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h
index 9e07b0464a8e..fab7d5d097fc 100644
--- a/drivers/net/wireless/libertas/scan.h
+++ b/drivers/net/wireless/libertas/scan.h
@@ -7,6 +7,10 @@
#ifndef _LBS_SCAN_H
#define _LBS_SCAN_H
+#include <net/iw_handler.h>
+
+#define MAX_NETWORK_COUNT 128
+
/**
* @brief Maximum number of channels that can be sent in a setuserscan ioctl
*/
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index a4972fed2941..dac462641170 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -60,7 +60,7 @@ static u32 convert_radiotap_rate_to_mv(u8 rate)
int lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned long flags;
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
struct txpd *txpd;
char *p802x_hdr;
uint16_t pkt_len;
diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h
index e0c2599da92f..fb7a2d1a2525 100644
--- a/drivers/net/wireless/libertas/types.h
+++ b/drivers/net/wireless/libertas/types.h
@@ -7,7 +7,6 @@
#include <linux/if_ether.h>
#include <asm/byteorder.h>
#include <linux/wireless.h>
-#include <net/ieee80211.h>
struct ieeetypes_cfparamset {
u8 elementid;
@@ -258,7 +257,7 @@ struct mrvlietypes_ledbhv {
* Note that the len member of the ieee80211_info_element varies depending on
* the mesh_id_len */
struct mrvl_meshie_val {
- uint8_t oui[P80211_OUI_LEN];
+ uint8_t oui[3];
uint8_t type;
uint8_t subtype;
uint8_t version;
@@ -270,7 +269,7 @@ struct mrvl_meshie_val {
} __attribute__ ((packed));
struct mrvl_meshie {
- struct ieee80211_info_element hdr;
+ u8 id, len;
struct mrvl_meshie_val val;
} __attribute__ ((packed));
diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
index 82c3e5a50ea6..c6102e08179e 100644
--- a/drivers/net/wireless/libertas/wext.c
+++ b/drivers/net/wireless/libertas/wext.c
@@ -8,7 +8,7 @@
#include <linux/wireless.h>
#include <linux/bitops.h>
-#include <net/ieee80211.h>
+#include <net/lib80211.h>
#include <net/iw_handler.h>
#include "host.h"
@@ -163,7 +163,7 @@ static int lbs_get_name(struct net_device *dev, struct iw_request_info *info,
static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info,
struct iw_freq *fwrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
struct chan_freq_power *cfp;
lbs_deb_enter(LBS_DEB_WEXT);
@@ -189,7 +189,7 @@ static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info,
static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info,
struct sockaddr *awrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
lbs_deb_enter(LBS_DEB_WEXT);
@@ -207,7 +207,7 @@ static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info,
static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
lbs_deb_enter(LBS_DEB_WEXT);
@@ -231,7 +231,7 @@ static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info,
static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
lbs_deb_enter(LBS_DEB_WEXT);
@@ -248,7 +248,7 @@ static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info,
static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
lbs_deb_enter(LBS_DEB_WEXT);
@@ -273,7 +273,7 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
int ret = 0;
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
u32 val = vwrq->value;
lbs_deb_enter(LBS_DEB_WEXT);
@@ -293,7 +293,7 @@ static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info,
static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
int ret = 0;
u16 val = 0;
@@ -315,7 +315,7 @@ out:
static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
int ret = 0;
u32 val = vwrq->value;
@@ -336,7 +336,7 @@ static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info,
static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
int ret = 0;
u16 val = 0;
@@ -359,7 +359,7 @@ out:
static int lbs_get_mode(struct net_device *dev,
struct iw_request_info *info, u32 * uwrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
lbs_deb_enter(LBS_DEB_WEXT);
@@ -385,7 +385,7 @@ static int lbs_get_txpow(struct net_device *dev,
struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
s16 curlevel = 0;
int ret = 0;
@@ -418,7 +418,7 @@ out:
static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
int ret = 0;
u16 slimit = 0, llimit = 0;
@@ -466,7 +466,7 @@ out:
static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
int ret = 0;
u16 val = 0;
@@ -542,7 +542,7 @@ static int lbs_get_range(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
{
int i, j;
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
struct iw_range *range = (struct iw_range *)extra;
struct chan_freq_power *cfp;
u8 rates[MAX_RATES + 1];
@@ -708,7 +708,7 @@ out:
static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
lbs_deb_enter(LBS_DEB_WEXT);
@@ -758,7 +758,7 @@ static int lbs_set_power(struct net_device *dev, struct iw_request_info *info,
static int lbs_get_power(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
lbs_deb_enter(LBS_DEB_WEXT);
@@ -781,7 +781,7 @@ static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev)
EXCELLENT = 95,
PERFECT = 100
};
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
u32 rssi_qual;
u32 tx_qual;
u32 quality = 0;
@@ -886,7 +886,7 @@ static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info,
struct iw_freq *fwrq, char *extra)
{
int ret = -EINVAL;
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
struct chan_freq_power *cfp;
struct assoc_request * assoc_req;
@@ -943,7 +943,7 @@ static int lbs_mesh_set_freq(struct net_device *dev,
struct iw_request_info *info,
struct iw_freq *fwrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
struct chan_freq_power *cfp;
int ret = -EINVAL;
@@ -994,7 +994,7 @@ out:
static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
u8 new_rate = 0;
int ret = -EINVAL;
u8 rates[MAX_RATES + 1];
@@ -1054,7 +1054,7 @@ out:
static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
lbs_deb_enter(LBS_DEB_WEXT);
@@ -1079,7 +1079,7 @@ static int lbs_set_mode(struct net_device *dev,
struct iw_request_info *info, u32 * uwrq, char *extra)
{
int ret = 0;
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
struct assoc_request * assoc_req;
lbs_deb_enter(LBS_DEB_WEXT);
@@ -1124,7 +1124,7 @@ static int lbs_get_encode(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *dwrq, u8 * extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
lbs_deb_enter(LBS_DEB_WEXT);
@@ -1319,7 +1319,7 @@ static int lbs_set_encode(struct net_device *dev,
struct iw_point *dwrq, char *extra)
{
int ret = 0;
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
struct assoc_request * assoc_req;
u16 is_default = 0, index = 0, set_tx_key = 0;
@@ -1395,7 +1395,7 @@ static int lbs_get_encodeext(struct net_device *dev,
char *extra)
{
int ret = -EINVAL;
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
int index, max_key_len;
@@ -1501,7 +1501,7 @@ static int lbs_set_encodeext(struct net_device *dev,
char *extra)
{
int ret = 0;
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
int alg = ext->alg;
struct assoc_request * assoc_req;
@@ -1639,7 +1639,7 @@ static int lbs_set_genie(struct net_device *dev,
struct iw_point *dwrq,
char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
int ret = 0;
struct assoc_request * assoc_req;
@@ -1685,7 +1685,7 @@ static int lbs_get_genie(struct net_device *dev,
char *extra)
{
int ret = 0;
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
lbs_deb_enter(LBS_DEB_WEXT);
@@ -1713,7 +1713,7 @@ static int lbs_set_auth(struct net_device *dev,
struct iw_param *dwrq,
char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
struct assoc_request * assoc_req;
int ret = 0;
int updated = 0;
@@ -1816,7 +1816,7 @@ static int lbs_get_auth(struct net_device *dev,
char *extra)
{
int ret = 0;
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
lbs_deb_enter(LBS_DEB_WEXT);
@@ -1857,7 +1857,7 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info,
struct iw_param *vwrq, char *extra)
{
int ret = 0;
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
s16 dbm = (s16) vwrq->value;
lbs_deb_enter(LBS_DEB_WEXT);
@@ -1936,7 +1936,7 @@ out:
static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
lbs_deb_enter(LBS_DEB_WEXT);
@@ -1971,12 +1971,13 @@ static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info,
static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
int ret = 0;
u8 ssid[IW_ESSID_MAX_SIZE];
u8 ssid_len = 0;
struct assoc_request * assoc_req;
int in_ssid_len = dwrq->length;
+ DECLARE_SSID_BUF(ssid_buf);
lbs_deb_enter(LBS_DEB_WEXT);
@@ -2005,7 +2006,7 @@ static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info,
lbs_deb_wext("requested any SSID\n");
} else {
lbs_deb_wext("requested SSID '%s'\n",
- escape_essid(ssid, ssid_len));
+ print_ssid(ssid_buf, ssid, ssid_len));
}
out:
@@ -2039,7 +2040,7 @@ static int lbs_mesh_get_essid(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
lbs_deb_enter(LBS_DEB_WEXT);
@@ -2057,7 +2058,7 @@ static int lbs_mesh_set_essid(struct net_device *dev,
struct iw_request_info *info,
struct iw_point *dwrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
int ret = 0;
lbs_deb_enter(LBS_DEB_WEXT);
@@ -2101,10 +2102,9 @@ static int lbs_mesh_set_essid(struct net_device *dev,
static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info,
struct sockaddr *awrq, char *extra)
{
- struct lbs_private *priv = dev->priv;
+ struct lbs_private *priv = netdev_priv(dev);
struct assoc_request * assoc_req;
int ret = 0;
- DECLARE_MAC_BUF(mac);
lbs_deb_enter(LBS_DEB_WEXT);
@@ -2114,7 +2114,7 @@ static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info,
if (awrq->sa_family != ARPHRD_ETHER)
return -EINVAL;
- lbs_deb_wext("ASSOC: WAP: sa_data %s\n", print_mac(mac, awrq->sa_data));
+ lbs_deb_wext("ASSOC: WAP: sa_data %pM\n", awrq->sa_data);
mutex_lock(&priv->lock);
diff --git a/drivers/net/wireless/libertas_tf/cmd.c b/drivers/net/wireless/libertas_tf/cmd.c
index fdbcf8ba3e8a..3d3914c83b14 100644
--- a/drivers/net/wireless/libertas_tf/cmd.c
+++ b/drivers/net/wireless/libertas_tf/cmd.c
@@ -79,7 +79,6 @@ int lbtf_update_hw_spec(struct lbtf_private *priv)
struct cmd_ds_get_hw_spec cmd;
int ret = -1;
u32 i;
- DECLARE_MAC_BUF(mac);
memset(&cmd, 0, sizeof(cmd));
cmd.hdr.size = cpu_to_le16(sizeof(cmd));
@@ -96,8 +95,8 @@ int lbtf_update_hw_spec(struct lbtf_private *priv)
priv->fwrelease = (priv->fwrelease << 8) |
(priv->fwrelease >> 24 & 0xff);
- printk(KERN_INFO "libertastf: %s, fw %u.%u.%up%u, cap 0x%08x\n",
- print_mac(mac, cmd.permanentaddr),
+ printk(KERN_INFO "libertastf: %pM, fw %u.%u.%up%u, cap 0x%08x\n",
+ cmd.permanentaddr,
priv->fwrelease >> 24 & 0xff,
priv->fwrelease >> 16 & 0xff,
priv->fwrelease >> 8 & 0xff,
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c
index feff945ad856..d1fc305de5fe 100644
--- a/drivers/net/wireless/libertas_tf/main.c
+++ b/drivers/net/wireless/libertas_tf/main.c
@@ -354,9 +354,11 @@ static void lbtf_op_remove_interface(struct ieee80211_hw *hw,
priv->vif = NULL;
}
-static int lbtf_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed)
{
struct lbtf_private *priv = hw->priv;
+ struct ieee80211_conf *conf = &hw->conf;
+
if (conf->channel->center_freq != priv->cur_freq) {
priv->cur_freq = conf->channel->center_freq;
lbtf_set_channel(priv, conf->channel->hw_value);
@@ -590,14 +592,14 @@ EXPORT_SYMBOL_GPL(lbtf_remove_card);
void lbtf_send_tx_feedback(struct lbtf_private *priv, u8 retrycnt, u8 fail)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(priv->tx_skb);
- memset(&info->status, 0, sizeof(info->status));
+
+ ieee80211_tx_info_clear_status(info);
/*
* Commented out, otherwise we never go beyond 1Mbit/s using mac80211
* default pid rc algorithm.
*
* info->status.retry_count = MRVL_DEFAULT_RETRIES - retrycnt;
*/
- info->status.excessive_retries = fail ? 1 : 0;
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && !fail)
info->flags |= IEEE80211_TX_STAT_ACK;
skb_pull(priv->tx_skb, sizeof(struct txpd));
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 1a019e98dac3..f83d69e813d3 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -21,6 +21,7 @@
#include <linux/if_arp.h>
#include <linux/rtnetlink.h>
#include <linux/etherdevice.h>
+#include <linux/debugfs.h>
MODULE_AUTHOR("Jouni Malinen");
MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211");
@@ -32,6 +33,9 @@ MODULE_PARM_DESC(radios, "Number of simulated radios");
struct hwsim_vif_priv {
u32 magic;
+ u8 bssid[ETH_ALEN];
+ bool assoc;
+ u16 aid;
};
#define HWSIM_VIF_MAGIC 0x69537748
@@ -63,13 +67,13 @@ struct hwsim_sta_priv {
static inline void hwsim_check_sta_magic(struct ieee80211_sta *sta)
{
struct hwsim_sta_priv *sp = (void *)sta->drv_priv;
- WARN_ON(sp->magic != HWSIM_VIF_MAGIC);
+ WARN_ON(sp->magic != HWSIM_STA_MAGIC);
}
static inline void hwsim_set_sta_magic(struct ieee80211_sta *sta)
{
struct hwsim_sta_priv *sp = (void *)sta->drv_priv;
- sp->magic = HWSIM_VIF_MAGIC;
+ sp->magic = HWSIM_STA_MAGIC;
}
static inline void hwsim_clear_sta_magic(struct ieee80211_sta *sta)
@@ -132,6 +136,12 @@ struct mac80211_hwsim_data {
unsigned int rx_filter;
int started;
struct timer_list beacon_timer;
+ enum ps_mode {
+ PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL
+ } ps;
+ bool ps_poll_pending;
+ struct dentry *debugfs;
+ struct dentry *debugfs_ps;
};
@@ -196,6 +206,34 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
}
+static bool hwsim_ps_rx_ok(struct mac80211_hwsim_data *data,
+ struct sk_buff *skb)
+{
+ switch (data->ps) {
+ case PS_DISABLED:
+ return true;
+ case PS_ENABLED:
+ return false;
+ case PS_AUTO_POLL:
+ /* TODO: accept (some) Beacons by default and other frames only
+ * if pending PS-Poll has been sent */
+ return true;
+ case PS_MANUAL_POLL:
+ /* Allow unicast frames to own address if there is a pending
+ * PS-Poll */
+ if (data->ps_poll_pending &&
+ memcmp(data->hw->wiphy->perm_addr, skb->data + 4,
+ ETH_ALEN) == 0) {
+ data->ps_poll_pending = false;
+ return true;
+ }
+ return false;
+ }
+
+ return true;
+}
+
+
static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
struct sk_buff *skb)
{
@@ -209,9 +247,12 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
/* TODO: set mactime */
rx_status.freq = data->channel->center_freq;
rx_status.band = data->channel->band;
- rx_status.rate_idx = info->tx_rate_idx;
+ rx_status.rate_idx = info->control.rates[0].idx;
/* TODO: simulate signal strength (and optional packet drop) */
+ if (data->ps != PS_DISABLED)
+ hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
+
/* Copy skb to all enabled radios that are on the current frequency */
spin_lock(&hwsim_radio_lock);
list_for_each_entry(data2, &hwsim_radios, list) {
@@ -221,6 +262,7 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
continue;
if (!data2->started || !data2->radio_enabled ||
+ !hwsim_ps_rx_ok(data2, skb) ||
data->channel->center_freq != data2->channel->center_freq)
continue;
@@ -269,13 +311,9 @@ static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
if (txi->control.sta)
hwsim_check_sta_magic(txi->control.sta);
- memset(&txi->status, 0, sizeof(txi->status));
- if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK)) {
- if (ack)
- txi->flags |= IEEE80211_TX_STAT_ACK;
- else
- txi->status.excessive_retries = 1;
- }
+ ieee80211_tx_info_clear_status(txi);
+ if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && ack)
+ txi->flags |= IEEE80211_TX_STAT_ACK;
ieee80211_tx_status_irqsafe(hw, skb);
return NETDEV_TX_OK;
}
@@ -294,6 +332,7 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw)
{
struct mac80211_hwsim_data *data = hw->priv;
data->started = 0;
+ del_timer(&data->beacon_timer);
printk(KERN_DEBUG "%s:%s\n", wiphy_name(hw->wiphy), __func__);
}
@@ -301,10 +340,9 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw)
static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf)
{
- DECLARE_MAC_BUF(mac);
- printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%s)\n",
+ printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n",
wiphy_name(hw->wiphy), __func__, conf->type,
- print_mac(mac, conf->mac_addr));
+ conf->mac_addr);
hwsim_set_magic(conf->vif);
return 0;
}
@@ -313,10 +351,9 @@ static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw,
static void mac80211_hwsim_remove_interface(
struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf)
{
- DECLARE_MAC_BUF(mac);
- printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%s)\n",
+ printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n",
wiphy_name(hw->wiphy), __func__, conf->type,
- print_mac(mac, conf->mac_addr));
+ conf->mac_addr);
hwsim_check_magic(conf->vif);
hwsim_clear_magic(conf->vif);
}
@@ -331,7 +368,8 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
hwsim_check_magic(vif);
- if (vif->type != NL80211_IFTYPE_AP)
+ if (vif->type != NL80211_IFTYPE_AP &&
+ vif->type != NL80211_IFTYPE_MESH_POINT)
return;
skb = ieee80211_beacon_get(hw, vif);
@@ -361,10 +399,10 @@ static void mac80211_hwsim_beacon(unsigned long arg)
}
-static int mac80211_hwsim_config(struct ieee80211_hw *hw,
- struct ieee80211_conf *conf)
+static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed)
{
struct mac80211_hwsim_data *data = hw->priv;
+ struct ieee80211_conf *conf = &hw->conf;
printk(KERN_DEBUG "%s:%s (freq=%d radio_enabled=%d beacon_int=%d)\n",
wiphy_name(hw->wiphy), __func__,
@@ -409,7 +447,16 @@ static int mac80211_hwsim_config_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_if_conf *conf)
{
+ struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
+
hwsim_check_magic(vif);
+ if (conf->changed & IEEE80211_IFCC_BSSID) {
+ DECLARE_MAC_BUF(mac);
+ printk(KERN_DEBUG "%s:%s: BSSID changed: %pM\n",
+ wiphy_name(hw->wiphy), __func__,
+ conf->bssid);
+ memcpy(vp->bssid, conf->bssid, ETH_ALEN);
+ }
return 0;
}
@@ -418,7 +465,46 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw,
struct ieee80211_bss_conf *info,
u32 changed)
{
+ struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
+
hwsim_check_magic(vif);
+
+ printk(KERN_DEBUG "%s:%s(changed=0x%x)\n",
+ wiphy_name(hw->wiphy), __func__, changed);
+
+ if (changed & BSS_CHANGED_ASSOC) {
+ printk(KERN_DEBUG " %s: ASSOC: assoc=%d aid=%d\n",
+ wiphy_name(hw->wiphy), info->assoc, info->aid);
+ vp->assoc = info->assoc;
+ vp->aid = info->aid;
+ }
+
+ if (changed & BSS_CHANGED_ERP_CTS_PROT) {
+ printk(KERN_DEBUG " %s: ERP_CTS_PROT: %d\n",
+ wiphy_name(hw->wiphy), info->use_cts_prot);
+ }
+
+ if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+ printk(KERN_DEBUG " %s: ERP_PREAMBLE: %d\n",
+ wiphy_name(hw->wiphy), info->use_short_preamble);
+ }
+
+ if (changed & BSS_CHANGED_ERP_SLOT) {
+ printk(KERN_DEBUG " %s: ERP_SLOT: %d\n",
+ wiphy_name(hw->wiphy), info->use_short_slot);
+ }
+
+ if (changed & BSS_CHANGED_HT) {
+ printk(KERN_DEBUG " %s: HT: op_mode=0x%x\n",
+ wiphy_name(hw->wiphy),
+ info->ht.operation_mode);
+ }
+
+ if (changed & BSS_CHANGED_BASIC_RATES) {
+ printk(KERN_DEBUG " %s: BASIC_RATES: 0x%llx\n",
+ wiphy_name(hw->wiphy),
+ (unsigned long long) info->basic_rates);
+ }
}
static void mac80211_hwsim_sta_notify(struct ieee80211_hw *hw,
@@ -434,6 +520,10 @@ static void mac80211_hwsim_sta_notify(struct ieee80211_hw *hw,
case STA_NOTIFY_REMOVE:
hwsim_clear_sta_magic(sta);
break;
+ case STA_NOTIFY_SLEEP:
+ case STA_NOTIFY_AWAKE:
+ /* TODO: make good use of these flags */
+ break;
}
}
@@ -445,6 +535,17 @@ static int mac80211_hwsim_set_tim(struct ieee80211_hw *hw,
return 0;
}
+static int mac80211_hwsim_conf_tx(
+ struct ieee80211_hw *hw, u16 queue,
+ const struct ieee80211_tx_queue_params *params)
+{
+ printk(KERN_DEBUG "%s:%s (queue=%d txop=%d cw_min=%d cw_max=%d "
+ "aifs=%d)\n",
+ wiphy_name(hw->wiphy), __func__, queue,
+ params->txop, params->cw_min, params->cw_max, params->aifs);
+ return 0;
+}
+
static const struct ieee80211_ops mac80211_hwsim_ops =
{
.tx = mac80211_hwsim_tx,
@@ -458,6 +559,7 @@ static const struct ieee80211_ops mac80211_hwsim_ops =
.bss_info_changed = mac80211_hwsim_bss_info_changed,
.sta_notify = mac80211_hwsim_sta_notify,
.set_tim = mac80211_hwsim_set_tim,
+ .conf_tx = mac80211_hwsim_conf_tx,
};
@@ -474,6 +576,8 @@ static void mac80211_hwsim_free(void)
spin_unlock_bh(&hwsim_radio_lock);
list_for_each_entry(data, &tmplist, list) {
+ debugfs_remove(data->debugfs_ps);
+ debugfs_remove(data->debugfs);
ieee80211_unregister_hw(data->hw);
device_unregister(data->dev);
ieee80211_free_hw(data->hw);
@@ -499,13 +603,131 @@ static void hwsim_mon_setup(struct net_device *dev)
}
+static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif)
+{
+ struct mac80211_hwsim_data *data = dat;
+ struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
+ DECLARE_MAC_BUF(buf);
+ struct sk_buff *skb;
+ struct ieee80211_pspoll *pspoll;
+
+ if (!vp->assoc)
+ return;
+
+ printk(KERN_DEBUG "%s:%s: send PS-Poll to %pM for aid %d\n",
+ wiphy_name(data->hw->wiphy), __func__, vp->bssid, vp->aid);
+
+ skb = dev_alloc_skb(sizeof(*pspoll));
+ if (!skb)
+ return;
+ pspoll = (void *) skb_put(skb, sizeof(*pspoll));
+ pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
+ IEEE80211_STYPE_PSPOLL |
+ IEEE80211_FCTL_PM);
+ pspoll->aid = cpu_to_le16(0xc000 | vp->aid);
+ memcpy(pspoll->bssid, vp->bssid, ETH_ALEN);
+ memcpy(pspoll->ta, mac, ETH_ALEN);
+ if (data->radio_enabled &&
+ !mac80211_hwsim_tx_frame(data->hw, skb))
+ printk(KERN_DEBUG "%s: PS-Poll frame not ack'ed\n", __func__);
+ dev_kfree_skb(skb);
+}
+
+
+static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac,
+ struct ieee80211_vif *vif, int ps)
+{
+ struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
+ DECLARE_MAC_BUF(buf);
+ struct sk_buff *skb;
+ struct ieee80211_hdr *hdr;
+
+ if (!vp->assoc)
+ return;
+
+ printk(KERN_DEBUG "%s:%s: send data::nullfunc to %pM ps=%d\n",
+ wiphy_name(data->hw->wiphy), __func__, vp->bssid, ps);
+
+ skb = dev_alloc_skb(sizeof(*hdr));
+ if (!skb)
+ return;
+ hdr = (void *) skb_put(skb, sizeof(*hdr) - ETH_ALEN);
+ hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
+ IEEE80211_STYPE_NULLFUNC |
+ (ps ? IEEE80211_FCTL_PM : 0));
+ hdr->duration_id = cpu_to_le16(0);
+ memcpy(hdr->addr1, vp->bssid, ETH_ALEN);
+ memcpy(hdr->addr2, mac, ETH_ALEN);
+ memcpy(hdr->addr3, vp->bssid, ETH_ALEN);
+ if (data->radio_enabled &&
+ !mac80211_hwsim_tx_frame(data->hw, skb))
+ printk(KERN_DEBUG "%s: nullfunc frame not ack'ed\n", __func__);
+ dev_kfree_skb(skb);
+}
+
+
+static void hwsim_send_nullfunc_ps(void *dat, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct mac80211_hwsim_data *data = dat;
+ hwsim_send_nullfunc(data, mac, vif, 1);
+}
+
+
+static void hwsim_send_nullfunc_no_ps(void *dat, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct mac80211_hwsim_data *data = dat;
+ hwsim_send_nullfunc(data, mac, vif, 0);
+}
+
+
+static int hwsim_fops_ps_read(void *dat, u64 *val)
+{
+ struct mac80211_hwsim_data *data = dat;
+ *val = data->ps;
+ return 0;
+}
+
+static int hwsim_fops_ps_write(void *dat, u64 val)
+{
+ struct mac80211_hwsim_data *data = dat;
+ enum ps_mode old_ps;
+
+ if (val != PS_DISABLED && val != PS_ENABLED && val != PS_AUTO_POLL &&
+ val != PS_MANUAL_POLL)
+ return -EINVAL;
+
+ old_ps = data->ps;
+ data->ps = val;
+
+ if (val == PS_MANUAL_POLL) {
+ ieee80211_iterate_active_interfaces(data->hw,
+ hwsim_send_ps_poll, data);
+ data->ps_poll_pending = true;
+ } else if (old_ps == PS_DISABLED && val != PS_DISABLED) {
+ ieee80211_iterate_active_interfaces(data->hw,
+ hwsim_send_nullfunc_ps,
+ data);
+ } else if (old_ps != PS_DISABLED && val == PS_DISABLED) {
+ ieee80211_iterate_active_interfaces(data->hw,
+ hwsim_send_nullfunc_no_ps,
+ data);
+ }
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_ps, hwsim_fops_ps_read, hwsim_fops_ps_write,
+ "%llu\n");
+
+
static int __init init_mac80211_hwsim(void)
{
int i, err = 0;
u8 addr[ETH_ALEN];
struct mac80211_hwsim_data *data;
struct ieee80211_hw *hw;
- DECLARE_MAC_BUF(mac);
if (radios < 1 || radios > 100)
return -EINVAL;
@@ -553,7 +775,8 @@ static int __init init_mac80211_hwsim(void)
hw->queues = 4;
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_AP);
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_MESH_POINT);
hw->ampdu_queues = 1;
/* ask mac80211 to reserve space for magic */
@@ -566,19 +789,18 @@ static int __init init_mac80211_hwsim(void)
data->band.n_channels = ARRAY_SIZE(hwsim_channels);
data->band.bitrates = data->rates;
data->band.n_bitrates = ARRAY_SIZE(hwsim_rates);
- data->band.ht_info.ht_supported = 1;
- data->band.ht_info.cap = IEEE80211_HT_CAP_SUP_WIDTH |
+ data->band.ht_cap.ht_supported = true;
+ data->band.ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
IEEE80211_HT_CAP_GRN_FLD |
IEEE80211_HT_CAP_SGI_40 |
IEEE80211_HT_CAP_DSSSCCK40;
- data->band.ht_info.ampdu_factor = 0x3;
- data->band.ht_info.ampdu_density = 0x6;
- memset(data->band.ht_info.supp_mcs_set, 0,
- sizeof(data->band.ht_info.supp_mcs_set));
- data->band.ht_info.supp_mcs_set[0] = 0xff;
- data->band.ht_info.supp_mcs_set[1] = 0xff;
- data->band.ht_info.supp_mcs_set[12] =
- IEEE80211_HT_CAP_MCS_TX_DEFINED;
+ data->band.ht_cap.ampdu_factor = 0x3;
+ data->band.ht_cap.ampdu_density = 0x6;
+ memset(&data->band.ht_cap.mcs, 0,
+ sizeof(data->band.ht_cap.mcs));
+ data->band.ht_cap.mcs.rx_mask[0] = 0xff;
+ data->band.ht_cap.mcs.rx_mask[1] = 0xff;
+ data->band.ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &data->band;
err = ieee80211_register_hw(hw);
@@ -588,9 +810,15 @@ static int __init init_mac80211_hwsim(void)
goto failed_hw;
}
- printk(KERN_DEBUG "%s: hwaddr %s registered\n",
+ printk(KERN_DEBUG "%s: hwaddr %pM registered\n",
wiphy_name(hw->wiphy),
- print_mac(mac, hw->wiphy->perm_addr));
+ hw->wiphy->perm_addr);
+
+ data->debugfs = debugfs_create_dir("hwsim",
+ hw->wiphy->debugfsdir);
+ data->debugfs_ps = debugfs_create_file("ps", 0666,
+ data->debugfs, data,
+ &hwsim_fops_ps);
setup_timer(&data->beacon_timer, mac80211_hwsim_beacon,
(unsigned long) hw);
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index a670f36b5f3f..24caec6caf1f 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -737,7 +737,6 @@ static int netwave_pcmcia_config(struct pcmcia_device *link) {
win_req_t req;
memreq_t mem;
u_char __iomem *ramBase = NULL;
- DECLARE_MAC_BUF(mac);
DEBUG(0, "netwave_pcmcia_config(0x%p)\n", link);
@@ -808,12 +807,12 @@ static int netwave_pcmcia_config(struct pcmcia_device *link) {
dev->dev_addr[i] = readb(ramBase + NETWAVE_EREG_PA + i);
printk(KERN_INFO "%s: Netwave: port %#3lx, irq %d, mem %lx, "
- "id %c%c, hw_addr %s\n",
+ "id %c%c, hw_addr %pM\n",
dev->name, dev->base_addr, dev->irq,
(u_long) ramBase,
(int) readb(ramBase+NETWAVE_EREG_NI),
(int) readb(ramBase+NETWAVE_EREG_NI+1),
- print_mac(mac, dev->dev_addr));
+ dev->dev_addr);
/* get revision words */
printk(KERN_DEBUG "Netwave_reset: revision %04x %04x\n",
@@ -1308,7 +1307,6 @@ static int netwave_rx(struct net_device *dev)
/* Queue packet for network layer */
netif_rx(skb);
- dev->last_rx = jiffies;
priv->stats.rx_packets++;
priv->stats.rx_bytes += rcvLen;
diff --git a/drivers/net/wireless/orinoco/Makefile b/drivers/net/wireless/orinoco/Makefile
new file mode 100644
index 000000000000..791366e08c50
--- /dev/null
+++ b/drivers/net/wireless/orinoco/Makefile
@@ -0,0 +1,12 @@
+#
+# Makefile for the orinoco wireless device drivers.
+#
+
+obj-$(CONFIG_HERMES) += orinoco.o hermes.o hermes_dld.o
+obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o
+obj-$(CONFIG_APPLE_AIRPORT) += airport.o
+obj-$(CONFIG_PLX_HERMES) += orinoco_plx.o
+obj-$(CONFIG_PCI_HERMES) += orinoco_pci.o
+obj-$(CONFIG_TMD_HERMES) += orinoco_tmd.o
+obj-$(CONFIG_NORTEL_HERMES) += orinoco_nortel.o
+obj-$(CONFIG_PCMCIA_SPECTRUM) += spectrum_cs.o
diff --git a/drivers/net/wireless/airport.c b/drivers/net/wireless/orinoco/airport.c
index ce03a2e865fa..28f1cae48439 100644
--- a/drivers/net/wireless/airport.c
+++ b/drivers/net/wireless/orinoco/airport.c
@@ -279,7 +279,7 @@ init_airport(void)
static void __exit
exit_airport(void)
{
- return macio_unregister_driver(&airport_driver);
+ macio_unregister_driver(&airport_driver);
}
module_init(init_airport);
diff --git a/drivers/net/wireless/hermes.c b/drivers/net/wireless/orinoco/hermes.c
index bfa375369df3..bfa375369df3 100644
--- a/drivers/net/wireless/hermes.c
+++ b/drivers/net/wireless/orinoco/hermes.c
diff --git a/drivers/net/wireless/hermes.h b/drivers/net/wireless/orinoco/hermes.h
index 8b13c8fef3dc..8b13c8fef3dc 100644
--- a/drivers/net/wireless/hermes.h
+++ b/drivers/net/wireless/orinoco/hermes.h
diff --git a/drivers/net/wireless/hermes_dld.c b/drivers/net/wireless/orinoco/hermes_dld.c
index d8c626e61a3a..d8c626e61a3a 100644
--- a/drivers/net/wireless/hermes_dld.c
+++ b/drivers/net/wireless/orinoco/hermes_dld.c
diff --git a/drivers/net/wireless/hermes_dld.h b/drivers/net/wireless/orinoco/hermes_dld.h
index 6fcb26277999..6fcb26277999 100644
--- a/drivers/net/wireless/hermes_dld.h
+++ b/drivers/net/wireless/orinoco/hermes_dld.h
diff --git a/drivers/net/wireless/hermes_rid.h b/drivers/net/wireless/orinoco/hermes_rid.h
index 42eb67dea1df..42eb67dea1df 100644
--- a/drivers/net/wireless/hermes_rid.h
+++ b/drivers/net/wireless/orinoco/hermes_rid.h
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c
index e0512e49d6d3..bc84e2792f8a 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco/orinoco.c
@@ -84,10 +84,11 @@
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/firmware.h>
+#include <linux/suspend.h>
#include <linux/if_arp.h>
#include <linux/wireless.h>
+#include <linux/ieee80211.h>
#include <net/iw_handler.h>
-#include <net/ieee80211.h>
#include <linux/scatterlist.h>
#include <linux/crypto.h>
@@ -143,7 +144,7 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2)
#define ORINOCO_MIN_MTU 256
-#define ORINOCO_MAX_MTU (IEEE80211_DATA_LEN - ENCAPS_OVERHEAD)
+#define ORINOCO_MAX_MTU (IEEE80211_MAX_DATA_LEN - ENCAPS_OVERHEAD)
#define SYMBOL_MAX_VER_LEN (14)
#define USER_BAP 0
@@ -392,7 +393,7 @@ static void orinoco_bss_data_init(struct orinoco_private *priv)
}
static inline u8 *orinoco_get_ie(u8 *data, size_t len,
- enum ieee80211_mfie eid)
+ enum ieee80211_eid eid)
{
u8 *p = data;
while ((p + 2) < (data + len)) {
@@ -409,7 +410,7 @@ static inline u8 *orinoco_get_wpa_ie(u8 *data, size_t len)
{
u8 *p = data;
while ((p + 2 + WPA_SELECTOR_LEN) < (data + len)) {
- if ((p[0] == MFIE_TYPE_GENERIC) &&
+ if ((p[0] == WLAN_EID_GENERIC) &&
(memcmp(&p[2], WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0))
return p;
p += p[1] + 2;
@@ -431,9 +432,9 @@ struct fw_info {
};
const static struct fw_info orinoco_fw[] = {
- { "", "agere_sta_fw.bin", "agere_ap_fw.bin", 0x00390000, 1000 },
- { "", "prism_sta_fw.bin", "prism_ap_fw.bin", 0, 1024 },
- { "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", "", 0x00003100, 512 }
+ { NULL, "agere_sta_fw.bin", "agere_ap_fw.bin", 0x00390000, 1000 },
+ { NULL, "prism_sta_fw.bin", "prism_ap_fw.bin", 0, 1024 },
+ { "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", NULL, 0x00003100, 512 }
};
/* Structure used to access fields in FW
@@ -487,13 +488,17 @@ orinoco_dl_firmware(struct orinoco_private *priv,
if (err)
goto free;
- err = request_firmware(&fw_entry, firmware, priv->dev);
- if (err) {
- printk(KERN_ERR "%s: Cannot find firmware %s\n",
- dev->name, firmware);
- err = -ENOENT;
- goto free;
- }
+ if (!priv->cached_fw) {
+ err = request_firmware(&fw_entry, firmware, priv->dev);
+
+ if (err) {
+ printk(KERN_ERR "%s: Cannot find firmware %s\n",
+ dev->name, firmware);
+ err = -ENOENT;
+ goto free;
+ }
+ } else
+ fw_entry = priv->cached_fw;
hdr = (const struct orinoco_fw_header *) fw_entry->data;
@@ -535,7 +540,9 @@ orinoco_dl_firmware(struct orinoco_private *priv,
dev->name, hermes_present(hw));
abort:
- release_firmware(fw_entry);
+ /* If we requested the firmware, release it. */
+ if (!priv->cached_fw)
+ release_firmware(fw_entry);
free:
kfree(pda);
@@ -639,34 +646,41 @@ symbol_dl_firmware(struct orinoco_private *priv,
int ret;
const struct firmware *fw_entry;
- if (request_firmware(&fw_entry, fw->pri_fw,
- priv->dev) != 0) {
- printk(KERN_ERR "%s: Cannot find firmware: %s\n",
- dev->name, fw->pri_fw);
- return -ENOENT;
- }
+ if (!priv->cached_pri_fw) {
+ if (request_firmware(&fw_entry, fw->pri_fw, priv->dev) != 0) {
+ printk(KERN_ERR "%s: Cannot find firmware: %s\n",
+ dev->name, fw->pri_fw);
+ return -ENOENT;
+ }
+ } else
+ fw_entry = priv->cached_pri_fw;
/* Load primary firmware */
ret = symbol_dl_image(priv, fw, fw_entry->data,
fw_entry->data + fw_entry->size, 0);
- release_firmware(fw_entry);
+
+ if (!priv->cached_pri_fw)
+ release_firmware(fw_entry);
if (ret) {
printk(KERN_ERR "%s: Primary firmware download failed\n",
dev->name);
return ret;
}
- if (request_firmware(&fw_entry, fw->sta_fw,
- priv->dev) != 0) {
- printk(KERN_ERR "%s: Cannot find firmware: %s\n",
- dev->name, fw->sta_fw);
- return -ENOENT;
- }
+ if (!priv->cached_fw) {
+ if (request_firmware(&fw_entry, fw->sta_fw, priv->dev) != 0) {
+ printk(KERN_ERR "%s: Cannot find firmware: %s\n",
+ dev->name, fw->sta_fw);
+ return -ENOENT;
+ }
+ } else
+ fw_entry = priv->cached_fw;
/* Load secondary firmware */
ret = symbol_dl_image(priv, fw, fw_entry->data,
fw_entry->data + fw_entry->size, 1);
- release_firmware(fw_entry);
+ if (!priv->cached_fw)
+ release_firmware(fw_entry);
if (ret) {
printk(KERN_ERR "%s: Secondary firmware download failed\n",
dev->name);
@@ -699,6 +713,45 @@ static int orinoco_download(struct orinoco_private *priv)
return err;
}
+#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP)
+static void orinoco_cache_fw(struct orinoco_private *priv, int ap)
+{
+ const struct firmware *fw_entry = NULL;
+ const char *pri_fw;
+ const char *fw;
+
+ pri_fw = orinoco_fw[priv->firmware_type].pri_fw;
+ if (ap)
+ fw = orinoco_fw[priv->firmware_type].ap_fw;
+ else
+ fw = orinoco_fw[priv->firmware_type].sta_fw;
+
+ if (pri_fw) {
+ if (request_firmware(&fw_entry, pri_fw, priv->dev) == 0)
+ priv->cached_pri_fw = fw_entry;
+ }
+
+ if (fw) {
+ if (request_firmware(&fw_entry, fw, priv->dev) == 0)
+ priv->cached_fw = fw_entry;
+ }
+}
+
+static void orinoco_uncache_fw(struct orinoco_private *priv)
+{
+ if (priv->cached_pri_fw)
+ release_firmware(priv->cached_pri_fw);
+ if (priv->cached_fw)
+ release_firmware(priv->cached_fw);
+
+ priv->cached_pri_fw = NULL;
+ priv->cached_fw = NULL;
+}
+#else
+#define orinoco_cache_fw(priv, ap)
+#define orinoco_uncache_fw(priv)
+#endif
+
/********************************************************************/
/* Device methods */
/********************************************************************/
@@ -800,7 +853,7 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
wstats->qual.qual = (int)le16_to_cpu(cq.qual);
wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
- wstats->qual.updated = 7;
+ wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
}
}
@@ -830,7 +883,8 @@ static int orinoco_change_mtu(struct net_device *dev, int new_mtu)
if ( (new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU) )
return -EINVAL;
- if ( (new_mtu + ENCAPS_OVERHEAD + IEEE80211_HLEN) >
+ /* MTU + encapsulation + header length */
+ if ( (new_mtu + ENCAPS_OVERHEAD + sizeof(struct ieee80211_hdr)) >
(priv->nicbuf_size - ETH_HLEN) )
return -EINVAL;
@@ -1158,7 +1212,7 @@ static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
wstats.level = level - 0x95;
wstats.noise = noise - 0x95;
wstats.qual = (level > noise) ? (level - noise) : 0;
- wstats.updated = 7;
+ wstats.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
/* Update spy records */
wireless_spy_update(dev, mac, &wstats);
}
@@ -1245,7 +1299,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
}
/* sanity check the length */
- if (datalen > IEEE80211_DATA_LEN + 12) {
+ if (datalen > IEEE80211_MAX_DATA_LEN + 12) {
printk(KERN_DEBUG "%s: oversized monitor frame, "
"data length = %d\n", dev->name, datalen);
stats->rx_length_errors++;
@@ -1280,7 +1334,6 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
skb->pkt_type = PACKET_OTHERHOST;
skb->protocol = __constant_htons(ETH_P_802_2);
- dev->last_rx = jiffies;
stats->rx_packets++;
stats->rx_bytes += skb->len;
@@ -1374,7 +1427,7 @@ static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
data. */
goto out;
}
- if (length > IEEE80211_DATA_LEN) {
+ if (length > IEEE80211_MAX_DATA_LEN) {
printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
dev->name, length);
stats->rx_length_errors++;
@@ -1477,12 +1530,11 @@ static void orinoco_rx(struct net_device *dev,
MICHAEL_MIC_LEN)) {
union iwreq_data wrqu;
struct iw_michaelmicfailure wxmic;
- DECLARE_MAC_BUF(mac);
printk(KERN_WARNING "%s: "
- "Invalid Michael MIC in data frame from %s, "
+ "Invalid Michael MIC in data frame from %pM, "
"using key %i\n",
- dev->name, print_mac(mac, src), key_id);
+ dev->name, src, key_id);
/* TODO: update stats */
@@ -1530,7 +1582,6 @@ static void orinoco_rx(struct net_device *dev,
else
memcpy(hdr->h_source, desc->addr2, ETH_ALEN);
- dev->last_rx = jiffies;
skb->protocol = eth_type_trans(skb, dev);
skb->ip_summed = CHECKSUM_NONE;
if (fc & IEEE80211_FCTL_TODS)
@@ -1699,7 +1750,7 @@ static void orinoco_send_bssid_wevent(struct orinoco_private *priv)
union iwreq_data wrqu;
int err;
- err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID,
+ err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
if (err != 0)
return;
@@ -1722,7 +1773,7 @@ static void orinoco_send_assocreqie_wevent(struct orinoco_private *priv)
if (!priv->has_wpa)
return;
- err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO,
+ err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO,
sizeof(buf), NULL, &buf);
if (err != 0)
return;
@@ -1752,7 +1803,7 @@ static void orinoco_send_assocrespie_wevent(struct orinoco_private *priv)
if (!priv->has_wpa)
return;
- err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENT_ASSOC_RESP_INFO,
+ err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_RESP_INFO,
sizeof(buf), NULL, &buf);
if (err != 0)
return;
@@ -2301,6 +2352,11 @@ int orinoco_reinit_firmware(struct net_device *dev)
int err;
err = hermes_init(hw);
+ if (priv->do_fw_download && !err) {
+ err = orinoco_download(priv);
+ if (err)
+ priv->do_fw_download = 0;
+ }
if (!err)
err = orinoco_allocate_fid(dev);
@@ -2926,12 +2982,6 @@ static void orinoco_reset(struct work_struct *work)
}
}
- if (priv->do_fw_download) {
- err = orinoco_download(priv);
- if (err)
- priv->do_fw_download = 0;
- }
-
err = orinoco_reinit_firmware(dev);
if (err) {
printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n",
@@ -3056,6 +3106,50 @@ irqreturn_t orinoco_interrupt(int irq, void *dev_id)
}
/********************************************************************/
+/* Power management */
+/********************************************************************/
+#if defined(CONFIG_PM_SLEEP) && !defined(CONFIG_HERMES_CACHE_FW_ON_INIT)
+static int orinoco_pm_notifier(struct notifier_block *notifier,
+ unsigned long pm_event,
+ void *unused)
+{
+ struct orinoco_private *priv = container_of(notifier,
+ struct orinoco_private,
+ pm_notifier);
+
+ /* All we need to do is cache the firmware before suspend, and
+ * release it when we come out.
+ *
+ * Only need to do this if we're downloading firmware. */
+ if (!priv->do_fw_download)
+ return NOTIFY_DONE;
+
+ switch (pm_event) {
+ case PM_HIBERNATION_PREPARE:
+ case PM_SUSPEND_PREPARE:
+ orinoco_cache_fw(priv, 0);
+ break;
+
+ case PM_POST_RESTORE:
+ /* Restore from hibernation failed. We need to clean
+ * up in exactly the same way, so fall through. */
+ case PM_POST_HIBERNATION:
+ case PM_POST_SUSPEND:
+ orinoco_uncache_fw(priv);
+ break;
+
+ case PM_RESTORE_PREPARE:
+ default:
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+#else /* !PM_SLEEP || HERMES_CACHE_FW_ON_INIT */
+#define orinoco_pm_notifier NULL
+#endif
+
+/********************************************************************/
/* Initialization */
/********************************************************************/
@@ -3277,11 +3371,10 @@ static int orinoco_init(struct net_device *dev)
struct hermes_idstring nickbuf;
u16 reclen;
int len;
- DECLARE_MAC_BUF(mac);
/* No need to lock, the hw_unavailable flag is already set in
* alloc_orinocodev() */
- priv->nicbuf_size = IEEE80211_FRAME_LEN + ETH_HLEN;
+ priv->nicbuf_size = IEEE80211_MAX_FRAME_LEN + ETH_HLEN;
/* Initialize the firmware */
err = hermes_init(hw);
@@ -3299,6 +3392,10 @@ static int orinoco_init(struct net_device *dev)
}
if (priv->do_fw_download) {
+#ifdef CONFIG_HERMES_CACHE_FW_ON_INIT
+ orinoco_cache_fw(priv, 0);
+#endif
+
err = orinoco_download(priv);
if (err)
priv->do_fw_download = 0;
@@ -3348,8 +3445,8 @@ static int orinoco_init(struct net_device *dev)
goto out;
}
- printk(KERN_DEBUG "%s: MAC address %s\n",
- dev->name, print_mac(mac, dev->dev_addr));
+ printk(KERN_DEBUG "%s: MAC address %pM\n",
+ dev->name, dev->dev_addr);
/* Get the station name */
err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
@@ -3535,6 +3632,13 @@ struct net_device
netif_carrier_off(dev);
priv->last_linkstatus = 0xffff;
+ priv->cached_pri_fw = NULL;
+ priv->cached_fw = NULL;
+
+ /* Register PM notifiers */
+ priv->pm_notifier.notifier_call = orinoco_pm_notifier;
+ register_pm_notifier(&priv->pm_notifier);
+
return dev;
}
@@ -3546,6 +3650,10 @@ void free_orinocodev(struct net_device *dev)
* when we call tasklet_kill it will run one final time,
* emptying the list */
tasklet_kill(&priv->rx_tasklet);
+
+ unregister_pm_notifier(&priv->pm_notifier);
+ orinoco_uncache_fw(priv);
+
priv->wpa_ie_len = 0;
kfree(priv->wpa_ie);
orinoco_mic_free(priv);
@@ -4672,7 +4780,7 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
/* Determine and validate the key index */
idx = encoding->flags & IW_ENCODE_INDEX;
if (idx) {
- if ((idx < 1) || (idx > WEP_KEYS))
+ if ((idx < 1) || (idx > 4))
goto out;
idx--;
} else
@@ -4777,7 +4885,7 @@ static int orinoco_ioctl_get_encodeext(struct net_device *dev,
idx = encoding->flags & IW_ENCODE_INDEX;
if (idx) {
- if ((idx < 1) || (idx > WEP_KEYS))
+ if ((idx < 1) || (idx > 4))
goto out;
idx--;
} else
@@ -4940,7 +5048,8 @@ static int orinoco_ioctl_set_genie(struct net_device *dev,
unsigned long flags;
int err = 0;
- if ((wrqu->data.length > MAX_WPA_IE_LEN) ||
+ /* cut off at IEEE80211_MAX_DATA_LEN */
+ if ((wrqu->data.length > IEEE80211_MAX_DATA_LEN) ||
(wrqu->data.length && (extra == NULL)))
return -EINVAL;
@@ -5433,7 +5542,7 @@ static inline char *orinoco_translate_scan(struct net_device *dev,
char *current_ev,
char *end_buf,
union hermes_scan_info *bss,
- unsigned int last_scanned)
+ unsigned long last_scanned)
{
struct orinoco_private *priv = netdev_priv(dev);
u16 capabilities;
@@ -5580,7 +5689,7 @@ static inline char *orinoco_translate_ext_scan(struct net_device *dev,
char *current_ev,
char *end_buf,
struct agere_ext_scan_info *bss,
- unsigned int last_scanned)
+ unsigned long last_scanned)
{
u16 capabilities;
u16 channel;
@@ -5623,7 +5732,7 @@ static inline char *orinoco_translate_ext_scan(struct net_device *dev,
&iwe, IW_EV_UINT_LEN);
}
- ie = orinoco_get_ie(bss->data, sizeof(bss->data), MFIE_TYPE_DS_SET);
+ ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_DS_PARAMS);
channel = ie ? ie[2] : 0;
if ((channel >= 1) && (channel <= NUM_CHANNELS)) {
/* Add channel and frequency */
@@ -5673,7 +5782,7 @@ static inline char *orinoco_translate_ext_scan(struct net_device *dev,
}
/* RSN IE */
- ie = orinoco_get_ie(bss->data, sizeof(bss->data), MFIE_TYPE_RSN);
+ ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_RSN);
if (ie) {
iwe.cmd = IWEVGENIE;
iwe.u.data.length = ie[1] + 2;
@@ -5681,7 +5790,7 @@ static inline char *orinoco_translate_ext_scan(struct net_device *dev,
&iwe, ie);
}
- ie = orinoco_get_ie(bss->data, sizeof(bss->data), MFIE_TYPE_RATES);
+ ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_SUPP_RATES);
if (ie) {
char *p = current_ev + iwe_stream_lcp_len(info);
int i;
@@ -5976,7 +6085,7 @@ static void orinoco_get_drvinfo(struct net_device *dev,
strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1);
strncpy(info->fw_version, priv->fw_name, sizeof(info->fw_version) - 1);
if (dev->dev.parent)
- strncpy(info->bus_info, dev->dev.parent->bus_id,
+ strncpy(info->bus_info, dev_name(dev->dev.parent),
sizeof(info->bus_info) - 1);
else
snprintf(info->bus_info, sizeof(info->bus_info) - 1,
diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h
index 981570bd3b9d..00750c8ba7db 100644
--- a/drivers/net/wireless/orinoco.h
+++ b/drivers/net/wireless/orinoco/orinoco.h
@@ -10,6 +10,7 @@
#define DRIVER_VERSION "0.15"
#include <linux/interrupt.h>
+#include <linux/suspend.h>
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <net/iw_handler.h>
@@ -66,6 +67,8 @@ struct orinoco_rx_data {
struct list_head list;
};
+struct firmware;
+
struct orinoco_private {
void *card; /* Pointer to card dependent structure */
struct device *dev;
@@ -164,6 +167,12 @@ struct orinoco_private {
unsigned int wpa_enabled:1;
unsigned int tkip_cm_active:1;
unsigned int key_mgmt:3;
+
+ /* Cached in memory firmware to use during ->resume. */
+ const struct firmware *cached_pri_fw;
+ const struct firmware *cached_fw;
+
+ struct notifier_block pm_notifier;
};
#ifdef ORINOCO_DEBUG
diff --git a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c
index 6fcf2bda7cdf..f127602670ec 100644
--- a/drivers/net/wireless/orinoco_cs.c
+++ b/drivers/net/wireless/orinoco/orinoco_cs.c
@@ -178,13 +178,17 @@ static int orinoco_cs_config_check(struct pcmcia_device *p_dev,
/* Note that the CIS values need to be rescaled */
if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
- DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
+ DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
+ __func__, vcc,
+ cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
if (!ignore_cis_vcc)
goto next_entry;
}
} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
- DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
+ DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
+ __func__, vcc,
+ dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
if (!ignore_cis_vcc)
goto next_entry;
}
@@ -308,7 +312,7 @@ orinoco_cs_config(struct pcmcia_device *link)
/* Finally, report what we've done */
printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io "
- "0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id,
+ "0x%04x-0x%04x\n", dev->name, dev_name(dev->dev.parent),
link->irq.AssignedIRQ, link->io.BasePort1,
link->io.BasePort1 + link->io.NumPorts1 - 1);
return 0;
diff --git a/drivers/net/wireless/orinoco_nortel.c b/drivers/net/wireless/orinoco/orinoco_nortel.c
index 2fc86596302e..2fc86596302e 100644
--- a/drivers/net/wireless/orinoco_nortel.c
+++ b/drivers/net/wireless/orinoco/orinoco_nortel.c
diff --git a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c
index 4ebd638a073e..4ebd638a073e 100644
--- a/drivers/net/wireless/orinoco_pci.c
+++ b/drivers/net/wireless/orinoco/orinoco_pci.c
diff --git a/drivers/net/wireless/orinoco_pci.h b/drivers/net/wireless/orinoco/orinoco_pci.h
index f4e5e06760c1..f4e5e06760c1 100644
--- a/drivers/net/wireless/orinoco_pci.h
+++ b/drivers/net/wireless/orinoco/orinoco_pci.h
diff --git a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c
index ef761857bb38..ef761857bb38 100644
--- a/drivers/net/wireless/orinoco_plx.c
+++ b/drivers/net/wireless/orinoco/orinoco_plx.c
diff --git a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c
index ede24ec309c0..ede24ec309c0 100644
--- a/drivers/net/wireless/orinoco_tmd.c
+++ b/drivers/net/wireless/orinoco/orinoco_tmd.c
diff --git a/drivers/net/wireless/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c
index 852789ad34b3..b2ca2e39c2cb 100644
--- a/drivers/net/wireless/spectrum_cs.c
+++ b/drivers/net/wireless/orinoco/spectrum_cs.c
@@ -248,13 +248,17 @@ static int spectrum_cs_config_check(struct pcmcia_device *p_dev,
/* Note that the CIS values need to be rescaled */
if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
- DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
+ DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
+ __func__, vcc,
+ cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
if (!ignore_cis_vcc)
goto next_entry;
}
} else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
- DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
+ DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n",
+ __func__, vcc,
+ dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
if (!ignore_cis_vcc)
goto next_entry;
}
@@ -383,7 +387,7 @@ spectrum_cs_config(struct pcmcia_device *link)
/* Finally, report what we've done */
printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io "
- "0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id,
+ "0x%04x-0x%04x\n", dev->name, dev_name(dev->dev.parent),
link->irq.AssignedIRQ, link->io.BasePort1,
link->io.BasePort1 + link->io.NumPorts1 - 1);
@@ -450,10 +454,29 @@ spectrum_cs_resume(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
struct orinoco_private *priv = netdev_priv(dev);
+ unsigned long flags;
+ int err;
+
+ err = orinoco_reinit_firmware(dev);
+ if (err) {
+ printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
+ dev->name, err);
+ return -EIO;
+ }
+
+ spin_lock_irqsave(&priv->lock, flags);
netif_device_attach(dev);
priv->hw_unavailable--;
- schedule_work(&priv->reset_work);
+
+ if (priv->open && !priv->hw_unavailable) {
+ err = __orinoco_up(dev);
+ if (err)
+ printk(KERN_ERR "%s: Error %d restarting card\n",
+ dev->name, err);
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
return 0;
}
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h
index 1d0704fe146f..ab79e32f0b27 100644
--- a/drivers/net/wireless/p54/p54.h
+++ b/drivers/net/wireless/p54/p54.h
@@ -14,17 +14,17 @@
* published by the Free Software Foundation.
*/
-enum control_frame_types {
- P54_CONTROL_TYPE_FILTER_SET = 0,
- P54_CONTROL_TYPE_CHANNEL_CHANGE,
- P54_CONTROL_TYPE_FREQDONE,
+enum p54_control_frame_types {
+ P54_CONTROL_TYPE_SETUP = 0,
+ P54_CONTROL_TYPE_SCAN,
+ P54_CONTROL_TYPE_TRAP,
P54_CONTROL_TYPE_DCFINIT,
- P54_CONTROL_TYPE_ENCRYPTION,
+ P54_CONTROL_TYPE_RX_KEYCACHE,
P54_CONTROL_TYPE_TIM,
- P54_CONTROL_TYPE_POWERMGT,
- P54_CONTROL_TYPE_FREEQUEUE,
+ P54_CONTROL_TYPE_PSM,
+ P54_CONTROL_TYPE_TXCANCEL,
P54_CONTROL_TYPE_TXDONE,
- P54_CONTROL_TYPE_PING,
+ P54_CONTROL_TYPE_BURST,
P54_CONTROL_TYPE_STAT_READBACK,
P54_CONTROL_TYPE_BBP,
P54_CONTROL_TYPE_EEPROM_READBACK,
@@ -37,18 +37,44 @@ enum control_frame_types {
P54_CONTROL_TYPE_XBOW_SYNTH_CFG,
P54_CONTROL_TYPE_CCE_QUIET,
P54_CONTROL_TYPE_PSM_STA_UNLOCK,
+ P54_CONTROL_TYPE_PCS,
+ P54_CONTROL_TYPE_BT_BALANCER = 28,
+ P54_CONTROL_TYPE_GROUP_ADDRESS_TABLE = 30,
+ P54_CONTROL_TYPE_ARPTABLE = 31,
+ P54_CONTROL_TYPE_BT_OPTIONS = 35
};
-struct p54_control_hdr {
- __le16 magic1;
+#define P54_HDR_FLAG_CONTROL BIT(15)
+#define P54_HDR_FLAG_CONTROL_OPSET (BIT(15) + BIT(0))
+
+struct p54_hdr {
+ __le16 flags;
__le16 len;
__le32 req_id;
- __le16 type; /* enum control_frame_types */
- u8 retry1;
- u8 retry2;
+ __le16 type; /* enum p54_control_frame_types */
+ u8 rts_tries;
+ u8 tries;
u8 data[0];
} __attribute__ ((packed));
+#define FREE_AFTER_TX(skb) \
+ ((((struct p54_hdr *) ((struct sk_buff *) skb)->data)-> \
+ flags) == cpu_to_le16(P54_HDR_FLAG_CONTROL_OPSET))
+
+struct p54_edcf_queue_param {
+ __le16 aifs;
+ __le16 cwmin;
+ __le16 cwmax;
+ __le16 txop;
+} __attribute__ ((packed));
+
+struct p54_rssi_linear_approximation {
+ s16 mul;
+ s16 add;
+ s16 longbow_unkn;
+ s16 longbow_unk2;
+};
+
#define EEPROM_READBACK_LEN 0x3fc
#define ISL38XX_DEV_FIRMWARE_ADDR 0x20000
@@ -59,49 +85,53 @@ struct p54_control_hdr {
#define FW_LM20 0x4c4d3230
struct p54_common {
+ struct ieee80211_hw *hw;
u32 rx_start;
u32 rx_end;
struct sk_buff_head tx_queue;
- void (*tx)(struct ieee80211_hw *dev, struct p54_control_hdr *data,
- size_t len, int free_on_tx);
+ void (*tx)(struct ieee80211_hw *dev, struct sk_buff *skb);
int (*open)(struct ieee80211_hw *dev);
void (*stop)(struct ieee80211_hw *dev);
int mode;
- u16 seqno;
u16 rx_mtu;
u8 headroom;
u8 tailroom;
struct mutex conf_mutex;
u8 mac_addr[ETH_ALEN];
u8 bssid[ETH_ALEN];
- __le16 filter_type;
struct pda_iq_autocal_entry *iq_autocal;
unsigned int iq_autocal_len;
struct pda_channel_output_limit *output_limit;
unsigned int output_limit_len;
struct pda_pa_curve_data *curve_data;
+ struct p54_rssi_linear_approximation rssical_db[IEEE80211_NUM_BANDS];
unsigned int filter_flags;
+ bool use_short_slot;
u16 rxhw;
u8 version;
- u8 rx_antenna;
unsigned int tx_hdr_len;
- void *cached_vdcf;
unsigned int fw_var;
unsigned int fw_interface;
unsigned int output_power;
u32 tsf_low32;
u32 tsf_high32;
+ u64 basic_rate_mask;
+ u16 wakeup_timer;
+ u16 aid;
struct ieee80211_tx_queue_stats tx_stats[8];
+ struct p54_edcf_queue_param qos_params[8];
struct ieee80211_low_level_stats stats;
- struct timer_list stats_timer;
- struct completion stats_comp;
- void *cached_stats;
+ struct delayed_work work;
+ struct sk_buff *cached_beacon;
int noise;
void *eeprom;
struct completion eeprom_comp;
+ u8 privacy_caps;
+ u8 rx_keycache_size;
};
int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb);
+void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb);
int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw);
int p54_read_eeprom(struct ieee80211_hw *dev);
struct ieee80211_hw *p54_init_common(size_t priv_data_len);
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c
index 827ca0384a4c..82354b974a04 100644
--- a/drivers/net/wireless/p54/p54common.c
+++ b/drivers/net/wireless/p54/p54common.c
@@ -1,12 +1,15 @@
-
/*
* Common code for mac80211 Prism54 drivers
*
* Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
* Copyright (c) 2007, Christian Lamparter <chunkeey@web.de>
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
*
- * Based on the islsm (softmac prism54) driver, which is:
- * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
+ * Based on:
+ * - the islsm (softmac prism54) driver, which is:
+ * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
+ * - stlc45xx driver
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
*
* 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
@@ -22,6 +25,9 @@
#include "p54.h"
#include "p54common.h"
+static int modparam_nohwcrypt;
+module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
MODULE_DESCRIPTION("Softmac Prism54 common code");
MODULE_LICENSE("GPL");
@@ -152,21 +158,21 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
priv->fw_interface = be32_to_cpup((__be32 *)
bootrec->data);
switch (priv->fw_interface) {
- case FW_FMAC:
- printk(KERN_INFO "p54: FreeMAC firmware\n");
- break;
- case FW_LM20:
- printk(KERN_INFO "p54: LM20 firmware\n");
- break;
case FW_LM86:
- printk(KERN_INFO "p54: LM86 firmware\n");
- break;
- case FW_LM87:
- printk(KERN_INFO "p54: LM87 firmware\n");
+ case FW_LM20:
+ case FW_LM87: {
+ char *iftype = (char *)bootrec->data;
+ printk(KERN_INFO "%s: p54 detected a LM%c%c "
+ "firmware\n",
+ wiphy_name(dev->wiphy),
+ iftype[2], iftype[3]);
break;
+ }
+ case FW_FMAC:
default:
- printk(KERN_INFO "p54: unknown firmware\n");
- break;
+ printk(KERN_ERR "%s: unsupported firmware\n",
+ wiphy_name(dev->wiphy));
+ return -ENODEV;
}
break;
case BR_CODE_COMPONENT_VERSION:
@@ -182,8 +188,10 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
priv->rx_end = le32_to_cpu(desc->rx_end) - 0x3500;
priv->headroom = desc->headroom;
priv->tailroom = desc->tailroom;
+ priv->privacy_caps = desc->privacy_caps;
+ priv->rx_keycache_size = desc->rx_keycache_size;
if (le32_to_cpu(bootrec->len) == 11)
- priv->rx_mtu = le16_to_cpu(bootrec->rx_mtu);
+ priv->rx_mtu = le16_to_cpu(desc->rx_mtu);
else
priv->rx_mtu = (size_t)
0x620 - priv->tx_hdr_len;
@@ -208,18 +216,35 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw)
}
if (fw_version)
- printk(KERN_INFO "p54: FW rev %s - Softmac protocol %x.%x\n",
- fw_version, priv->fw_var >> 8, priv->fw_var & 0xff);
+ printk(KERN_INFO "%s: FW rev %s - Softmac protocol %x.%x\n",
+ wiphy_name(dev->wiphy), fw_version,
+ priv->fw_var >> 8, priv->fw_var & 0xff);
+
+ if (priv->fw_var < 0x500)
+ printk(KERN_INFO "%s: you are using an obsolete firmware. "
+ "visit http://wireless.kernel.org/en/users/Drivers/p54 "
+ "and grab one for \"kernel >= 2.6.28\"!\n",
+ wiphy_name(dev->wiphy));
if (priv->fw_var >= 0x300) {
/* Firmware supports QoS, use it! */
- priv->tx_stats[4].limit = 3;
- priv->tx_stats[5].limit = 4;
- priv->tx_stats[6].limit = 3;
- priv->tx_stats[7].limit = 1;
+ priv->tx_stats[4].limit = 3; /* AC_VO */
+ priv->tx_stats[5].limit = 4; /* AC_VI */
+ priv->tx_stats[6].limit = 3; /* AC_BE */
+ priv->tx_stats[7].limit = 2; /* AC_BK */
dev->queues = 4;
}
+ if (!modparam_nohwcrypt)
+ printk(KERN_INFO "%s: cryptographic accelerator "
+ "WEP:%s, TKIP:%s, CCMP:%s\n",
+ wiphy_name(dev->wiphy),
+ (priv->privacy_caps & BR_DESC_PRIV_CAP_WEP) ? "YES" :
+ "no", (priv->privacy_caps & (BR_DESC_PRIV_CAP_TKIP |
+ BR_DESC_PRIV_CAP_MICHAEL)) ? "YES" : "no",
+ (priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP) ?
+ "YES" : "no");
+
return 0;
}
EXPORT_SYMBOL_GPL(p54_parse_firmware);
@@ -310,6 +335,36 @@ static const char *p54_rf_chips[] = { "NULL", "Duette3", "Duette2",
"Frisbee", "Xbow", "Longbow", "NULL", "NULL" };
static int p54_init_xbow_synth(struct ieee80211_hw *dev);
+static void p54_parse_rssical(struct ieee80211_hw *dev, void *data, int len,
+ u16 type)
+{
+ struct p54_common *priv = dev->priv;
+ int offset = (type == PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED) ? 2 : 0;
+ int entry_size = sizeof(struct pda_rssi_cal_entry) + offset;
+ int num_entries = (type == PDR_RSSI_LINEAR_APPROXIMATION) ? 1 : 2;
+ int i;
+
+ if (len != (entry_size * num_entries)) {
+ printk(KERN_ERR "%s: unknown rssi calibration data packing "
+ " type:(%x) len:%d.\n",
+ wiphy_name(dev->wiphy), type, len);
+
+ print_hex_dump_bytes("rssical:", DUMP_PREFIX_NONE,
+ data, len);
+
+ printk(KERN_ERR "%s: please report this issue.\n",
+ wiphy_name(dev->wiphy));
+ return;
+ }
+
+ for (i = 0; i < num_entries; i++) {
+ struct pda_rssi_cal_entry *cal = data +
+ (offset + i * entry_size);
+ priv->rssical_db[i].mul = (s16) le16_to_cpu(cal->mul);
+ priv->rssical_db[i].add = (s16) le16_to_cpu(cal->add);
+ }
+}
+
static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
{
struct p54_common *priv = dev->priv;
@@ -320,7 +375,6 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
int err;
u8 *end = (u8 *)eeprom + len;
u16 synth = 0;
- DECLARE_MAC_BUF(mac);
wrap = (struct eeprom_pda_wrap *) eeprom;
entry = (void *)wrap->data + le16_to_cpu(wrap->len);
@@ -377,8 +431,9 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
err = p54_convert_rev1(dev, curve_data);
break;
default:
- printk(KERN_ERR "p54: unknown curve data "
+ printk(KERN_ERR "%s: unknown curve data "
"revision %d\n",
+ wiphy_name(dev->wiphy),
curve_data->cal_method_rev);
err = -ENODEV;
break;
@@ -409,12 +464,40 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
case PDR_HARDWARE_PLATFORM_COMPONENT_ID:
priv->version = *(u8 *)(entry->data + 1);
break;
+ case PDR_RSSI_LINEAR_APPROXIMATION:
+ case PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND:
+ case PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED:
+ p54_parse_rssical(dev, entry->data, data_len,
+ le16_to_cpu(entry->code));
+ break;
case PDR_END:
/* make it overrun */
entry_len = len;
break;
+ case PDR_MANUFACTURING_PART_NUMBER:
+ case PDR_PDA_VERSION:
+ case PDR_NIC_SERIAL_NUMBER:
+ case PDR_REGULATORY_DOMAIN_LIST:
+ case PDR_TEMPERATURE_TYPE:
+ case PDR_PRISM_PCI_IDENTIFIER:
+ case PDR_COUNTRY_INFORMATION:
+ case PDR_OEM_NAME:
+ case PDR_PRODUCT_NAME:
+ case PDR_UTF8_OEM_NAME:
+ case PDR_UTF8_PRODUCT_NAME:
+ case PDR_COUNTRY_LIST:
+ case PDR_DEFAULT_COUNTRY:
+ case PDR_ANTENNA_GAIN:
+ case PDR_PRISM_INDIGO_PA_CALIBRATION_DATA:
+ case PDR_REGULATORY_POWER_LIMITS:
+ case PDR_RADIATED_TRANSMISSION_CORRECTION:
+ case PDR_PRISM_TX_IQ_CALIBRATION:
+ case PDR_BASEBAND_REGISTERS:
+ case PDR_PER_CHANNEL_BASEBAND_REGISTERS:
+ break;
default:
- printk(KERN_INFO "p54: unknown eeprom code : 0x%x\n",
+ printk(KERN_INFO "%s: unknown eeprom code : 0x%x\n",
+ wiphy_name(dev->wiphy),
le16_to_cpu(entry->code));
break;
}
@@ -424,17 +507,18 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
if (!synth || !priv->iq_autocal || !priv->output_limit ||
!priv->curve_data) {
- printk(KERN_ERR "p54: not all required entries found in eeprom!\n");
+ printk(KERN_ERR "%s: not all required entries found in eeprom!\n",
+ wiphy_name(dev->wiphy));
err = -EINVAL;
goto err;
}
- priv->rxhw = synth & 0x07;
+ priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK;
if (priv->rxhw == 4)
p54_init_xbow_synth(dev);
- if (!(synth & 0x40))
+ if (!(synth & PDR_SYNTH_24_GHZ_DISABLED))
dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2GHz;
- if (!(synth & 0x80))
+ if (!(synth & PDR_SYNTH_5_GHZ_DISABLED))
dev->wiphy->bands[IEEE80211_BAND_5GHZ] = &band_5GHz;
if (!is_valid_ether_addr(dev->wiphy->perm_addr)) {
@@ -446,9 +530,9 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
SET_IEEE80211_PERM_ADDR(dev, perm_addr);
}
- printk(KERN_INFO "%s: hwaddr %s, MAC:isl38%02x RF:%s\n",
+ printk(KERN_INFO "%s: hwaddr %pM, MAC:isl38%02x RF:%s\n",
wiphy_name(dev->wiphy),
- print_mac(mac, dev->wiphy->perm_addr),
+ dev->wiphy->perm_addr,
priv->version, p54_rf_chips[priv->rxhw]);
return 0;
@@ -469,36 +553,56 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len)
priv->curve_data = NULL;
}
- printk(KERN_ERR "p54: eeprom parse failed!\n");
+ printk(KERN_ERR "%s: eeprom parse failed!\n",
+ wiphy_name(dev->wiphy));
return err;
}
static int p54_rssi_to_dbm(struct ieee80211_hw *dev, int rssi)
{
- /* TODO: get the rssi_add & rssi_mul data from the eeprom */
- return ((rssi * 0x83) / 64 - 400) / 4;
+ struct p54_common *priv = dev->priv;
+ int band = dev->conf.channel->band;
+
+ return ((rssi * priv->rssical_db[band].mul) / 64 +
+ priv->rssical_db[band].add) / 4;
}
static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
{
struct p54_common *priv = dev->priv;
- struct p54_rx_hdr *hdr = (struct p54_rx_hdr *) skb->data;
+ struct p54_rx_data *hdr = (struct p54_rx_data *) skb->data;
struct ieee80211_rx_status rx_status = {0};
u16 freq = le16_to_cpu(hdr->freq);
size_t header_len = sizeof(*hdr);
u32 tsf32;
- if (!(hdr->magic & cpu_to_le16(0x0001))) {
+ /*
+ * If the device is in a unspecified state we have to
+ * ignore all data frames. Else we could end up with a
+ * nasty crash.
+ */
+ if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
+ return 0;
+
+ if (!(hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_IN_FCS_GOOD))) {
if (priv->filter_flags & FIF_FCSFAIL)
rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
else
return 0;
}
+ if (hdr->decrypt_status == P54_DECRYPT_OK)
+ rx_status.flag |= RX_FLAG_DECRYPTED;
+ if ((hdr->decrypt_status == P54_DECRYPT_FAIL_MICHAEL) ||
+ (hdr->decrypt_status == P54_DECRYPT_FAIL_TKIP))
+ rx_status.flag |= RX_FLAG_MMIC_ERROR;
+
rx_status.signal = p54_rssi_to_dbm(dev, hdr->rssi);
rx_status.noise = priv->noise;
/* XX correct? */
rx_status.qual = (100 * hdr->rssi) / 127;
+ if (hdr->rate & 0x10)
+ rx_status.flag |= RX_FLAG_SHORTPRE;
rx_status.rate_idx = (dev->conf.channel->band == IEEE80211_BAND_2GHZ ?
hdr->rate : (hdr->rate - 4)) & 0xf;
rx_status.freq = freq;
@@ -513,7 +617,7 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
rx_status.flag |= RX_FLAG_TSFT;
- if (hdr->magic & cpu_to_le16(0x4000))
+ if (hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN))
header_len += hdr->align[0];
skb_pull(skb, header_len);
@@ -521,6 +625,9 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb)
ieee80211_rx_irqsafe(dev, skb, &rx_status);
+ queue_delayed_work(dev->workqueue, &priv->work,
+ msecs_to_jiffies(P54_STATISTICS_UPDATE));
+
return -1;
}
@@ -529,88 +636,197 @@ static void inline p54_wake_free_queues(struct ieee80211_hw *dev)
struct p54_common *priv = dev->priv;
int i;
+ if (priv->mode == NL80211_IFTYPE_UNSPECIFIED)
+ return ;
+
for (i = 0; i < dev->queues; i++)
if (priv->tx_stats[i + 4].len < priv->tx_stats[i + 4].limit)
ieee80211_wake_queue(dev, i);
}
+void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb)
+{
+ struct p54_common *priv = dev->priv;
+ struct ieee80211_tx_info *info;
+ struct memrecord *range;
+ unsigned long flags;
+ u32 freed = 0, last_addr = priv->rx_start;
+
+ if (unlikely(!skb || !dev || !skb_queue_len(&priv->tx_queue)))
+ return;
+
+ /*
+ * don't try to free an already unlinked skb
+ */
+ if (unlikely((!skb->next) || (!skb->prev)))
+ return;
+
+ spin_lock_irqsave(&priv->tx_queue.lock, flags);
+ info = IEEE80211_SKB_CB(skb);
+ range = (void *)info->rate_driver_data;
+ if (skb->prev != (struct sk_buff *)&priv->tx_queue) {
+ struct ieee80211_tx_info *ni;
+ struct memrecord *mr;
+
+ ni = IEEE80211_SKB_CB(skb->prev);
+ mr = (struct memrecord *)ni->rate_driver_data;
+ last_addr = mr->end_addr;
+ }
+ if (skb->next != (struct sk_buff *)&priv->tx_queue) {
+ struct ieee80211_tx_info *ni;
+ struct memrecord *mr;
+
+ ni = IEEE80211_SKB_CB(skb->next);
+ mr = (struct memrecord *)ni->rate_driver_data;
+ freed = mr->start_addr - last_addr;
+ } else
+ freed = priv->rx_end - last_addr;
+ __skb_unlink(skb, &priv->tx_queue);
+ spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+ dev_kfree_skb_any(skb);
+
+ if (freed >= priv->headroom + sizeof(struct p54_hdr) + 48 +
+ IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom)
+ p54_wake_free_queues(dev);
+}
+EXPORT_SYMBOL_GPL(p54_free_skb);
+
+static struct sk_buff *p54_find_tx_entry(struct ieee80211_hw *dev,
+ __le32 req_id)
+{
+ struct p54_common *priv = dev->priv;
+ struct sk_buff *entry = priv->tx_queue.next;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->tx_queue.lock, flags);
+ while (entry != (struct sk_buff *)&priv->tx_queue) {
+ struct p54_hdr *hdr = (struct p54_hdr *) entry->data;
+
+ if (hdr->req_id == req_id) {
+ spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+ return entry;
+ }
+ entry = entry->next;
+ }
+ spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+ return NULL;
+}
+
static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb)
{
struct p54_common *priv = dev->priv;
- struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
- struct p54_frame_sent_hdr *payload = (struct p54_frame_sent_hdr *) hdr->data;
+ struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
+ struct p54_frame_sent *payload = (struct p54_frame_sent *) hdr->data;
struct sk_buff *entry = (struct sk_buff *) priv->tx_queue.next;
u32 addr = le32_to_cpu(hdr->req_id) - priv->headroom;
struct memrecord *range = NULL;
u32 freed = 0;
u32 last_addr = priv->rx_start;
unsigned long flags;
+ int count, idx;
spin_lock_irqsave(&priv->tx_queue.lock, flags);
while (entry != (struct sk_buff *)&priv->tx_queue) {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry);
- range = (void *)info->driver_data;
- if (range->start_addr == addr) {
- struct p54_control_hdr *entry_hdr;
- struct p54_tx_control_allocdata *entry_data;
- int pad = 0;
-
- if (entry->next != (struct sk_buff *)&priv->tx_queue) {
- struct ieee80211_tx_info *ni;
- struct memrecord *mr;
-
- ni = IEEE80211_SKB_CB(entry->next);
- mr = (struct memrecord *)ni->driver_data;
- freed = mr->start_addr - last_addr;
- } else
- freed = priv->rx_end - last_addr;
+ struct p54_hdr *entry_hdr;
+ struct p54_tx_data *entry_data;
+ int pad = 0;
+ range = (void *)info->rate_driver_data;
+ if (range->start_addr != addr) {
last_addr = range->end_addr;
- __skb_unlink(entry, &priv->tx_queue);
- spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+ entry = entry->next;
+ continue;
+ }
- memset(&info->status, 0, sizeof(info->status));
- entry_hdr = (struct p54_control_hdr *) entry->data;
- entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data;
- if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0)
- pad = entry_data->align[0];
-
- priv->tx_stats[entry_data->hw_queue].len--;
- if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
- if (!(payload->status & 0x01))
- info->flags |= IEEE80211_TX_STAT_ACK;
- else
- info->status.excessive_retries = 1;
- }
- info->status.retry_count = payload->retries - 1;
- info->status.ack_signal = p54_rssi_to_dbm(dev,
- le16_to_cpu(payload->ack_rssi));
- skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
- ieee80211_tx_status_irqsafe(dev, entry);
- goto out;
+ if (entry->next != (struct sk_buff *)&priv->tx_queue) {
+ struct ieee80211_tx_info *ni;
+ struct memrecord *mr;
+
+ ni = IEEE80211_SKB_CB(entry->next);
+ mr = (struct memrecord *)ni->rate_driver_data;
+ freed = mr->start_addr - last_addr;
} else
- last_addr = range->end_addr;
- entry = entry->next;
+ freed = priv->rx_end - last_addr;
+
+ last_addr = range->end_addr;
+ __skb_unlink(entry, &priv->tx_queue);
+ spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+
+ entry_hdr = (struct p54_hdr *) entry->data;
+ entry_data = (struct p54_tx_data *) entry_hdr->data;
+ priv->tx_stats[entry_data->hw_queue].len--;
+ priv->stats.dot11ACKFailureCount += payload->tries - 1;
+
+ if (unlikely(entry == priv->cached_beacon)) {
+ kfree_skb(entry);
+ priv->cached_beacon = NULL;
+ goto out;
+ }
+
+ /*
+ * Clear manually, ieee80211_tx_info_clear_status would
+ * clear the counts too and we need them.
+ */
+ memset(&info->status.ampdu_ack_len, 0,
+ sizeof(struct ieee80211_tx_info) -
+ offsetof(struct ieee80211_tx_info, status.ampdu_ack_len));
+ BUILD_BUG_ON(offsetof(struct ieee80211_tx_info,
+ status.ampdu_ack_len) != 23);
+
+ if (entry_hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN))
+ pad = entry_data->align[0];
+
+ /* walk through the rates array and adjust the counts */
+ count = payload->tries;
+ for (idx = 0; idx < 4; idx++) {
+ if (count >= info->status.rates[idx].count) {
+ count -= info->status.rates[idx].count;
+ } else if (count > 0) {
+ info->status.rates[idx].count = count;
+ count = 0;
+ } else {
+ info->status.rates[idx].idx = -1;
+ info->status.rates[idx].count = 0;
+ }
+ }
+
+ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
+ (!payload->status))
+ info->flags |= IEEE80211_TX_STAT_ACK;
+ if (payload->status & P54_TX_PSM_CANCELLED)
+ info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+ info->status.ack_signal = p54_rssi_to_dbm(dev,
+ (int)payload->ack_rssi);
+ skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data));
+ ieee80211_tx_status_irqsafe(dev, entry);
+ goto out;
}
spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
out:
- if (freed >= IEEE80211_MAX_RTS_THRESHOLD + 0x170 +
- sizeof(struct p54_control_hdr))
+ if (freed >= priv->headroom + sizeof(struct p54_hdr) + 48 +
+ IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom)
p54_wake_free_queues(dev);
}
static void p54_rx_eeprom_readback(struct ieee80211_hw *dev,
struct sk_buff *skb)
{
- struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
+ struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
struct p54_eeprom_lm86 *eeprom = (struct p54_eeprom_lm86 *) hdr->data;
struct p54_common *priv = dev->priv;
if (!priv->eeprom)
return ;
- memcpy(priv->eeprom, eeprom->data, le16_to_cpu(eeprom->len));
+ if (priv->fw_var >= 0x509) {
+ memcpy(priv->eeprom, eeprom->v2.data,
+ le16_to_cpu(eeprom->v2.len));
+ } else {
+ memcpy(priv->eeprom, eeprom->v1.data,
+ le16_to_cpu(eeprom->v1.len));
+ }
complete(&priv->eeprom_comp);
}
@@ -618,10 +834,14 @@ static void p54_rx_eeprom_readback(struct ieee80211_hw *dev,
static void p54_rx_stats(struct ieee80211_hw *dev, struct sk_buff *skb)
{
struct p54_common *priv = dev->priv;
- struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
+ struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
struct p54_statistics *stats = (struct p54_statistics *) hdr->data;
- u32 tsf32 = le32_to_cpu(stats->tsf32);
+ u32 tsf32;
+
+ if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
+ return ;
+ tsf32 = le32_to_cpu(stats->tsf32);
if (tsf32 < priv->tsf_low32)
priv->tsf_high32++;
priv->tsf_low32 = tsf32;
@@ -631,19 +851,50 @@ static void p54_rx_stats(struct ieee80211_hw *dev, struct sk_buff *skb)
priv->stats.dot11FCSErrorCount = le32_to_cpu(stats->rx_bad_fcs);
priv->noise = p54_rssi_to_dbm(dev, le32_to_cpu(stats->noise));
- complete(&priv->stats_comp);
- mod_timer(&priv->stats_timer, jiffies + 5 * HZ);
+ p54_free_skb(dev, p54_find_tx_entry(dev, hdr->req_id));
+}
+
+static void p54_rx_trap(struct ieee80211_hw *dev, struct sk_buff *skb)
+{
+ struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
+ struct p54_trap *trap = (struct p54_trap *) hdr->data;
+ u16 event = le16_to_cpu(trap->event);
+ u16 freq = le16_to_cpu(trap->frequency);
+
+ switch (event) {
+ case P54_TRAP_BEACON_TX:
+ break;
+ case P54_TRAP_RADAR:
+ printk(KERN_INFO "%s: radar (freq:%d MHz)\n",
+ wiphy_name(dev->wiphy), freq);
+ break;
+ case P54_TRAP_NO_BEACON:
+ break;
+ case P54_TRAP_SCAN:
+ break;
+ case P54_TRAP_TBTT:
+ break;
+ case P54_TRAP_TIMER:
+ break;
+ default:
+ printk(KERN_INFO "%s: received event:%x freq:%d\n",
+ wiphy_name(dev->wiphy), event, freq);
+ break;
+ }
}
static int p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb)
{
- struct p54_control_hdr *hdr = (struct p54_control_hdr *) skb->data;
+ struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
switch (le16_to_cpu(hdr->type)) {
case P54_CONTROL_TYPE_TXDONE:
p54_rx_frame_sent(dev, skb);
break;
+ case P54_CONTROL_TYPE_TRAP:
+ p54_rx_trap(dev, skb);
+ break;
case P54_CONTROL_TYPE_BBP:
break;
case P54_CONTROL_TYPE_STAT_READBACK:
@@ -664,9 +915,9 @@ static int p54_rx_control(struct ieee80211_hw *dev, struct sk_buff *skb)
/* returns zero if skb can be reused */
int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb)
{
- u8 type = le16_to_cpu(*((__le16 *)skb->data)) >> 8;
+ u16 type = le16_to_cpu(*((__le16 *)skb->data));
- if (type == 0x80)
+ if (type & P54_HDR_FLAG_CONTROL)
return p54_rx_control(dev, skb);
else
return p54_rx_data(dev, skb);
@@ -682,12 +933,14 @@ EXPORT_SYMBOL_GPL(p54_rx);
* marks allocated areas as reserved if necessary. p54_rx_frame_sent frees
* allocated areas.
*/
-static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
- struct p54_control_hdr *data, u32 len)
+static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
+ struct p54_hdr *data, u32 len)
{
struct p54_common *priv = dev->priv;
struct sk_buff *entry = priv->tx_queue.next;
struct sk_buff *target_skb = NULL;
+ struct ieee80211_tx_info *info;
+ struct memrecord *range;
u32 last_addr = priv->rx_start;
u32 largest_hole = 0;
u32 target_addr = priv->rx_start;
@@ -695,12 +948,37 @@ static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
unsigned int left;
len = (len + priv->headroom + priv->tailroom + 3) & ~0x3;
+ if (!skb)
+ return -EINVAL;
+
spin_lock_irqsave(&priv->tx_queue.lock, flags);
+
left = skb_queue_len(&priv->tx_queue);
+ if (unlikely(left >= 28)) {
+ /*
+ * The tx_queue is nearly full!
+ * We have throttle normal data traffic, because we must
+ * have a few spare slots for control frames left.
+ */
+ ieee80211_stop_queues(dev);
+ queue_delayed_work(dev->workqueue, &priv->work,
+ msecs_to_jiffies(P54_TX_TIMEOUT));
+
+ if (unlikely(left == 32)) {
+ /*
+ * The tx_queue is now really full.
+ *
+ * TODO: check if the device has crashed and reset it.
+ */
+ spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+ return -ENOSPC;
+ }
+ }
+
while (left--) {
u32 hole_size;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(entry);
- struct memrecord *range = (void *)info->driver_data;
+ info = IEEE80211_SKB_CB(entry);
+ range = (void *)info->rate_driver_data;
hole_size = range->start_addr - last_addr;
if (!target_skb && hole_size >= len) {
target_skb = entry->prev;
@@ -715,64 +993,102 @@ static void p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb,
target_skb = priv->tx_queue.prev;
largest_hole = max(largest_hole, priv->rx_end - last_addr - len);
if (!skb_queue_empty(&priv->tx_queue)) {
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(target_skb);
- struct memrecord *range = (void *)info->driver_data;
+ info = IEEE80211_SKB_CB(target_skb);
+ range = (void *)info->rate_driver_data;
target_addr = range->end_addr;
}
} else
largest_hole = max(largest_hole, priv->rx_end - last_addr);
- if (skb) {
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct memrecord *range = (void *)info->driver_data;
- range->start_addr = target_addr;
- range->end_addr = target_addr + len;
- __skb_queue_after(&priv->tx_queue, target_skb, skb);
- if (largest_hole < priv->rx_mtu + priv->headroom +
- priv->tailroom +
- sizeof(struct p54_control_hdr))
- ieee80211_stop_queues(dev);
+ if (!target_skb) {
+ spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+ ieee80211_stop_queues(dev);
+ return -ENOSPC;
}
+
+ info = IEEE80211_SKB_CB(skb);
+ range = (void *)info->rate_driver_data;
+ range->start_addr = target_addr;
+ range->end_addr = target_addr + len;
+ __skb_queue_after(&priv->tx_queue, target_skb, skb);
spin_unlock_irqrestore(&priv->tx_queue.lock, flags);
+ if (largest_hole < priv->headroom + sizeof(struct p54_hdr) +
+ 48 + IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom)
+ ieee80211_stop_queues(dev);
+
data->req_id = cpu_to_le32(target_addr + priv->headroom);
+ return 0;
+}
+
+static struct sk_buff *p54_alloc_skb(struct ieee80211_hw *dev,
+ u16 hdr_flags, u16 len, u16 type, gfp_t memflags)
+{
+ struct p54_common *priv = dev->priv;
+ struct p54_hdr *hdr;
+ struct sk_buff *skb;
+
+ skb = __dev_alloc_skb(len + priv->tx_hdr_len, memflags);
+ if (!skb)
+ return NULL;
+ skb_reserve(skb, priv->tx_hdr_len);
+
+ hdr = (struct p54_hdr *) skb_put(skb, sizeof(*hdr));
+ hdr->flags = cpu_to_le16(hdr_flags);
+ hdr->len = cpu_to_le16(len - sizeof(*hdr));
+ hdr->type = cpu_to_le16(type);
+ hdr->tries = hdr->rts_tries = 0;
+
+ if (unlikely(p54_assign_address(dev, skb, hdr, len))) {
+ kfree_skb(skb);
+ return NULL;
+ }
+ return skb;
}
int p54_read_eeprom(struct ieee80211_hw *dev)
{
struct p54_common *priv = dev->priv;
- struct p54_control_hdr *hdr = NULL;
+ struct p54_hdr *hdr = NULL;
struct p54_eeprom_lm86 *eeprom_hdr;
- size_t eeprom_size = 0x2020, offset = 0, blocksize;
+ struct sk_buff *skb;
+ size_t eeprom_size = 0x2020, offset = 0, blocksize, maxblocksize;
int ret = -ENOMEM;
void *eeprom = NULL;
- hdr = (struct p54_control_hdr *)kzalloc(sizeof(*hdr) +
- sizeof(*eeprom_hdr) + EEPROM_READBACK_LEN, GFP_KERNEL);
- if (!hdr)
- goto free;
+ maxblocksize = EEPROM_READBACK_LEN;
+ if (priv->fw_var >= 0x509)
+ maxblocksize -= 0xc;
+ else
+ maxblocksize -= 0x4;
+ skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL, sizeof(*hdr) +
+ sizeof(*eeprom_hdr) + maxblocksize,
+ P54_CONTROL_TYPE_EEPROM_READBACK, GFP_KERNEL);
+ if (!skb)
+ goto free;
priv->eeprom = kzalloc(EEPROM_READBACK_LEN, GFP_KERNEL);
if (!priv->eeprom)
goto free;
-
eeprom = kzalloc(eeprom_size, GFP_KERNEL);
if (!eeprom)
goto free;
- hdr->magic1 = cpu_to_le16(0x8000);
- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_EEPROM_READBACK);
- hdr->retry1 = hdr->retry2 = 0;
- eeprom_hdr = (struct p54_eeprom_lm86 *) hdr->data;
+ eeprom_hdr = (struct p54_eeprom_lm86 *) skb_put(skb,
+ sizeof(*eeprom_hdr) + maxblocksize);
while (eeprom_size) {
- blocksize = min(eeprom_size, (size_t)EEPROM_READBACK_LEN);
- hdr->len = cpu_to_le16(blocksize + sizeof(*eeprom_hdr));
- eeprom_hdr->offset = cpu_to_le16(offset);
- eeprom_hdr->len = cpu_to_le16(blocksize);
- p54_assign_address(dev, NULL, hdr, le16_to_cpu(hdr->len) +
- sizeof(*hdr));
- priv->tx(dev, hdr, le16_to_cpu(hdr->len) + sizeof(*hdr), 0);
+ blocksize = min(eeprom_size, maxblocksize);
+ if (priv->fw_var < 0x509) {
+ eeprom_hdr->v1.offset = cpu_to_le16(offset);
+ eeprom_hdr->v1.len = cpu_to_le16(blocksize);
+ } else {
+ eeprom_hdr->v2.offset = cpu_to_le32(offset);
+ eeprom_hdr->v2.len = cpu_to_le16(blocksize);
+ eeprom_hdr->v2.magic2 = 0xf;
+ memcpy(eeprom_hdr->v2.magic, (const char *)"LOCK", 4);
+ }
+ priv->tx(dev, skb);
if (!wait_for_completion_interruptible_timeout(&priv->eeprom_comp, HZ)) {
printk(KERN_ERR "%s: device does not respond!\n",
@@ -790,166 +1106,422 @@ int p54_read_eeprom(struct ieee80211_hw *dev)
free:
kfree(priv->eeprom);
priv->eeprom = NULL;
- kfree(hdr);
+ p54_free_skb(dev, skb);
kfree(eeprom);
return ret;
}
EXPORT_SYMBOL_GPL(p54_read_eeprom);
+static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta,
+ bool set)
+{
+ struct p54_common *priv = dev->priv;
+ struct sk_buff *skb;
+ struct p54_tim *tim;
+
+ skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET,
+ sizeof(struct p54_hdr) + sizeof(*tim),
+ P54_CONTROL_TYPE_TIM, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ tim = (struct p54_tim *) skb_put(skb, sizeof(*tim));
+ tim->count = 1;
+ tim->entry[0] = cpu_to_le16(set ? (sta->aid | 0x8000) : sta->aid);
+ priv->tx(dev, skb);
+ return 0;
+}
+
+static int p54_sta_unlock(struct ieee80211_hw *dev, u8 *addr)
+{
+ struct p54_common *priv = dev->priv;
+ struct sk_buff *skb;
+ struct p54_sta_unlock *sta;
+
+ skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET,
+ sizeof(struct p54_hdr) + sizeof(*sta),
+ P54_CONTROL_TYPE_PSM_STA_UNLOCK, GFP_ATOMIC);
+ if (!skb)
+ return -ENOMEM;
+
+ sta = (struct p54_sta_unlock *)skb_put(skb, sizeof(*sta));
+ memcpy(sta->addr, addr, ETH_ALEN);
+ priv->tx(dev, skb);
+ return 0;
+}
+
+static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif,
+ enum sta_notify_cmd notify_cmd,
+ struct ieee80211_sta *sta)
+{
+ switch (notify_cmd) {
+ case STA_NOTIFY_ADD:
+ case STA_NOTIFY_REMOVE:
+ /*
+ * Notify the firmware that we don't want or we don't
+ * need to buffer frames for this station anymore.
+ */
+
+ p54_sta_unlock(dev, sta->addr);
+ break;
+ case STA_NOTIFY_AWAKE:
+ /* update the firmware's filter table */
+ p54_sta_unlock(dev, sta->addr);
+ break;
+ default:
+ break;
+ }
+}
+
+static int p54_tx_cancel(struct ieee80211_hw *dev, struct sk_buff *entry)
+{
+ struct p54_common *priv = dev->priv;
+ struct sk_buff *skb;
+ struct p54_hdr *hdr;
+ struct p54_txcancel *cancel;
+
+ skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET,
+ sizeof(struct p54_hdr) + sizeof(*cancel),
+ P54_CONTROL_TYPE_TXCANCEL, GFP_ATOMIC);
+ if (!skb)
+ return -ENOMEM;
+
+ hdr = (void *)entry->data;
+ cancel = (struct p54_txcancel *)skb_put(skb, sizeof(*cancel));
+ cancel->req_id = hdr->req_id;
+ priv->tx(dev, skb);
+ return 0;
+}
+
+static int p54_tx_fill(struct ieee80211_hw *dev, struct sk_buff *skb,
+ struct ieee80211_tx_info *info, u8 *queue, size_t *extra_len,
+ u16 *flags, u16 *aid)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct p54_common *priv = dev->priv;
+ int ret = 0;
+
+ if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) {
+ if (ieee80211_is_beacon(hdr->frame_control)) {
+ *aid = 0;
+ *queue = 0;
+ *extra_len = IEEE80211_MAX_TIM_LEN;
+ *flags = P54_HDR_FLAG_DATA_OUT_TIMESTAMP;
+ return 0;
+ } else if (ieee80211_is_probe_resp(hdr->frame_control)) {
+ *aid = 0;
+ *queue = 2;
+ *flags = P54_HDR_FLAG_DATA_OUT_TIMESTAMP |
+ P54_HDR_FLAG_DATA_OUT_NOCANCEL;
+ return 0;
+ } else {
+ *queue = 2;
+ ret = 0;
+ }
+ } else {
+ *queue += 4;
+ ret = 1;
+ }
+
+ switch (priv->mode) {
+ case NL80211_IFTYPE_STATION:
+ *aid = 1;
+ break;
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_MESH_POINT:
+ if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
+ *aid = 0;
+ *queue = 3;
+ return 0;
+ }
+ if (info->control.sta)
+ *aid = info->control.sta->aid;
+ else
+ *flags |= P54_HDR_FLAG_DATA_OUT_NOCANCEL;
+ }
+ return ret;
+}
+
+static u8 p54_convert_algo(enum ieee80211_key_alg alg)
+{
+ switch (alg) {
+ case ALG_WEP:
+ return P54_CRYPTO_WEP;
+ case ALG_TKIP:
+ return P54_CRYPTO_TKIPMICHAEL;
+ case ALG_CCMP:
+ return P54_CRYPTO_AESCCMP;
+ default:
+ return 0;
+ }
+}
+
static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_tx_queue_stats *current_queue;
+ struct ieee80211_tx_queue_stats *current_queue = NULL;
struct p54_common *priv = dev->priv;
- struct p54_control_hdr *hdr;
- struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
- struct p54_tx_control_allocdata *txhdr;
- size_t padding, len;
- u8 rate;
+ struct p54_hdr *hdr;
+ struct p54_tx_data *txhdr;
+ size_t padding, len, tim_len = 0;
+ int i, j, ridx, ret;
+ u16 hdr_flags = 0, aid = 0;
+ u8 rate, queue, crypt_offset = 0;
u8 cts_rate = 0x20;
+ u8 rc_flags;
+ u8 calculated_tries[4];
+ u8 nrates = 0, nremaining = 8;
- current_queue = &priv->tx_stats[skb_get_queue_mapping(skb) + 4];
- if (unlikely(current_queue->len > current_queue->limit))
+ queue = skb_get_queue_mapping(skb);
+
+ ret = p54_tx_fill(dev, skb, info, &queue, &tim_len, &hdr_flags, &aid);
+ current_queue = &priv->tx_stats[queue];
+ if (unlikely((current_queue->len > current_queue->limit) && ret))
return NETDEV_TX_BUSY;
current_queue->len++;
current_queue->count++;
- if (current_queue->len == current_queue->limit)
+ if ((current_queue->len == current_queue->limit) && ret)
ieee80211_stop_queue(dev, skb_get_queue_mapping(skb));
padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3;
len = skb->len;
- txhdr = (struct p54_tx_control_allocdata *)
- skb_push(skb, sizeof(*txhdr) + padding);
- hdr = (struct p54_control_hdr *) skb_push(skb, sizeof(*hdr));
+ if (info->control.hw_key) {
+ crypt_offset = ieee80211_get_hdrlen_from_skb(skb);
+ if (info->control.hw_key->alg == ALG_TKIP) {
+ u8 *iv = (u8 *)(skb->data + crypt_offset);
+ /*
+ * The firmware excepts that the IV has to have
+ * this special format
+ */
+ iv[1] = iv[0];
+ iv[0] = iv[2];
+ iv[2] = 0;
+ }
+ }
+
+ txhdr = (struct p54_tx_data *) skb_push(skb, sizeof(*txhdr) + padding);
+ hdr = (struct p54_hdr *) skb_push(skb, sizeof(*hdr));
if (padding)
- hdr->magic1 = cpu_to_le16(0x4010);
- else
- hdr->magic1 = cpu_to_le16(0x0010);
- hdr->len = cpu_to_le16(len);
- hdr->type = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? 0 : cpu_to_le16(1);
- hdr->retry1 = hdr->retry2 = info->control.retry_limit;
-
- /* TODO: add support for alternate retry TX rates */
- rate = ieee80211_get_tx_rate(dev, info)->hw_value;
- if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) {
- rate |= 0x10;
- cts_rate |= 0x10;
+ hdr_flags |= P54_HDR_FLAG_DATA_ALIGN;
+ hdr->type = cpu_to_le16(aid);
+ hdr->rts_tries = info->control.rates[0].count;
+
+ /*
+ * we register the rates in perfect order, and
+ * RTS/CTS won't happen on 5 GHz
+ */
+ cts_rate = info->control.rts_cts_rate_idx;
+
+ memset(&txhdr->rateset, 0, sizeof(txhdr->rateset));
+
+ /* see how many rates got used */
+ for (i = 0; i < 4; i++) {
+ if (info->control.rates[i].idx < 0)
+ break;
+ nrates++;
+ }
+
+ /* limit tries to 8/nrates per rate */
+ for (i = 0; i < nrates; i++) {
+ /*
+ * The magic expression here is equivalent to 8/nrates for
+ * all values that matter, but avoids division and jumps.
+ * Note that nrates can only take the values 1 through 4.
+ */
+ calculated_tries[i] = min_t(int, ((15 >> nrates) | 1) + 1,
+ info->control.rates[i].count);
+ nremaining -= calculated_tries[i];
}
- if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
- rate |= 0x40;
- cts_rate |= ieee80211_get_rts_cts_rate(dev, info)->hw_value;
- } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
- rate |= 0x20;
- cts_rate |= ieee80211_get_rts_cts_rate(dev, info)->hw_value;
+
+ /* if there are tries left, distribute from back to front */
+ for (i = nrates - 1; nremaining > 0 && i >= 0; i--) {
+ int tmp = info->control.rates[i].count - calculated_tries[i];
+
+ if (tmp <= 0)
+ continue;
+ /* RC requested more tries at this rate */
+
+ tmp = min_t(int, tmp, nremaining);
+ calculated_tries[i] += tmp;
+ nremaining -= tmp;
+ }
+
+ ridx = 0;
+ for (i = 0; i < nrates && ridx < 8; i++) {
+ /* we register the rates in perfect order */
+ rate = info->control.rates[i].idx;
+ if (info->band == IEEE80211_BAND_5GHZ)
+ rate += 4;
+
+ /* store the count we actually calculated for TX status */
+ info->control.rates[i].count = calculated_tries[i];
+
+ rc_flags = info->control.rates[i].flags;
+ if (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) {
+ rate |= 0x10;
+ cts_rate |= 0x10;
+ }
+ if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS)
+ rate |= 0x40;
+ else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
+ rate |= 0x20;
+ for (j = 0; j < calculated_tries[i] && ridx < 8; j++) {
+ txhdr->rateset[ridx] = rate;
+ ridx++;
+ }
+ }
+
+ if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
+ hdr_flags |= P54_HDR_FLAG_DATA_OUT_SEQNR;
+
+ /* TODO: enable bursting */
+ hdr->flags = cpu_to_le16(hdr_flags);
+ hdr->tries = ridx;
+ txhdr->rts_rate_idx = 0;
+ if (info->control.hw_key) {
+ crypt_offset += info->control.hw_key->iv_len;
+ txhdr->key_type = p54_convert_algo(info->control.hw_key->alg);
+ txhdr->key_len = min((u8)16, info->control.hw_key->keylen);
+ memcpy(txhdr->key, info->control.hw_key->key, txhdr->key_len);
+ if (info->control.hw_key->alg == ALG_TKIP) {
+ if (unlikely(skb_tailroom(skb) < 12))
+ goto err;
+ /* reserve space for the MIC key */
+ len += 8;
+ memcpy(skb_put(skb, 8), &(info->control.hw_key->key
+ [NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY]), 8);
+ }
+ /* reserve some space for ICV */
+ len += info->control.hw_key->icv_len;
+ } else {
+ txhdr->key_type = 0;
+ txhdr->key_len = 0;
}
- memset(txhdr->rateset, rate, 8);
- txhdr->key_type = 0;
- txhdr->key_len = 0;
- txhdr->hw_queue = skb_get_queue_mapping(skb) + 4;
+ txhdr->crypt_offset = crypt_offset;
+ txhdr->hw_queue = queue;
+ if (current_queue)
+ txhdr->backlog = current_queue->len;
+ else
+ txhdr->backlog = 0;
+ memset(txhdr->durations, 0, sizeof(txhdr->durations));
txhdr->tx_antenna = (info->antenna_sel_tx == 0) ?
2 : info->antenna_sel_tx - 1;
txhdr->output_power = priv->output_power;
- txhdr->cts_rate = (info->flags & IEEE80211_TX_CTL_NO_ACK) ?
- 0 : cts_rate;
+ txhdr->cts_rate = cts_rate;
if (padding)
txhdr->align[0] = padding;
- /* FIXME: The sequence that follows is needed for this driver to
- * work with mac80211 since "mac80211: fix TX sequence numbers".
- * As with the temporary code in rt2x00, changes will be needed
- * to get proper sequence numbers on beacons. In addition, this
- * patch places the sequence number in the hardware state, which
- * limits us to a single virtual state.
- */
- if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
- if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
- priv->seqno += 0x10;
- ieee80211hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
- ieee80211hdr->seq_ctrl |= cpu_to_le16(priv->seqno);
- }
+ hdr->len = cpu_to_le16(len);
/* modifies skb->cb and with it info, so must be last! */
- p54_assign_address(dev, skb, hdr, skb->len);
+ if (unlikely(p54_assign_address(dev, skb, hdr, skb->len + tim_len)))
+ goto err;
+ priv->tx(dev, skb);
+
+ queue_delayed_work(dev->workqueue, &priv->work,
+ msecs_to_jiffies(P54_TX_FRAME_LIFETIME));
- priv->tx(dev, hdr, skb->len, 0);
return 0;
+
+ err:
+ skb_pull(skb, sizeof(*hdr) + sizeof(*txhdr) + padding);
+ if (current_queue) {
+ current_queue->len--;
+ current_queue->count--;
+ }
+ return NETDEV_TX_BUSY;
}
-static int p54_set_filter(struct ieee80211_hw *dev, u16 filter_type,
- const u8 *bssid)
+static int p54_setup_mac(struct ieee80211_hw *dev)
{
struct p54_common *priv = dev->priv;
- struct p54_control_hdr *hdr;
- struct p54_tx_control_filter *filter;
- size_t data_len;
+ struct sk_buff *skb;
+ struct p54_setup_mac *setup;
+ u16 mode;
- hdr = kzalloc(sizeof(*hdr) + sizeof(*filter) +
- priv->tx_hdr_len, GFP_ATOMIC);
- if (!hdr)
+ skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*setup) +
+ sizeof(struct p54_hdr), P54_CONTROL_TYPE_SETUP,
+ GFP_ATOMIC);
+ if (!skb)
return -ENOMEM;
- hdr = (void *)hdr + priv->tx_hdr_len;
-
- filter = (struct p54_tx_control_filter *) hdr->data;
- hdr->magic1 = cpu_to_le16(0x8001);
- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_FILTER_SET);
-
- priv->filter_type = filter->filter_type = cpu_to_le16(filter_type);
- memcpy(filter->mac_addr, priv->mac_addr, ETH_ALEN);
- if (!bssid)
- memset(filter->bssid, ~0, ETH_ALEN);
- else
- memcpy(filter->bssid, bssid, ETH_ALEN);
-
- filter->rx_antenna = priv->rx_antenna;
+ setup = (struct p54_setup_mac *) skb_put(skb, sizeof(*setup));
+ if (dev->conf.radio_enabled) {
+ switch (priv->mode) {
+ case NL80211_IFTYPE_STATION:
+ mode = P54_FILTER_TYPE_STATION;
+ break;
+ case NL80211_IFTYPE_AP:
+ mode = P54_FILTER_TYPE_AP;
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_MESH_POINT:
+ mode = P54_FILTER_TYPE_IBSS;
+ break;
+ default:
+ mode = P54_FILTER_TYPE_NONE;
+ break;
+ }
+ if (priv->filter_flags & FIF_PROMISC_IN_BSS)
+ mode |= P54_FILTER_TYPE_TRANSPARENT;
+ } else
+ mode = P54_FILTER_TYPE_RX_DISABLED;
+ setup->mac_mode = cpu_to_le16(mode);
+ memcpy(setup->mac_addr, priv->mac_addr, ETH_ALEN);
+ memcpy(setup->bssid, priv->bssid, ETH_ALEN);
+ setup->rx_antenna = 2; /* automatic */
+ setup->rx_align = 0;
if (priv->fw_var < 0x500) {
- data_len = P54_TX_CONTROL_FILTER_V1_LEN;
- filter->v1.basic_rate_mask = cpu_to_le32(0x15F);
- filter->v1.rx_addr = cpu_to_le32(priv->rx_end);
- filter->v1.max_rx = cpu_to_le16(priv->rx_mtu);
- filter->v1.rxhw = cpu_to_le16(priv->rxhw);
- filter->v1.wakeup_timer = cpu_to_le16(500);
+ setup->v1.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
+ memset(setup->v1.rts_rates, 0, 8);
+ setup->v1.rx_addr = cpu_to_le32(priv->rx_end);
+ setup->v1.max_rx = cpu_to_le16(priv->rx_mtu);
+ setup->v1.rxhw = cpu_to_le16(priv->rxhw);
+ setup->v1.wakeup_timer = cpu_to_le16(priv->wakeup_timer);
+ setup->v1.unalloc0 = cpu_to_le16(0);
} else {
- data_len = P54_TX_CONTROL_FILTER_V2_LEN;
- filter->v2.rx_addr = cpu_to_le32(priv->rx_end);
- filter->v2.max_rx = cpu_to_le16(priv->rx_mtu);
- filter->v2.rxhw = cpu_to_le16(priv->rxhw);
- filter->v2.timer = cpu_to_le16(1000);
+ setup->v2.rx_addr = cpu_to_le32(priv->rx_end);
+ setup->v2.max_rx = cpu_to_le16(priv->rx_mtu);
+ setup->v2.rxhw = cpu_to_le16(priv->rxhw);
+ setup->v2.timer = cpu_to_le16(priv->wakeup_timer);
+ setup->v2.truncate = cpu_to_le16(48896);
+ setup->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
+ setup->v2.sbss_offset = 0;
+ setup->v2.mcast_window = 0;
+ setup->v2.rx_rssi_threshold = 0;
+ setup->v2.rx_ed_threshold = 0;
+ setup->v2.ref_clock = cpu_to_le32(644245094);
+ setup->v2.lpf_bandwidth = cpu_to_le16(65535);
+ setup->v2.osc_start_delay = cpu_to_le16(65535);
}
-
- hdr->len = cpu_to_le16(data_len);
- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + data_len);
- priv->tx(dev, hdr, sizeof(*hdr) + data_len, 1);
+ priv->tx(dev, skb);
return 0;
}
-static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
+static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell)
{
struct p54_common *priv = dev->priv;
- struct p54_control_hdr *hdr;
- struct p54_tx_control_channel *chan;
+ struct sk_buff *skb;
+ struct p54_scan *chan;
unsigned int i;
- size_t data_len;
void *entry;
+ __le16 freq = cpu_to_le16(dev->conf.channel->center_freq);
+ int band = dev->conf.channel->band;
- hdr = kzalloc(sizeof(*hdr) + sizeof(*chan) +
- priv->tx_hdr_len, GFP_KERNEL);
- if (!hdr)
+ skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*chan) +
+ sizeof(struct p54_hdr), P54_CONTROL_TYPE_SCAN,
+ GFP_ATOMIC);
+ if (!skb)
return -ENOMEM;
- hdr = (void *)hdr + priv->tx_hdr_len;
-
- chan = (struct p54_tx_control_channel *) hdr->data;
-
- hdr->magic1 = cpu_to_le16(0x8001);
-
- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_CHANNEL_CHANGE);
-
- chan->flags = cpu_to_le16(0x1);
- chan->dwell = cpu_to_le16(0x0);
+ chan = (struct p54_scan *) skb_put(skb, sizeof(*chan));
+ memset(chan->padding1, 0, sizeof(chan->padding1));
+ chan->mode = cpu_to_le16(mode);
+ chan->dwell = cpu_to_le16(dwell);
for (i = 0; i < priv->iq_autocal_len; i++) {
if (priv->iq_autocal[i].freq != freq)
@@ -990,61 +1562,50 @@ static int p54_set_freq(struct ieee80211_hw *dev, __le16 freq)
}
entry += sizeof(__le16);
- chan->pa_points_per_curve =
- min(priv->curve_data->points_per_channel, (u8) 8);
-
- memcpy(chan->curve_data, entry, sizeof(*chan->curve_data) *
- chan->pa_points_per_curve);
+ chan->pa_points_per_curve = 8;
+ memset(chan->curve_data, 0, sizeof(*chan->curve_data));
+ memcpy(chan->curve_data, entry,
+ sizeof(struct p54_pa_curve_data_sample) *
+ min((u8)8, priv->curve_data->points_per_channel));
break;
}
if (priv->fw_var < 0x500) {
- data_len = P54_TX_CONTROL_CHANNEL_V1_LEN;
- chan->v1.rssical_mul = cpu_to_le16(130);
- chan->v1.rssical_add = cpu_to_le16(0xfe70);
+ chan->v1_rssi.mul = cpu_to_le16(priv->rssical_db[band].mul);
+ chan->v1_rssi.add = cpu_to_le16(priv->rssical_db[band].add);
} else {
- data_len = P54_TX_CONTROL_CHANNEL_V2_LEN;
- chan->v2.rssical_mul = cpu_to_le16(130);
- chan->v2.rssical_add = cpu_to_le16(0xfe70);
- chan->v2.basic_rate_mask = cpu_to_le32(0x15f);
+ chan->v2.rssi.mul = cpu_to_le16(priv->rssical_db[band].mul);
+ chan->v2.rssi.add = cpu_to_le16(priv->rssical_db[band].add);
+ chan->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask);
+ memset(chan->v2.rts_rates, 0, 8);
}
-
- hdr->len = cpu_to_le16(data_len);
- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + data_len);
- priv->tx(dev, hdr, sizeof(*hdr) + data_len, 1);
+ priv->tx(dev, skb);
return 0;
err:
printk(KERN_ERR "%s: frequency change failed\n", wiphy_name(dev->wiphy));
- kfree(hdr);
+ kfree_skb(skb);
return -EINVAL;
}
static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act)
{
struct p54_common *priv = dev->priv;
- struct p54_control_hdr *hdr;
- struct p54_tx_control_led *led;
+ struct sk_buff *skb;
+ struct p54_led *led;
- hdr = kzalloc(sizeof(*hdr) + sizeof(*led) +
- priv->tx_hdr_len, GFP_KERNEL);
- if (!hdr)
+ skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*led) +
+ sizeof(struct p54_hdr), P54_CONTROL_TYPE_LED,
+ GFP_ATOMIC);
+ if (!skb)
return -ENOMEM;
- hdr = (void *)hdr + priv->tx_hdr_len;
- hdr->magic1 = cpu_to_le16(0x8001);
- hdr->len = cpu_to_le16(sizeof(*led));
- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_LED);
- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*led));
-
- led = (struct p54_tx_control_led *) hdr->data;
+ led = (struct p54_led *)skb_put(skb, sizeof(*led));
led->mode = cpu_to_le16(mode);
led->led_permanent = cpu_to_le16(link);
led->led_temporary = cpu_to_le16(act);
led->duration = cpu_to_le16(1000);
-
- priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*led), 1);
-
+ priv->tx(dev, skb);
return 0;
}
@@ -1056,88 +1617,144 @@ do { \
queue.txop = cpu_to_le16(_txop); \
} while(0)
-static void p54_init_vdcf(struct ieee80211_hw *dev)
+static int p54_set_edcf(struct ieee80211_hw *dev)
{
struct p54_common *priv = dev->priv;
- struct p54_control_hdr *hdr;
- struct p54_tx_control_vdcf *vdcf;
-
- /* all USB V1 adapters need a extra headroom */
- hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len;
- hdr->magic1 = cpu_to_le16(0x8001);
- hdr->len = cpu_to_le16(sizeof(*vdcf));
- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_DCFINIT);
- hdr->req_id = cpu_to_le32(priv->rx_start);
-
- vdcf = (struct p54_tx_control_vdcf *) hdr->data;
-
- P54_SET_QUEUE(vdcf->queue[0], 0x0002, 0x0003, 0x0007, 47);
- P54_SET_QUEUE(vdcf->queue[1], 0x0002, 0x0007, 0x000f, 94);
- P54_SET_QUEUE(vdcf->queue[2], 0x0003, 0x000f, 0x03ff, 0);
- P54_SET_QUEUE(vdcf->queue[3], 0x0007, 0x000f, 0x03ff, 0);
+ struct sk_buff *skb;
+ struct p54_edcf *edcf;
+
+ skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*edcf) +
+ sizeof(struct p54_hdr), P54_CONTROL_TYPE_DCFINIT,
+ GFP_ATOMIC);
+ if (!skb)
+ return -ENOMEM;
+
+ edcf = (struct p54_edcf *)skb_put(skb, sizeof(*edcf));
+ if (priv->use_short_slot) {
+ edcf->slottime = 9;
+ edcf->sifs = 0x10;
+ edcf->eofpad = 0x00;
+ } else {
+ edcf->slottime = 20;
+ edcf->sifs = 0x0a;
+ edcf->eofpad = 0x06;
+ }
+ /* (see prism54/isl_oid.h for further details) */
+ edcf->frameburst = cpu_to_le16(0);
+ edcf->round_trip_delay = cpu_to_le16(0);
+ edcf->flags = 0;
+ memset(edcf->mapping, 0, sizeof(edcf->mapping));
+ memcpy(edcf->queue, priv->qos_params, sizeof(edcf->queue));
+ priv->tx(dev, skb);
+ return 0;
}
-static void p54_set_vdcf(struct ieee80211_hw *dev)
+static int p54_beacon_tim(struct sk_buff *skb)
{
- struct p54_common *priv = dev->priv;
- struct p54_control_hdr *hdr;
- struct p54_tx_control_vdcf *vdcf;
+ /*
+ * the good excuse for this mess is ... the firmware.
+ * The dummy TIM MUST be at the end of the beacon frame,
+ * because it'll be overwritten!
+ */
- hdr = (void *)priv->cached_vdcf + priv->tx_hdr_len;
+ struct ieee80211_mgmt *mgmt = (void *)skb->data;
+ u8 *pos, *end;
- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*vdcf));
+ if (skb->len <= sizeof(mgmt))
+ return -EINVAL;
- vdcf = (struct p54_tx_control_vdcf *) hdr->data;
+ pos = (u8 *)mgmt->u.beacon.variable;
+ end = skb->data + skb->len;
+ while (pos < end) {
+ if (pos + 2 + pos[1] > end)
+ return -EINVAL;
- if (dev->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
- vdcf->slottime = 9;
- vdcf->magic1 = 0x10;
- vdcf->magic2 = 0x00;
- } else {
- vdcf->slottime = 20;
- vdcf->magic1 = 0x0a;
- vdcf->magic2 = 0x06;
- }
+ if (pos[0] == WLAN_EID_TIM) {
+ u8 dtim_len = pos[1];
+ u8 dtim_period = pos[3];
+ u8 *next = pos + 2 + dtim_len;
- /* (see prism54/isl_oid.h for further details) */
- vdcf->frameburst = cpu_to_le16(0);
+ if (dtim_len < 3)
+ return -EINVAL;
+
+ memmove(pos, next, end - next);
- priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*vdcf), 0);
+ if (dtim_len > 3)
+ skb_trim(skb, skb->len - (dtim_len - 3));
+
+ pos = end - (dtim_len + 2);
+
+ /* add the dummy at the end */
+ pos[0] = WLAN_EID_TIM;
+ pos[1] = 3;
+ pos[2] = 0;
+ pos[3] = dtim_period;
+ pos[4] = 0;
+ return 0;
+ }
+ pos += 2 + pos[1];
+ }
+ return 0;
}
-static int p54_start(struct ieee80211_hw *dev)
+static int p54_beacon_update(struct ieee80211_hw *dev,
+ struct ieee80211_vif *vif)
{
struct p54_common *priv = dev->priv;
- int err;
-
- if (!priv->cached_vdcf) {
- priv->cached_vdcf = kzalloc(sizeof(struct p54_tx_control_vdcf)+
- priv->tx_hdr_len + sizeof(struct p54_control_hdr),
- GFP_KERNEL);
+ struct sk_buff *beacon;
+ int ret;
- if (!priv->cached_vdcf)
- return -ENOMEM;
+ if (priv->cached_beacon) {
+ p54_tx_cancel(dev, priv->cached_beacon);
+ /* wait for the last beacon the be freed */
+ msleep(10);
}
- if (!priv->cached_stats) {
- priv->cached_stats = kzalloc(sizeof(struct p54_statistics) +
- priv->tx_hdr_len + sizeof(struct p54_control_hdr),
- GFP_KERNEL);
+ beacon = ieee80211_beacon_get(dev, vif);
+ if (!beacon)
+ return -ENOMEM;
+ ret = p54_beacon_tim(beacon);
+ if (ret)
+ return ret;
+ ret = p54_tx(dev, beacon);
+ if (ret)
+ return ret;
+ priv->cached_beacon = beacon;
+ priv->tsf_high32 = 0;
+ priv->tsf_low32 = 0;
- if (!priv->cached_stats) {
- kfree(priv->cached_vdcf);
- priv->cached_vdcf = NULL;
- return -ENOMEM;
- }
- }
+ return 0;
+}
+static int p54_start(struct ieee80211_hw *dev)
+{
+ struct p54_common *priv = dev->priv;
+ int err;
+
+ mutex_lock(&priv->conf_mutex);
err = priv->open(dev);
- if (!err)
- priv->mode = NL80211_IFTYPE_MONITOR;
+ if (err)
+ goto out;
+ P54_SET_QUEUE(priv->qos_params[0], 0x0002, 0x0003, 0x0007, 47);
+ P54_SET_QUEUE(priv->qos_params[1], 0x0002, 0x0007, 0x000f, 94);
+ P54_SET_QUEUE(priv->qos_params[2], 0x0003, 0x000f, 0x03ff, 0);
+ P54_SET_QUEUE(priv->qos_params[3], 0x0007, 0x000f, 0x03ff, 0);
+ err = p54_set_edcf(dev);
+ if (err)
+ goto out;
+
+ memset(priv->bssid, ~0, ETH_ALEN);
+ priv->mode = NL80211_IFTYPE_MONITOR;
+ err = p54_setup_mac(dev);
+ if (err) {
+ priv->mode = NL80211_IFTYPE_UNSPECIFIED;
+ goto out;
+ }
- p54_init_vdcf(dev);
+ queue_delayed_work(dev->workqueue, &priv->work, 0);
- mod_timer(&priv->stats_timer, jiffies + HZ);
+out:
+ mutex_unlock(&priv->conf_mutex);
return err;
}
@@ -1146,12 +1763,18 @@ static void p54_stop(struct ieee80211_hw *dev)
struct p54_common *priv = dev->priv;
struct sk_buff *skb;
- del_timer(&priv->stats_timer);
+ mutex_lock(&priv->conf_mutex);
+ priv->mode = NL80211_IFTYPE_UNSPECIFIED;
+ cancel_delayed_work_sync(&priv->work);
+ if (priv->cached_beacon)
+ p54_tx_cancel(dev, priv->cached_beacon);
+
+ priv->stop(dev);
while ((skb = skb_dequeue(&priv->tx_queue)))
kfree_skb(skb);
- priv->stop(dev);
+ priv->cached_beacon = NULL;
priv->tsf_high32 = priv->tsf_low32 = 0;
- priv->mode = NL80211_IFTYPE_UNSPECIFIED;
+ mutex_unlock(&priv->conf_mutex);
}
static int p54_add_interface(struct ieee80211_hw *dev,
@@ -1159,32 +1782,28 @@ static int p54_add_interface(struct ieee80211_hw *dev,
{
struct p54_common *priv = dev->priv;
- if (priv->mode != NL80211_IFTYPE_MONITOR)
+ mutex_lock(&priv->conf_mutex);
+ if (priv->mode != NL80211_IFTYPE_MONITOR) {
+ mutex_unlock(&priv->conf_mutex);
return -EOPNOTSUPP;
+ }
switch (conf->type) {
case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_MESH_POINT:
priv->mode = conf->type;
break;
default:
+ mutex_unlock(&priv->conf_mutex);
return -EOPNOTSUPP;
}
memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN);
-
- p54_set_filter(dev, 0, NULL);
-
- switch (conf->type) {
- case NL80211_IFTYPE_STATION:
- p54_set_filter(dev, 1, NULL);
- break;
- default:
- BUG(); /* impossible */
- break;
- }
-
+ p54_setup_mac(dev);
p54_set_leds(dev, 1, 0, 0);
-
+ mutex_unlock(&priv->conf_mutex);
return 0;
}
@@ -1192,22 +1811,38 @@ static void p54_remove_interface(struct ieee80211_hw *dev,
struct ieee80211_if_init_conf *conf)
{
struct p54_common *priv = dev->priv;
+
+ mutex_lock(&priv->conf_mutex);
+ if (priv->cached_beacon)
+ p54_tx_cancel(dev, priv->cached_beacon);
priv->mode = NL80211_IFTYPE_MONITOR;
memset(priv->mac_addr, 0, ETH_ALEN);
- p54_set_filter(dev, 0, NULL);
+ memset(priv->bssid, 0, ETH_ALEN);
+ p54_setup_mac(dev);
+ mutex_unlock(&priv->conf_mutex);
}
-static int p54_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+static int p54_config(struct ieee80211_hw *dev, u32 changed)
{
int ret;
struct p54_common *priv = dev->priv;
+ struct ieee80211_conf *conf = &dev->conf;
mutex_lock(&priv->conf_mutex);
- priv->rx_antenna = (conf->antenna_sel_rx == 0) ?
- 2 : conf->antenna_sel_tx - 1;
- priv->output_power = conf->power_level << 2;
- ret = p54_set_freq(dev, cpu_to_le16(conf->channel->center_freq));
- p54_set_vdcf(dev);
+ if (changed & IEEE80211_CONF_CHANGE_POWER)
+ priv->output_power = conf->power_level << 2;
+ if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED) {
+ ret = p54_setup_mac(dev);
+ if (ret)
+ goto out;
+ }
+ if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+ ret = p54_scan(dev, P54_SCAN_EXIT, 0);
+ if (ret)
+ goto out;
+ }
+
+out:
mutex_unlock(&priv->conf_mutex);
return ret;
}
@@ -1217,13 +1852,36 @@ static int p54_config_interface(struct ieee80211_hw *dev,
struct ieee80211_if_conf *conf)
{
struct p54_common *priv = dev->priv;
+ int ret = 0;
mutex_lock(&priv->conf_mutex);
- p54_set_filter(dev, 0, conf->bssid);
- p54_set_leds(dev, 1, !is_multicast_ether_addr(conf->bssid), 0);
- memcpy(priv->bssid, conf->bssid, ETH_ALEN);
+ if (conf->changed & IEEE80211_IFCC_BSSID) {
+ memcpy(priv->bssid, conf->bssid, ETH_ALEN);
+ ret = p54_setup_mac(dev);
+ if (ret)
+ goto out;
+ }
+
+ if (conf->changed & IEEE80211_IFCC_BEACON) {
+ ret = p54_scan(dev, P54_SCAN_EXIT, 0);
+ if (ret)
+ goto out;
+ ret = p54_setup_mac(dev);
+ if (ret)
+ goto out;
+ ret = p54_beacon_update(dev, vif);
+ if (ret)
+ goto out;
+ ret = p54_set_edcf(dev);
+ if (ret)
+ goto out;
+ }
+
+ ret = p54_set_leds(dev, 1, !is_multicast_ether_addr(priv->bssid), 0);
+
+out:
mutex_unlock(&priv->conf_mutex);
- return 0;
+ return ret;
}
static void p54_configure_filter(struct ieee80211_hw *dev,
@@ -1233,94 +1891,78 @@ static void p54_configure_filter(struct ieee80211_hw *dev,
{
struct p54_common *priv = dev->priv;
- *total_flags &= FIF_BCN_PRBRESP_PROMISC |
- FIF_PROMISC_IN_BSS |
- FIF_FCSFAIL;
+ *total_flags &= FIF_PROMISC_IN_BSS |
+ (*total_flags & FIF_PROMISC_IN_BSS) ?
+ FIF_FCSFAIL : 0;
priv->filter_flags = *total_flags;
- if (changed_flags & FIF_BCN_PRBRESP_PROMISC) {
- if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
- p54_set_filter(dev, le16_to_cpu(priv->filter_type),
- NULL);
- else
- p54_set_filter(dev, le16_to_cpu(priv->filter_type),
- priv->bssid);
- }
-
- if (changed_flags & FIF_PROMISC_IN_BSS) {
- if (*total_flags & FIF_PROMISC_IN_BSS)
- p54_set_filter(dev, le16_to_cpu(priv->filter_type) |
- 0x8, NULL);
- else
- p54_set_filter(dev, le16_to_cpu(priv->filter_type) &
- ~0x8, priv->bssid);
- }
+ if (changed_flags & FIF_PROMISC_IN_BSS)
+ p54_setup_mac(dev);
}
static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct p54_common *priv = dev->priv;
- struct p54_tx_control_vdcf *vdcf;
-
- vdcf = (struct p54_tx_control_vdcf *)(((struct p54_control_hdr *)
- ((void *)priv->cached_vdcf + priv->tx_hdr_len))->data);
+ int ret;
+ mutex_lock(&priv->conf_mutex);
if ((params) && !(queue > 4)) {
- P54_SET_QUEUE(vdcf->queue[queue], params->aifs,
+ P54_SET_QUEUE(priv->qos_params[queue], params->aifs,
params->cw_min, params->cw_max, params->txop);
+ ret = p54_set_edcf(dev);
} else
- return -EINVAL;
-
- p54_set_vdcf(dev);
-
- return 0;
+ ret = -EINVAL;
+ mutex_unlock(&priv->conf_mutex);
+ return ret;
}
static int p54_init_xbow_synth(struct ieee80211_hw *dev)
{
struct p54_common *priv = dev->priv;
- struct p54_control_hdr *hdr;
- struct p54_tx_control_xbow_synth *xbow;
+ struct sk_buff *skb;
+ struct p54_xbow_synth *xbow;
- hdr = kzalloc(sizeof(*hdr) + sizeof(*xbow) +
- priv->tx_hdr_len, GFP_KERNEL);
- if (!hdr)
+ skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*xbow) +
+ sizeof(struct p54_hdr),
+ P54_CONTROL_TYPE_XBOW_SYNTH_CFG,
+ GFP_KERNEL);
+ if (!skb)
return -ENOMEM;
- hdr = (void *)hdr + priv->tx_hdr_len;
- hdr->magic1 = cpu_to_le16(0x8001);
- hdr->len = cpu_to_le16(sizeof(*xbow));
- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_XBOW_SYNTH_CFG);
- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*xbow));
-
- xbow = (struct p54_tx_control_xbow_synth *) hdr->data;
+ xbow = (struct p54_xbow_synth *)skb_put(skb, sizeof(*xbow));
xbow->magic1 = cpu_to_le16(0x1);
xbow->magic2 = cpu_to_le16(0x2);
xbow->freq = cpu_to_le16(5390);
-
- priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*xbow), 1);
-
+ memset(xbow->padding, 0, sizeof(xbow->padding));
+ priv->tx(dev, skb);
return 0;
}
-static void p54_statistics_timer(unsigned long data)
+static void p54_work(struct work_struct *work)
{
- struct ieee80211_hw *dev = (struct ieee80211_hw *) data;
- struct p54_common *priv = dev->priv;
- struct p54_control_hdr *hdr;
- struct p54_statistics *stats;
+ struct p54_common *priv = container_of(work, struct p54_common,
+ work.work);
+ struct ieee80211_hw *dev = priv->hw;
+ struct sk_buff *skb;
- BUG_ON(!priv->cached_stats);
+ if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED))
+ return ;
- hdr = (void *)priv->cached_stats + priv->tx_hdr_len;
- hdr->magic1 = cpu_to_le16(0x8000);
- hdr->len = cpu_to_le16(sizeof(*stats));
- hdr->type = cpu_to_le16(P54_CONTROL_TYPE_STAT_READBACK);
- p54_assign_address(dev, NULL, hdr, sizeof(*hdr) + sizeof(*stats));
+ /*
+ * TODO: walk through tx_queue and do the following tasks
+ * 1. initiate bursts.
+ * 2. cancel stuck frames / reset the device if necessary.
+ */
+
+ skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL, sizeof(struct p54_hdr) +
+ sizeof(struct p54_statistics),
+ P54_CONTROL_TYPE_STAT_READBACK, GFP_KERNEL);
+ if (!skb)
+ return ;
- priv->tx(dev, hdr, sizeof(*hdr) + sizeof(*stats), 0);
+ priv->tx(dev, skb);
}
static int p54_get_stats(struct ieee80211_hw *dev,
@@ -1328,17 +1970,7 @@ static int p54_get_stats(struct ieee80211_hw *dev,
{
struct p54_common *priv = dev->priv;
- del_timer(&priv->stats_timer);
- p54_statistics_timer((unsigned long)dev);
-
- if (!wait_for_completion_interruptible_timeout(&priv->stats_comp, HZ)) {
- printk(KERN_ERR "%s: device does not respond!\n",
- wiphy_name(dev->wiphy));
- return -EBUSY;
- }
-
memcpy(stats, &priv->stats, sizeof(*stats));
-
return 0;
}
@@ -1352,14 +1984,133 @@ static int p54_get_tx_stats(struct ieee80211_hw *dev,
return 0;
}
+static void p54_bss_info_changed(struct ieee80211_hw *dev,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info,
+ u32 changed)
+{
+ struct p54_common *priv = dev->priv;
+
+ if (changed & BSS_CHANGED_ERP_SLOT) {
+ priv->use_short_slot = info->use_short_slot;
+ p54_set_edcf(dev);
+ }
+ if (changed & BSS_CHANGED_BASIC_RATES) {
+ if (dev->conf.channel->band == IEEE80211_BAND_5GHZ)
+ priv->basic_rate_mask = (info->basic_rates << 4);
+ else
+ priv->basic_rate_mask = info->basic_rates;
+ p54_setup_mac(dev);
+ if (priv->fw_var >= 0x500)
+ p54_scan(dev, P54_SCAN_EXIT, 0);
+ }
+ if (changed & BSS_CHANGED_ASSOC) {
+ if (info->assoc) {
+ priv->aid = info->aid;
+ priv->wakeup_timer = info->beacon_int *
+ info->dtim_period * 5;
+ p54_setup_mac(dev);
+ }
+ }
+
+}
+
+static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
+ const u8 *local_address, const u8 *address,
+ struct ieee80211_key_conf *key)
+{
+ struct p54_common *priv = dev->priv;
+ struct sk_buff *skb;
+ struct p54_keycache *rxkey;
+ u8 algo = 0;
+
+ if (modparam_nohwcrypt)
+ return -EOPNOTSUPP;
+
+ if (cmd == DISABLE_KEY)
+ algo = 0;
+ else {
+ switch (key->alg) {
+ case ALG_TKIP:
+ if (!(priv->privacy_caps & (BR_DESC_PRIV_CAP_MICHAEL |
+ BR_DESC_PRIV_CAP_TKIP)))
+ return -EOPNOTSUPP;
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ algo = P54_CRYPTO_TKIPMICHAEL;
+ break;
+ case ALG_WEP:
+ if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP))
+ return -EOPNOTSUPP;
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ algo = P54_CRYPTO_WEP;
+ break;
+ case ALG_CCMP:
+ if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP))
+ return -EOPNOTSUPP;
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ algo = P54_CRYPTO_AESCCMP;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ if (key->keyidx > priv->rx_keycache_size) {
+ /*
+ * The device supports the choosen algorithm, but the firmware
+ * does not provide enough key slots to store all of them.
+ * So, incoming frames have to be decoded by the mac80211 stack,
+ * but we can still offload encryption for outgoing frames.
+ */
+
+ return 0;
+ }
+
+ mutex_lock(&priv->conf_mutex);
+ skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*rxkey) +
+ sizeof(struct p54_hdr), P54_CONTROL_TYPE_RX_KEYCACHE,
+ GFP_ATOMIC);
+ if (!skb) {
+ mutex_unlock(&priv->conf_mutex);
+ return -ENOMEM;
+ }
+
+ /* TODO: some devices have 4 more free slots for rx keys */
+ rxkey = (struct p54_keycache *)skb_put(skb, sizeof(*rxkey));
+ rxkey->entry = key->keyidx;
+ rxkey->key_id = key->keyidx;
+ rxkey->key_type = algo;
+ if (address)
+ memcpy(rxkey->mac, address, ETH_ALEN);
+ else
+ memset(rxkey->mac, ~0, ETH_ALEN);
+ if (key->alg != ALG_TKIP) {
+ rxkey->key_len = min((u8)16, key->keylen);
+ memcpy(rxkey->key, key->key, rxkey->key_len);
+ } else {
+ rxkey->key_len = 24;
+ memcpy(rxkey->key, key->key, 16);
+ memcpy(&(rxkey->key[16]), &(key->key
+ [NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]), 8);
+ }
+
+ priv->tx(dev, skb);
+ mutex_unlock(&priv->conf_mutex);
+ return 0;
+}
+
static const struct ieee80211_ops p54_ops = {
.tx = p54_tx,
.start = p54_start,
.stop = p54_stop,
.add_interface = p54_add_interface,
.remove_interface = p54_remove_interface,
+ .set_tim = p54_set_tim,
+ .sta_notify = p54_sta_notify,
+ .set_key = p54_set_key,
.config = p54_config,
.config_interface = p54_config_interface,
+ .bss_info_changed = p54_bss_info_changed,
.configure_filter = p54_configure_filter,
.conf_tx = p54_conf_tx,
.get_stats = p54_get_stats,
@@ -1376,32 +2127,43 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len)
return NULL;
priv = dev->priv;
+ priv->hw = dev;
priv->mode = NL80211_IFTYPE_UNSPECIFIED;
+ priv->basic_rate_mask = 0x15f;
skb_queue_head_init(&priv->tx_queue);
- dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | /* not sure */
- IEEE80211_HW_RX_INCLUDES_FCS |
+ dev->flags = IEEE80211_HW_RX_INCLUDES_FCS |
IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM;
- dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+ dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_ADHOC) |
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_MESH_POINT);
dev->channel_change_time = 1000; /* TODO: find actual value */
-
- priv->tx_stats[0].limit = 1;
- priv->tx_stats[1].limit = 1;
- priv->tx_stats[2].limit = 1;
- priv->tx_stats[3].limit = 1;
- priv->tx_stats[4].limit = 5;
+ priv->tx_stats[0].limit = 1; /* Beacon queue */
+ priv->tx_stats[1].limit = 1; /* Probe queue for HW scan */
+ priv->tx_stats[2].limit = 3; /* queue for MLMEs */
+ priv->tx_stats[3].limit = 3; /* Broadcast / MC queue */
+ priv->tx_stats[4].limit = 5; /* Data */
dev->queues = 1;
priv->noise = -94;
- dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 +
- sizeof(struct p54_tx_control_allocdata);
+ /*
+ * We support at most 8 tries no matter which rate they're at,
+ * we cannot support max_rates * max_rate_tries as we set it
+ * here, but setting it correctly to 4/2 or so would limit us
+ * artificially if the RC algorithm wants just two rates, so
+ * let's say 4/7, we'll redistribute it at TX time, see the
+ * comments there.
+ */
+ dev->max_rates = 4;
+ dev->max_rate_tries = 7;
+ dev->extra_tx_headroom = sizeof(struct p54_hdr) + 4 +
+ sizeof(struct p54_tx_data);
mutex_init(&priv->conf_mutex);
init_completion(&priv->eeprom_comp);
- init_completion(&priv->stats_comp);
- setup_timer(&priv->stats_timer, p54_statistics_timer,
- (unsigned long)dev);
+ INIT_DELAYED_WORK(&priv->work, p54_work);
return dev;
}
@@ -1410,11 +2172,9 @@ EXPORT_SYMBOL_GPL(p54_init_common);
void p54_free_common(struct ieee80211_hw *dev)
{
struct p54_common *priv = dev->priv;
- kfree(priv->cached_stats);
kfree(priv->iq_autocal);
kfree(priv->output_limit);
kfree(priv->curve_data);
- kfree(priv->cached_vdcf);
}
EXPORT_SYMBOL_GPL(p54_free_common);
diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h
index 2fa994cfcfed..f5729de83fe1 100644
--- a/drivers/net/wireless/p54/p54common.h
+++ b/drivers/net/wireless/p54/p54common.h
@@ -7,8 +7,12 @@
* Copyright (c) 2006, Michael Wu <flamingice@sourmilk.net>
* Copyright (c) 2007, Christian Lamparter <chunkeey@web.de>
*
- * Based on the islsm (softmac prism54) driver, which is:
- * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
+ * Based on:
+ * - the islsm (softmac prism54) driver, which is:
+ * Copyright 2004-2006 Jean-Baptiste Note <jbnote@gmail.com>, et al.
+ *
+ * - LMAC API interface header file for STLC4560 (lmac_longbow.h)
+ * Copyright (C) 2007 Conexant Systems, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -19,9 +23,24 @@ struct bootrec {
__le32 code;
__le32 len;
u32 data[10];
- __le16 rx_mtu;
} __attribute__((packed));
+#define PDR_SYNTH_FRONTEND_MASK 0x0007
+#define PDR_SYNTH_IQ_CAL_MASK 0x0018
+#define PDR_SYNTH_IQ_CAL_PA_DETECTOR 0x0000
+#define PDR_SYNTH_IQ_CAL_DISABLED 0x0008
+#define PDR_SYNTH_IQ_CAL_ZIF 0x0010
+#define PDR_SYNTH_FAA_SWITCH_MASK 0x0020
+#define PDR_SYNTH_FAA_SWITCH_ENABLED 0x0001
+#define PDR_SYNTH_24_GHZ_MASK 0x0040
+#define PDR_SYNTH_24_GHZ_DISABLED 0x0040
+#define PDR_SYNTH_5_GHZ_MASK 0x0080
+#define PDR_SYNTH_5_GHZ_DISABLED 0x0080
+#define PDR_SYNTH_RX_DIV_MASK 0x0100
+#define PDR_SYNTH_RX_DIV_SUPPORTED 0x0100
+#define PDR_SYNTH_TX_DIV_MASK 0x0200
+#define PDR_SYNTH_TX_DIV_SUPPORTED 0x0200
+
struct bootrec_exp_if {
__le16 role;
__le16 if_id;
@@ -30,6 +49,13 @@ struct bootrec_exp_if {
__le16 top_compat;
} __attribute__((packed));
+#define BR_DESC_PRIV_CAP_WEP BIT(0)
+#define BR_DESC_PRIV_CAP_TKIP BIT(1)
+#define BR_DESC_PRIV_CAP_MICHAEL BIT(2)
+#define BR_DESC_PRIV_CAP_CCX_CP BIT(3)
+#define BR_DESC_PRIV_CAP_CCX_MIC BIT(4)
+#define BR_DESC_PRIV_CAP_AESCCMP BIT(5)
+
struct bootrec_desc {
__le16 modes;
__le16 flags;
@@ -37,8 +63,15 @@ struct bootrec_desc {
__le32 rx_end;
u8 headroom;
u8 tailroom;
- u8 unimportant[6];
+ u8 tx_queues;
+ u8 tx_depth;
+ u8 privacy_caps;
+ u8 rx_keycache_size;
+ u8 time_size;
+ u8 padding;
u8 rates[16];
+ u8 padding2[4];
+ __le16 rx_mtu;
} __attribute__((packed));
#define BR_CODE_MIN 0x80000000
@@ -51,6 +84,31 @@ struct bootrec_desc {
#define BR_CODE_END_OF_BRA 0xFF0000FF
#define LEGACY_BR_CODE_END_OF_BRA 0xFFFFFFFF
+#define P54_HDR_FLAG_DATA_ALIGN BIT(14)
+#define P54_HDR_FLAG_DATA_OUT_PROMISC BIT(0)
+#define P54_HDR_FLAG_DATA_OUT_TIMESTAMP BIT(1)
+#define P54_HDR_FLAG_DATA_OUT_SEQNR BIT(2)
+#define P54_HDR_FLAG_DATA_OUT_BIT3 BIT(3)
+#define P54_HDR_FLAG_DATA_OUT_BURST BIT(4)
+#define P54_HDR_FLAG_DATA_OUT_NOCANCEL BIT(5)
+#define P54_HDR_FLAG_DATA_OUT_CLEARTIM BIT(6)
+#define P54_HDR_FLAG_DATA_OUT_HITCHHIKE BIT(7)
+#define P54_HDR_FLAG_DATA_OUT_COMPRESS BIT(8)
+#define P54_HDR_FLAG_DATA_OUT_CONCAT BIT(9)
+#define P54_HDR_FLAG_DATA_OUT_PCS_ACCEPT BIT(10)
+#define P54_HDR_FLAG_DATA_OUT_WAITEOSP BIT(11)
+
+#define P54_HDR_FLAG_DATA_IN_FCS_GOOD BIT(0)
+#define P54_HDR_FLAG_DATA_IN_MATCH_MAC BIT(1)
+#define P54_HDR_FLAG_DATA_IN_MCBC BIT(2)
+#define P54_HDR_FLAG_DATA_IN_BEACON BIT(3)
+#define P54_HDR_FLAG_DATA_IN_MATCH_BSS BIT(4)
+#define P54_HDR_FLAG_DATA_IN_BCAST_BSS BIT(5)
+#define P54_HDR_FLAG_DATA_IN_DATA BIT(6)
+#define P54_HDR_FLAG_DATA_IN_TRUNCATED BIT(7)
+#define P54_HDR_FLAG_DATA_IN_BIT8 BIT(8)
+#define P54_HDR_FLAG_DATA_IN_TRANSPARENT BIT(9)
+
/* PDA defines are Copyright (C) 2005 Nokia Corporation (taken from islsm_pda.h) */
struct pda_entry {
@@ -117,6 +175,11 @@ struct pda_pa_curve_data {
u8 data[0];
} __attribute__ ((packed));
+struct pda_rssi_cal_entry {
+ __le16 mul;
+ __le16 add;
+} __attribute__ ((packed));
+
/*
* this defines the PDR codes used to build PDAs as defined in document
* number 553155. The current implementation mirrors version 1.1 of the
@@ -165,6 +228,19 @@ struct pda_pa_curve_data {
#define PDR_BASEBAND_REGISTERS 0x8000
#define PDR_PER_CHANNEL_BASEBAND_REGISTERS 0x8001
+/* PDR definitions for default country & country list */
+#define PDR_COUNTRY_CERT_CODE 0x80
+#define PDR_COUNTRY_CERT_CODE_REAL 0x00
+#define PDR_COUNTRY_CERT_CODE_PSEUDO 0x80
+#define PDR_COUNTRY_CERT_BAND 0x40
+#define PDR_COUNTRY_CERT_BAND_2GHZ 0x00
+#define PDR_COUNTRY_CERT_BAND_5GHZ 0x40
+#define PDR_COUNTRY_CERT_IODOOR 0x30
+#define PDR_COUNTRY_CERT_IODOOR_BOTH 0x00
+#define PDR_COUNTRY_CERT_IODOOR_INDOOR 0x20
+#define PDR_COUNTRY_CERT_IODOOR_OUTDOOR 0x30
+#define PDR_COUNTRY_CERT_INDEX 0x0F
+
/* stored in skb->cb */
struct memrecord {
u32 start_addr;
@@ -172,41 +248,108 @@ struct memrecord {
};
struct p54_eeprom_lm86 {
- __le16 offset;
- __le16 len;
- u8 data[0];
+ union {
+ struct {
+ __le16 offset;
+ __le16 len;
+ u8 data[0];
+ } v1;
+ struct {
+ __le32 offset;
+ __le16 len;
+ u8 magic2;
+ u8 pad;
+ u8 magic[4];
+ u8 data[0];
+ } v2;
+ } __attribute__ ((packed));
} __attribute__ ((packed));
-struct p54_rx_hdr {
- __le16 magic;
+enum p54_rx_decrypt_status {
+ P54_DECRYPT_NONE = 0,
+ P54_DECRYPT_OK,
+ P54_DECRYPT_NOKEY,
+ P54_DECRYPT_NOMICHAEL,
+ P54_DECRYPT_NOCKIPMIC,
+ P54_DECRYPT_FAIL_WEP,
+ P54_DECRYPT_FAIL_TKIP,
+ P54_DECRYPT_FAIL_MICHAEL,
+ P54_DECRYPT_FAIL_CKIPKP,
+ P54_DECRYPT_FAIL_CKIPMIC,
+ P54_DECRYPT_FAIL_AESCCMP
+};
+
+struct p54_rx_data {
+ __le16 flags;
__le16 len;
__le16 freq;
u8 antenna;
u8 rate;
u8 rssi;
u8 quality;
- u16 unknown2;
+ u8 decrypt_status;
+ u8 rssi_raw;
__le32 tsf32;
__le32 unalloc0;
u8 align[0];
} __attribute__ ((packed));
-struct p54_frame_sent_hdr {
+enum p54_trap_type {
+ P54_TRAP_SCAN = 0,
+ P54_TRAP_TIMER,
+ P54_TRAP_BEACON_TX,
+ P54_TRAP_FAA_RADIO_ON,
+ P54_TRAP_FAA_RADIO_OFF,
+ P54_TRAP_RADAR,
+ P54_TRAP_NO_BEACON,
+ P54_TRAP_TBTT,
+ P54_TRAP_SCO_ENTER,
+ P54_TRAP_SCO_EXIT
+};
+
+struct p54_trap {
+ __le16 event;
+ __le16 frequency;
+} __attribute__ ((packed));
+
+enum p54_frame_sent_status {
+ P54_TX_OK = 0,
+ P54_TX_FAILED,
+ P54_TX_PSM,
+ P54_TX_PSM_CANCELLED = 4
+};
+
+struct p54_frame_sent {
u8 status;
- u8 retries;
- __le16 ack_rssi;
+ u8 tries;
+ u8 ack_rssi;
+ u8 quality;
__le16 seq;
- u16 rate;
+ u8 antenna;
+ u8 padding;
} __attribute__ ((packed));
-struct p54_tx_control_allocdata {
+enum p54_tx_data_crypt {
+ P54_CRYPTO_NONE = 0,
+ P54_CRYPTO_WEP,
+ P54_CRYPTO_TKIP,
+ P54_CRYPTO_TKIPMICHAEL,
+ P54_CRYPTO_CCX_WEPMIC,
+ P54_CRYPTO_CCX_KPMIC,
+ P54_CRYPTO_CCX_KP,
+ P54_CRYPTO_AESCCMP
+};
+
+struct p54_tx_data {
u8 rateset[8];
- u8 unalloc0[2];
+ u8 rts_rate_idx;
+ u8 crypt_offset;
u8 key_type;
u8 key_len;
u8 key[16];
u8 hw_queue;
- u8 unalloc1[9];
+ u8 backlog;
+ __le16 durations[4];
u8 tx_antenna;
u8 output_power;
u8 cts_rate;
@@ -214,8 +357,23 @@ struct p54_tx_control_allocdata {
u8 align[0];
} __attribute__ ((packed));
-struct p54_tx_control_filter {
- __le16 filter_type;
+/* unit is ms */
+#define P54_TX_FRAME_LIFETIME 2000
+#define P54_TX_TIMEOUT 4000
+#define P54_STATISTICS_UPDATE 5000
+
+#define P54_FILTER_TYPE_NONE 0
+#define P54_FILTER_TYPE_STATION BIT(0)
+#define P54_FILTER_TYPE_IBSS BIT(1)
+#define P54_FILTER_TYPE_AP BIT(2)
+#define P54_FILTER_TYPE_TRANSPARENT BIT(3)
+#define P54_FILTER_TYPE_PROMISCUOUS BIT(4)
+#define P54_FILTER_TYPE_HIBERNATE BIT(5)
+#define P54_FILTER_TYPE_NOACK BIT(6)
+#define P54_FILTER_TYPE_RX_DISABLED BIT(7)
+
+struct p54_setup_mac {
+ __le16 mac_mode;
u8 mac_addr[ETH_ALEN];
u8 bssid[ETH_ALEN];
u8 rx_antenna;
@@ -235,17 +393,29 @@ struct p54_tx_control_filter {
__le16 max_rx;
__le16 rxhw;
__le16 timer;
- __le16 unalloc0;
- __le32 unalloc1;
+ __le16 truncate;
+ __le32 basic_rate_mask;
+ u8 sbss_offset;
+ u8 mcast_window;
+ u8 rx_rssi_threshold;
+ u8 rx_ed_threshold;
+ __le32 ref_clock;
+ __le16 lpf_bandwidth;
+ __le16 osc_start_delay;
} v2 __attribute__ ((packed));
} __attribute__ ((packed));
} __attribute__ ((packed));
-#define P54_TX_CONTROL_FILTER_V1_LEN (sizeof(struct p54_tx_control_filter))
-#define P54_TX_CONTROL_FILTER_V2_LEN (sizeof(struct p54_tx_control_filter)-8)
+#define P54_SETUP_V1_LEN 40
+#define P54_SETUP_V2_LEN (sizeof(struct p54_setup_mac))
-struct p54_tx_control_channel {
- __le16 flags;
+#define P54_SCAN_EXIT BIT(0)
+#define P54_SCAN_TRAP BIT(1)
+#define P54_SCAN_ACTIVE BIT(2)
+#define P54_SCAN_FILTER BIT(3)
+
+struct p54_scan {
+ __le16 mode;
__le16 dwell;
u8 padding1[20];
struct pda_iq_autocal_entry iq_autocal;
@@ -261,45 +431,35 @@ struct p54_tx_control_channel {
u8 dup_16qam;
u8 dup_64qam;
union {
- struct {
- __le16 rssical_mul;
- __le16 rssical_add;
- } v1 __attribute__ ((packed));
+ struct pda_rssi_cal_entry v1_rssi;
struct {
__le32 basic_rate_mask;
- u8 rts_rates[8];
- __le16 rssical_mul;
- __le16 rssical_add;
+ u8 rts_rates[8];
+ struct pda_rssi_cal_entry rssi;
} v2 __attribute__ ((packed));
} __attribute__ ((packed));
} __attribute__ ((packed));
-#define P54_TX_CONTROL_CHANNEL_V1_LEN (sizeof(struct p54_tx_control_channel)-12)
-#define P54_TX_CONTROL_CHANNEL_V2_LEN (sizeof(struct p54_tx_control_channel))
+#define P54_SCAN_V1_LEN 0x70
+#define P54_SCAN_V2_LEN 0x7c
-struct p54_tx_control_led {
+struct p54_led {
__le16 mode;
__le16 led_temporary;
__le16 led_permanent;
__le16 duration;
} __attribute__ ((packed));
-struct p54_tx_vdcf_queues {
- __le16 aifs;
- __le16 cwmin;
- __le16 cwmax;
- __le16 txop;
-} __attribute__ ((packed));
-
-struct p54_tx_control_vdcf {
- u8 padding;
+struct p54_edcf {
+ u8 flags;
u8 slottime;
- u8 magic1;
- u8 magic2;
- struct p54_tx_vdcf_queues queue[8];
- u8 pad2[4];
+ u8 sifs;
+ u8 eofpad;
+ struct p54_edcf_queue_param queue[8];
+ u8 mapping[4];
__le16 frameburst;
+ __le16 round_trip_delay;
} __attribute__ ((packed));
struct p54_statistics {
@@ -312,14 +472,103 @@ struct p54_statistics {
__le32 tsf32;
__le32 airtime;
__le32 noise;
- __le32 unkn[10]; /* CCE / CCA / RADAR */
+ __le32 sample_noise[8];
+ __le32 sample_cca;
+ __le32 sample_tx;
} __attribute__ ((packed));
-struct p54_tx_control_xbow_synth {
+struct p54_xbow_synth {
__le16 magic1;
__le16 magic2;
__le16 freq;
u32 padding[5];
} __attribute__ ((packed));
+struct p54_timer {
+ __le32 interval;
+} __attribute__ ((packed));
+
+struct p54_keycache {
+ u8 entry;
+ u8 key_id;
+ u8 mac[ETH_ALEN];
+ u8 padding[2];
+ u8 key_type;
+ u8 key_len;
+ u8 key[24];
+} __attribute__ ((packed));
+
+struct p54_burst {
+ u8 flags;
+ u8 queue;
+ u8 backlog;
+ u8 pad;
+ __le16 durations[32];
+} __attribute__ ((packed));
+
+struct p54_psm_interval {
+ __le16 interval;
+ __le16 periods;
+} __attribute__ ((packed));
+
+#define P54_PSM BIT(0)
+#define P54_PSM_DTIM BIT(1)
+#define P54_PSM_MCBC BIT(2)
+#define P54_PSM_CHECKSUM BIT(3)
+#define P54_PSM_SKIP_MORE_DATA BIT(4)
+#define P54_PSM_BEACON_TIMEOUT BIT(5)
+#define P54_PSM_HFOSLEEP BIT(6)
+#define P54_PSM_AUTOSWITCH_SLEEP BIT(7)
+#define P54_PSM_LPIT BIT(8)
+#define P54_PSM_BF_UCAST_SKIP BIT(9)
+#define P54_PSM_BF_MCAST_SKIP BIT(10)
+
+struct p54_psm {
+ __le16 mode;
+ __le16 aid;
+ struct p54_psm_interval intervals[4];
+ u8 beacon_rssi_skip_max;
+ u8 rssi_delta_threshold;
+ u8 nr;
+ u8 exclude[1];
+} __attribute__ ((packed));
+
+#define MC_FILTER_ADDRESS_NUM 4
+
+struct p54_group_address_table {
+ __le16 filter_enable;
+ __le16 num_address;
+ u8 mac_list[MC_FILTER_ADDRESS_NUM][ETH_ALEN];
+} __attribute__ ((packed));
+
+struct p54_txcancel {
+ __le32 req_id;
+} __attribute__ ((packed));
+
+struct p54_sta_unlock {
+ u8 addr[ETH_ALEN];
+ u16 padding;
+} __attribute__ ((packed));
+
+#define P54_TIM_CLEAR BIT(15)
+struct p54_tim {
+ u8 count;
+ u8 padding[3];
+ __le16 entry[8];
+} __attribute__ ((packed));
+
+struct p54_cce_quiet {
+ __le32 period;
+} __attribute__ ((packed));
+
+struct p54_bt_balancer {
+ __le16 prio_thresh;
+ __le16 acl_thresh;
+} __attribute__ ((packed));
+
+struct p54_arp_table {
+ __le16 filter_enable;
+ u8 ipv4_addr[4];
+} __attribute__ ((packed));
+
#endif /* P54COMMON_H */
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c
index 88b3cad8b65e..aa367a0ddc49 100644
--- a/drivers/net/wireless/p54/p54pci.c
+++ b/drivers/net/wireless/p54/p54pci.c
@@ -28,6 +28,7 @@ MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
MODULE_DESCRIPTION("Prism54 PCI wireless driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("prism54pci");
+MODULE_FIRMWARE("isl3886pci");
static struct pci_device_id p54p_table[] __devinitdata = {
/* Intersil PRISM Duette/Prism GT Wireless LAN adapter */
@@ -46,7 +47,6 @@ MODULE_DEVICE_TABLE(pci, p54p_table);
static int p54p_upload_firmware(struct ieee80211_hw *dev)
{
struct p54p_priv *priv = dev->priv;
- const struct firmware *fw_entry = NULL;
__le32 reg;
int err;
__le32 *data;
@@ -72,21 +72,15 @@ static int p54p_upload_firmware(struct ieee80211_hw *dev)
P54P_WRITE(ctrl_stat, reg);
wmb();
- err = request_firmware(&fw_entry, "isl3886", &priv->pdev->dev);
- if (err) {
- printk(KERN_ERR "%s (p54pci): cannot find firmware "
- "(isl3886)\n", pci_name(priv->pdev));
- return err;
- }
+ /* wait for the firmware to reset properly */
+ mdelay(10);
- err = p54_parse_firmware(dev, fw_entry);
- if (err) {
- release_firmware(fw_entry);
+ err = p54_parse_firmware(dev, priv->firmware);
+ if (err)
return err;
- }
- data = (__le32 *) fw_entry->data;
- remains = fw_entry->size;
+ data = (__le32 *) priv->firmware->data;
+ remains = priv->firmware->size;
device_addr = ISL38XX_DEV_FIRMWARE_ADDR;
while (remains) {
u32 i = 0;
@@ -104,8 +98,6 @@ static int p54p_upload_firmware(struct ieee80211_hw *dev)
P54P_READ(int_enable);
}
- release_firmware(fw_entry);
-
reg = P54P_READ(ctrl_stat);
reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN);
reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET);
@@ -235,7 +227,9 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index,
while (i != idx) {
desc = &ring[i];
- kfree(tx_buf[i]);
+ if (tx_buf[i])
+ if (FREE_AFTER_TX((struct sk_buff *) tx_buf[i]))
+ p54_free_skb(dev, tx_buf[i]);
tx_buf[i] = NULL;
pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr),
@@ -306,8 +300,7 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id)
return reg ? IRQ_HANDLED : IRQ_NONE;
}
-static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
- size_t len, int free_on_tx)
+static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
{
struct p54p_priv *priv = dev->priv;
struct p54p_ring_control *ring_control = priv->ring_control;
@@ -322,28 +315,21 @@ static void p54p_tx(struct ieee80211_hw *dev, struct p54_control_hdr *data,
idx = le32_to_cpu(ring_control->host_idx[1]);
i = idx % ARRAY_SIZE(ring_control->tx_data);
- mapping = pci_map_single(priv->pdev, data, len, PCI_DMA_TODEVICE);
+ priv->tx_buf_data[i] = skb;
+ mapping = pci_map_single(priv->pdev, skb->data, skb->len,
+ PCI_DMA_TODEVICE);
desc = &ring_control->tx_data[i];
desc->host_addr = cpu_to_le32(mapping);
- desc->device_addr = data->req_id;
- desc->len = cpu_to_le16(len);
+ desc->device_addr = ((struct p54_hdr *)skb->data)->req_id;
+ desc->len = cpu_to_le16(skb->len);
desc->flags = 0;
wmb();
ring_control->host_idx[1] = cpu_to_le32(idx + 1);
-
- if (free_on_tx)
- priv->tx_buf_data[i] = data;
-
spin_unlock_irqrestore(&priv->lock, flags);
P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE));
P54P_READ(dev_int);
-
- /* FIXME: unlikely to happen because the device usually runs out of
- memory before we fill the ring up, but we can make it impossible */
- if (idx - device_idx > ARRAY_SIZE(ring_control->tx_data) - 2)
- printk(KERN_INFO "%s: tx overflow.\n", wiphy_name(dev->wiphy));
}
static void p54p_stop(struct ieee80211_hw *dev)
@@ -393,7 +379,7 @@ static void p54p_stop(struct ieee80211_hw *dev)
le16_to_cpu(desc->len),
PCI_DMA_TODEVICE);
- kfree(priv->tx_buf_data[i]);
+ p54_free_skb(dev, priv->tx_buf_data[i]);
priv->tx_buf_data[i] = NULL;
}
@@ -405,7 +391,7 @@ static void p54p_stop(struct ieee80211_hw *dev)
le16_to_cpu(desc->len),
PCI_DMA_TODEVICE);
- kfree(priv->tx_buf_mgmt[i]);
+ p54_free_skb(dev, priv->tx_buf_mgmt[i]);
priv->tx_buf_mgmt[i] = NULL;
}
@@ -481,7 +467,6 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
struct ieee80211_hw *dev;
unsigned long mem_addr, mem_len;
int err;
- DECLARE_MAC_BUF(mac);
err = pci_enable_device(pdev);
if (err) {
@@ -495,15 +480,14 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
if (mem_len < sizeof(struct p54p_csr)) {
printk(KERN_ERR "%s (p54pci): Too short PCI resources\n",
pci_name(pdev));
- pci_disable_device(pdev);
- return err;
+ goto err_disable_dev;
}
err = pci_request_regions(pdev, "p54pci");
if (err) {
printk(KERN_ERR "%s (p54pci): Cannot obtain PCI resources\n",
pci_name(pdev));
- return err;
+ goto err_disable_dev;
}
if (pci_set_dma_mask(pdev, DMA_32BIT_MASK) ||
@@ -556,6 +540,17 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
spin_lock_init(&priv->lock);
tasklet_init(&priv->rx_tasklet, p54p_rx_tasklet, (unsigned long)dev);
+ err = request_firmware(&priv->firmware, "isl3886pci",
+ &priv->pdev->dev);
+ if (err) {
+ printk(KERN_ERR "%s (p54pci): cannot find firmware "
+ "(isl3886pci)\n", pci_name(priv->pdev));
+ err = request_firmware(&priv->firmware, "isl3886",
+ &priv->pdev->dev);
+ if (err)
+ goto err_free_common;
+ }
+
err = p54p_open(dev);
if (err)
goto err_free_common;
@@ -574,6 +569,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
return 0;
err_free_common:
+ release_firmware(priv->firmware);
p54_free_common(dev);
pci_free_consistent(pdev, sizeof(*priv->ring_control),
priv->ring_control, priv->ring_control_dma);
@@ -587,6 +583,7 @@ static int __devinit p54p_probe(struct pci_dev *pdev,
err_free_reg:
pci_release_regions(pdev);
+ err_disable_dev:
pci_disable_device(pdev);
return err;
}
@@ -601,6 +598,7 @@ static void __devexit p54p_remove(struct pci_dev *pdev)
ieee80211_unregister_hw(dev);
priv = dev->priv;
+ release_firmware(priv->firmware);
pci_free_consistent(pdev, sizeof(*priv->ring_control),
priv->ring_control, priv->ring_control_dma);
p54_free_common(dev);
diff --git a/drivers/net/wireless/p54/p54pci.h b/drivers/net/wireless/p54/p54pci.h
index 4a6778070afc..fbb683953fb2 100644
--- a/drivers/net/wireless/p54/p54pci.h
+++ b/drivers/net/wireless/p54/p54pci.h
@@ -93,7 +93,7 @@ struct p54p_priv {
struct pci_dev *pdev;
struct p54p_csr __iomem *map;
struct tasklet_struct rx_tasklet;
-
+ const struct firmware *firmware;
spinlock_t lock;
struct p54p_ring_control *ring_control;
dma_addr_t ring_control_dma;
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
index 75d749bccb0d..c44a200059d2 100644
--- a/drivers/net/wireless/p54/p54usb.c
+++ b/drivers/net/wireless/p54/p54usb.c
@@ -28,6 +28,8 @@ MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
MODULE_DESCRIPTION("Prism54 USB wireless driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("prism54usb");
+MODULE_FIRMWARE("isl3886usb");
+MODULE_FIRMWARE("isl3887usb");
static struct usb_device_id p54u_table[] __devinitdata = {
/* Version 1 devices (pci chip + net2280) */
@@ -84,13 +86,13 @@ static void p54u_rx_cb(struct urb *urb)
struct ieee80211_hw *dev = info->dev;
struct p54u_priv *priv = dev->priv;
+ skb_unlink(skb, &priv->rx_queue);
+
if (unlikely(urb->status)) {
- info->urb = NULL;
- usb_free_urb(urb);
+ dev_kfree_skb_irq(skb);
return;
}
- skb_unlink(skb, &priv->rx_queue);
skb_put(skb, urb->actual_length);
if (priv->hw_type == P54U_NET2280)
@@ -103,7 +105,6 @@ static void p54u_rx_cb(struct urb *urb)
if (p54_rx(dev, skb)) {
skb = dev_alloc_skb(priv->common.rx_mtu + 32);
if (unlikely(!skb)) {
- usb_free_urb(urb);
/* TODO check rx queue length and refill *somewhere* */
return;
}
@@ -113,7 +114,6 @@ static void p54u_rx_cb(struct urb *urb)
info->dev = dev;
urb->transfer_buffer = skb_tail_pointer(skb);
urb->context = skb;
- skb_queue_tail(&priv->rx_queue, skb);
} else {
if (priv->hw_type == P54U_NET2280)
skb_push(skb, priv->common.tx_hdr_len);
@@ -128,40 +128,56 @@ static void p54u_rx_cb(struct urb *urb)
WARN_ON(1);
urb->transfer_buffer = skb_tail_pointer(skb);
}
-
- skb_queue_tail(&priv->rx_queue, skb);
}
-
- usb_submit_urb(urb, GFP_ATOMIC);
+ skb_queue_tail(&priv->rx_queue, skb);
+ usb_anchor_urb(urb, &priv->submitted);
+ if (usb_submit_urb(urb, GFP_ATOMIC)) {
+ skb_unlink(skb, &priv->rx_queue);
+ usb_unanchor_urb(urb);
+ dev_kfree_skb_irq(skb);
+ }
}
static void p54u_tx_cb(struct urb *urb)
{
- usb_free_urb(urb);
+ struct sk_buff *skb = urb->context;
+ struct ieee80211_hw *dev = (struct ieee80211_hw *)
+ usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0));
+ struct p54u_priv *priv = dev->priv;
+
+ skb_pull(skb, priv->common.tx_hdr_len);
+ if (FREE_AFTER_TX(skb))
+ p54_free_skb(dev, skb);
}
-static void p54u_tx_free_cb(struct urb *urb)
+static void p54u_tx_dummy_cb(struct urb *urb) { }
+
+static void p54u_free_urbs(struct ieee80211_hw *dev)
{
- kfree(urb->transfer_buffer);
- usb_free_urb(urb);
+ struct p54u_priv *priv = dev->priv;
+ usb_kill_anchored_urbs(&priv->submitted);
}
static int p54u_init_urbs(struct ieee80211_hw *dev)
{
struct p54u_priv *priv = dev->priv;
- struct urb *entry;
+ struct urb *entry = NULL;
struct sk_buff *skb;
struct p54u_rx_info *info;
+ int ret = 0;
while (skb_queue_len(&priv->rx_queue) < 32) {
skb = __dev_alloc_skb(priv->common.rx_mtu + 32, GFP_KERNEL);
- if (!skb)
- break;
+ if (!skb) {
+ ret = -ENOMEM;
+ goto err;
+ }
entry = usb_alloc_urb(0, GFP_KERNEL);
if (!entry) {
- kfree_skb(skb);
- break;
+ ret = -ENOMEM;
+ goto err;
}
+
usb_fill_bulk_urb(entry, priv->udev,
usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA),
skb_tail_pointer(skb),
@@ -170,33 +186,32 @@ static int p54u_init_urbs(struct ieee80211_hw *dev)
info->urb = entry;
info->dev = dev;
skb_queue_tail(&priv->rx_queue, skb);
- usb_submit_urb(entry, GFP_KERNEL);
+
+ usb_anchor_urb(entry, &priv->submitted);
+ ret = usb_submit_urb(entry, GFP_KERNEL);
+ if (ret) {
+ skb_unlink(skb, &priv->rx_queue);
+ usb_unanchor_urb(entry);
+ goto err;
+ }
+ usb_free_urb(entry);
+ entry = NULL;
}
return 0;
-}
-
-static void p54u_free_urbs(struct ieee80211_hw *dev)
-{
- struct p54u_priv *priv = dev->priv;
- struct p54u_rx_info *info;
- struct sk_buff *skb;
- while ((skb = skb_dequeue(&priv->rx_queue))) {
- info = (struct p54u_rx_info *) skb->cb;
- if (!info->urb)
- continue;
-
- usb_kill_urb(info->urb);
- kfree_skb(skb);
- }
+ err:
+ usb_free_urb(entry);
+ kfree_skb(skb);
+ p54u_free_urbs(dev);
+ return ret;
}
-static void p54u_tx_3887(struct ieee80211_hw *dev, struct p54_control_hdr *data,
- size_t len, int free_on_tx)
+static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb)
{
struct p54u_priv *priv = dev->priv;
struct urb *addr_urb, *data_urb;
+ int err = 0;
addr_urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!addr_urb)
@@ -209,59 +224,85 @@ static void p54u_tx_3887(struct ieee80211_hw *dev, struct p54_control_hdr *data,
}
usb_fill_bulk_urb(addr_urb, priv->udev,
- usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), &data->req_id,
- sizeof(data->req_id), p54u_tx_cb, dev);
+ usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
+ &((struct p54_hdr *)skb->data)->req_id, 4,
+ p54u_tx_dummy_cb, dev);
usb_fill_bulk_urb(data_urb, priv->udev,
- usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), data, len,
- free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
+ usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
+ skb->data, skb->len, p54u_tx_cb, skb);
+
+ usb_anchor_urb(addr_urb, &priv->submitted);
+ err = usb_submit_urb(addr_urb, GFP_ATOMIC);
+ if (err) {
+ usb_unanchor_urb(addr_urb);
+ goto out;
+ }
- usb_submit_urb(addr_urb, GFP_ATOMIC);
- usb_submit_urb(data_urb, GFP_ATOMIC);
+ usb_anchor_urb(addr_urb, &priv->submitted);
+ err = usb_submit_urb(data_urb, GFP_ATOMIC);
+ if (err)
+ usb_unanchor_urb(data_urb);
+
+ out:
+ usb_free_urb(addr_urb);
+ usb_free_urb(data_urb);
+
+ if (err)
+ p54_free_skb(dev, skb);
}
-static __le32 p54u_lm87_chksum(const u32 *data, size_t length)
+static __le32 p54u_lm87_chksum(const __le32 *data, size_t length)
{
u32 chk = 0;
length >>= 2;
while (length--) {
- chk ^= *data++;
+ chk ^= le32_to_cpu(*data++);
chk = (chk >> 5) ^ (chk << 3);
}
return cpu_to_le32(chk);
}
-static void p54u_tx_lm87(struct ieee80211_hw *dev,
- struct p54_control_hdr *data,
- size_t len, int free_on_tx)
+static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb)
{
struct p54u_priv *priv = dev->priv;
struct urb *data_urb;
- struct lm87_tx_hdr *hdr = (void *)data - sizeof(*hdr);
+ struct lm87_tx_hdr *hdr;
+ __le32 checksum;
+ __le32 addr = ((struct p54_hdr *)skb->data)->req_id;
data_urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!data_urb)
return;
- hdr->chksum = p54u_lm87_chksum((u32 *)data, len);
- hdr->device_addr = data->req_id;
+ checksum = p54u_lm87_chksum((__le32 *)skb->data, skb->len);
+ hdr = (struct lm87_tx_hdr *)skb_push(skb, sizeof(*hdr));
+ hdr->chksum = checksum;
+ hdr->device_addr = addr;
usb_fill_bulk_urb(data_urb, priv->udev,
- usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr,
- len + sizeof(*hdr), free_on_tx ? p54u_tx_free_cb : p54u_tx_cb,
- dev);
-
- usb_submit_urb(data_urb, GFP_ATOMIC);
+ usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
+ skb->data, skb->len, p54u_tx_cb, skb);
+
+ usb_anchor_urb(data_urb, &priv->submitted);
+ if (usb_submit_urb(data_urb, GFP_ATOMIC)) {
+ usb_unanchor_urb(data_urb);
+ skb_pull(skb, sizeof(*hdr));
+ p54_free_skb(dev, skb);
+ }
+ usb_free_urb(data_urb);
}
-static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *data,
- size_t len, int free_on_tx)
+static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb)
{
struct p54u_priv *priv = dev->priv;
struct urb *int_urb, *data_urb;
struct net2280_tx_hdr *hdr;
struct net2280_reg_write *reg;
+ int err = 0;
+ __le32 addr = ((struct p54_hdr *) skb->data)->req_id;
+ __le16 len = cpu_to_le16(skb->len);
reg = kmalloc(sizeof(*reg), GFP_ATOMIC);
if (!reg)
@@ -284,21 +325,47 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct p54_control_hdr *da
reg->addr = cpu_to_le32(P54U_DEV_BASE);
reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA);
- len += sizeof(*data);
- hdr = (void *)data - sizeof(*hdr);
+ hdr = (void *)skb_push(skb, sizeof(*hdr));
memset(hdr, 0, sizeof(*hdr));
- hdr->device_addr = data->req_id;
- hdr->len = cpu_to_le16(len);
+ hdr->len = len;
+ hdr->device_addr = addr;
usb_fill_bulk_urb(int_urb, priv->udev,
usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg),
- p54u_tx_free_cb, dev);
- usb_submit_urb(int_urb, GFP_ATOMIC);
+ p54u_tx_dummy_cb, dev);
+
+ /*
+ * This flag triggers a code path in the USB subsystem that will
+ * free what's inside the transfer_buffer after the callback routine
+ * has completed.
+ */
+ int_urb->transfer_flags |= URB_FREE_BUFFER;
usb_fill_bulk_urb(data_urb, priv->udev,
- usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), hdr, len + sizeof(*hdr),
- free_on_tx ? p54u_tx_free_cb : p54u_tx_cb, dev);
- usb_submit_urb(data_urb, GFP_ATOMIC);
+ usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA),
+ skb->data, skb->len, p54u_tx_cb, skb);
+
+ usb_anchor_urb(int_urb, &priv->submitted);
+ err = usb_submit_urb(int_urb, GFP_ATOMIC);
+ if (err) {
+ usb_unanchor_urb(int_urb);
+ goto out;
+ }
+
+ usb_anchor_urb(data_urb, &priv->submitted);
+ err = usb_submit_urb(data_urb, GFP_ATOMIC);
+ if (err) {
+ usb_unanchor_urb(data_urb);
+ goto out;
+ }
+ out:
+ usb_free_urb(int_urb);
+ usb_free_urb(data_urb);
+
+ if (err) {
+ skb_pull(skb, sizeof(*hdr));
+ p54_free_skb(dev, skb);
+ }
}
static int p54u_write(struct p54u_priv *priv,
@@ -375,7 +442,8 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL);
if (!buf) {
- printk(KERN_ERR "p54usb: cannot allocate firmware upload buffer!\n");
+ dev_err(&priv->udev->dev, "(p54usb) cannot allocate firmware"
+ "upload buffer!\n");
err = -ENOMEM;
goto err_bufalloc;
}
@@ -383,14 +451,18 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
memcpy(buf, start_string, 4);
err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 4);
if (err) {
- printk(KERN_ERR "p54usb: reset failed! (%d)\n", err);
+ dev_err(&priv->udev->dev, "(p54usb) reset failed! (%d)\n", err);
goto err_reset;
}
- err = request_firmware(&fw_entry, "isl3887usb_bare", &priv->udev->dev);
+ err = request_firmware(&fw_entry, "isl3887usb", &priv->udev->dev);
if (err) {
- printk(KERN_ERR "p54usb: cannot find firmware (isl3887usb_bare)!\n");
- goto err_req_fw_failed;
+ dev_err(&priv->udev->dev, "p54usb: cannot find firmware "
+ "(isl3887usb)\n");
+ err = request_firmware(&fw_entry, "isl3887usb_bare",
+ &priv->udev->dev);
+ if (err)
+ goto err_req_fw_failed;
}
err = p54_parse_firmware(dev, fw_entry);
@@ -441,7 +513,8 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_size);
if (err) {
- printk(KERN_ERR "p54usb: firmware upload failed!\n");
+ dev_err(&priv->udev->dev, "(p54usb) firmware "
+ "upload failed!\n");
goto err_upload_failed;
}
@@ -452,10 +525,9 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
*((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, fw_entry->data, fw_entry->size));
err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32));
if (err) {
- printk(KERN_ERR "p54usb: firmware upload failed!\n");
+ dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n");
goto err_upload_failed;
}
-
timeout = jiffies + msecs_to_jiffies(1000);
while (!(err = usb_bulk_msg(priv->udev,
usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) {
@@ -463,25 +535,27 @@ static int p54u_upload_firmware_3887(struct ieee80211_hw *dev)
break;
if (alen > 5 && !memcmp(buf, "ERROR", 5)) {
- printk(KERN_INFO "p54usb: firmware upload failed!\n");
err = -EINVAL;
break;
}
if (time_after(jiffies, timeout)) {
- printk(KERN_ERR "p54usb: firmware boot timed out!\n");
+ dev_err(&priv->udev->dev, "(p54usb) firmware boot "
+ "timed out!\n");
err = -ETIMEDOUT;
break;
}
}
- if (err)
+ if (err) {
+ dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n");
goto err_upload_failed;
+ }
buf[0] = 'g';
buf[1] = '\r';
err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 2);
if (err) {
- printk(KERN_ERR "p54usb: firmware boot failed!\n");
+ dev_err(&priv->udev->dev, "(p54usb) firmware boot failed!\n");
goto err_upload_failed;
}
@@ -521,15 +595,21 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
buf = kmalloc(512, GFP_KERNEL);
if (!buf) {
- printk(KERN_ERR "p54usb: firmware buffer alloc failed!\n");
+ dev_err(&priv->udev->dev, "(p54usb) firmware buffer "
+ "alloc failed!\n");
return -ENOMEM;
}
- err = request_firmware(&fw_entry, "isl3890usb", &priv->udev->dev);
+ err = request_firmware(&fw_entry, "isl3886usb", &priv->udev->dev);
if (err) {
- printk(KERN_ERR "p54usb: cannot find firmware (isl3890usb)!\n");
- kfree(buf);
- return err;
+ dev_err(&priv->udev->dev, "(p54usb) cannot find firmware "
+ "(isl3886usb)\n");
+ err = request_firmware(&fw_entry, "isl3890usb",
+ &priv->udev->dev);
+ if (err) {
+ kfree(buf);
+ return err;
+ }
}
err = p54_parse_firmware(dev, fw_entry);
@@ -648,8 +728,8 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_len);
if (err) {
- printk(KERN_ERR "p54usb: firmware block upload "
- "failed\n");
+ dev_err(&priv->udev->dev, "(p54usb) firmware block "
+ "upload failed\n");
goto fail;
}
@@ -682,8 +762,8 @@ static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev)
0x002C | (unsigned long)&devreg->direct_mem_win);
if (!(reg & cpu_to_le32(ISL38XX_DMA_STATUS_DONE)) ||
!(reg & cpu_to_le32(ISL38XX_DMA_STATUS_READY))) {
- printk(KERN_ERR "p54usb: firmware DMA transfer "
- "failed\n");
+ dev_err(&priv->udev->dev, "(p54usb) firmware DMA "
+ "transfer failed\n");
goto fail;
}
@@ -786,11 +866,11 @@ static int __devinit p54u_probe(struct usb_interface *intf,
struct p54u_priv *priv;
int err;
unsigned int i, recognized_pipes;
- DECLARE_MAC_BUF(mac);
dev = p54_init_common(sizeof(*priv));
+
if (!dev) {
- printk(KERN_ERR "p54usb: ieee80211 alloc failed\n");
+ dev_err(&udev->dev, "(p54usb) ieee80211 alloc failed\n");
return -ENOMEM;
}
@@ -842,6 +922,7 @@ static int __devinit p54u_probe(struct usb_interface *intf,
goto err_free_dev;
skb_queue_head_init(&priv->rx_queue);
+ init_usb_anchor(&priv->submitted);
p54u_open(dev);
err = p54_read_eeprom(dev);
@@ -851,7 +932,7 @@ static int __devinit p54u_probe(struct usb_interface *intf,
err = ieee80211_register_hw(dev);
if (err) {
- printk(KERN_ERR "p54usb: Cannot register netdevice\n");
+ dev_err(&udev->dev, "(p54usb) Cannot register netdevice\n");
goto err_free_dev;
}
diff --git a/drivers/net/wireless/p54/p54usb.h b/drivers/net/wireless/p54/p54usb.h
index 5b8fe91379c3..54ee738bf2af 100644
--- a/drivers/net/wireless/p54/p54usb.h
+++ b/drivers/net/wireless/p54/p54usb.h
@@ -133,6 +133,7 @@ struct p54u_priv {
spinlock_t lock;
struct sk_buff_head rx_queue;
+ struct usb_anchor submitted;
};
#endif /* P54USB_H */
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
index 16e68f4b654a..57a150a22de5 100644
--- a/drivers/net/wireless/prism54/isl_ioctl.c
+++ b/drivers/net/wireless/prism54/isl_ioctl.c
@@ -2028,12 +2028,11 @@ static void
format_event(islpci_private *priv, char *dest, const char *str,
const struct obj_mlme *mlme, u16 *length, int error)
{
- DECLARE_MAC_BUF(mac);
int n = snprintf(dest, IW_CUSTOM_MAX,
- "%s %s %s %s (%2.2X)",
+ "%s %s %pM %s (%2.2X)",
str,
((priv->iw_mode == IW_MODE_MASTER) ? "from" : "to"),
- print_mac(mac, mlme->address),
+ mlme->address,
(error ? (mlme->code ? " : REJECTED " : " : ACCEPTED ")
: ""), mlme->code);
BUG_ON(n > IW_CUSTOM_MAX);
@@ -2113,7 +2112,6 @@ prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid,
{
struct list_head *ptr;
struct islpci_bss_wpa_ie *bss = NULL;
- DECLARE_MAC_BUF(mac);
if (wpa_ie_len > MAX_WPA_IE_LEN)
wpa_ie_len = MAX_WPA_IE_LEN;
@@ -2154,7 +2152,7 @@ prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid,
bss->last_update = jiffies;
} else {
printk(KERN_DEBUG "Failed to add BSS WPA entry for "
- "%s\n", print_mac(mac, bssid));
+ "%pM\n", bssid);
}
/* expire old entries from WPA list */
@@ -2219,7 +2217,6 @@ prism54_process_bss_data(islpci_private *priv, u32 oid, u8 *addr,
{
struct ieee80211_beacon_phdr *hdr;
u8 *pos, *end;
- DECLARE_MAC_BUF(mac);
if (!priv->wpa)
return;
@@ -2230,7 +2227,7 @@ prism54_process_bss_data(islpci_private *priv, u32 oid, u8 *addr,
while (pos < end) {
if (pos + 2 + pos[1] > end) {
printk(KERN_DEBUG "Parsing Beacon/ProbeResp failed "
- "for %s\n", print_mac(mac, addr));
+ "for %pM\n", addr);
return;
}
if (pos[0] == WLAN_EID_GENERIC && pos[1] >= 4 &&
@@ -2269,7 +2266,6 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
size_t len = 0; /* u16, better? */
u8 *payload = NULL, *pos = NULL;
int ret;
- DECLARE_MAC_BUF(mac);
/* I think all trapable objects are listed here.
* Some oids have a EX version. The difference is that they are emitted
@@ -2358,8 +2354,8 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
break;
memcpy(&confirm->address, mlmeex->address, ETH_ALEN);
- printk(KERN_DEBUG "Authenticate from: address:\t%s\n",
- print_mac(mac, mlmeex->address));
+ printk(KERN_DEBUG "Authenticate from: address:\t%pM\n",
+ mlmeex->address);
confirm->id = -1; /* or mlmeex->id ? */
confirm->state = 0; /* not used */
confirm->code = 0;
@@ -2404,8 +2400,8 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
wpa_ie_len = prism54_wpa_bss_ie_get(priv, mlmeex->address, wpa_ie);
if (!wpa_ie_len) {
- printk(KERN_DEBUG "No WPA IE found from address:\t%s\n",
- print_mac(mac, mlmeex->address));
+ printk(KERN_DEBUG "No WPA IE found from address:\t%pM\n",
+ mlmeex->address);
kfree(confirm);
break;
}
@@ -2441,8 +2437,8 @@ prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid,
wpa_ie_len = prism54_wpa_bss_ie_get(priv, mlmeex->address, wpa_ie);
if (!wpa_ie_len) {
- printk(KERN_DEBUG "No WPA IE found from address:\t%s\n",
- print_mac(mac, mlmeex->address));
+ printk(KERN_DEBUG "No WPA IE found from address:\t%pM\n",
+ mlmeex->address);
kfree(confirm);
break;
}
diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c
index af2e4f2405f2..9a72b1e3e163 100644
--- a/drivers/net/wireless/prism54/islpci_hotplug.c
+++ b/drivers/net/wireless/prism54/islpci_hotplug.c
@@ -93,7 +93,7 @@ static struct pci_driver prism54_driver = {
Module initialization functions
******************************************************************************/
-int
+static int
prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct net_device *ndev;
@@ -216,7 +216,7 @@ prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id)
static volatile int __in_cleanup_module = 0;
/* this one removes one(!!) instance only */
-void
+static void
prism54_remove(struct pci_dev *pdev)
{
struct net_device *ndev = pci_get_drvdata(pdev);
@@ -259,7 +259,7 @@ prism54_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
}
-int
+static int
prism54_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *ndev = pci_get_drvdata(pdev);
@@ -282,7 +282,7 @@ prism54_suspend(struct pci_dev *pdev, pm_message_t state)
return 0;
}
-int
+static int
prism54_resume(struct pci_dev *pdev)
{
struct net_device *ndev = pci_get_drvdata(pdev);
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 1404a5717520..99ec7d622518 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -414,7 +414,6 @@ static int ray_config(struct pcmcia_device *link)
memreq_t mem;
struct net_device *dev = (struct net_device *)link->priv;
ray_dev_t *local = netdev_priv(dev);
- DECLARE_MAC_BUF(mac);
DEBUG(1, "ray_config(0x%p)\n", link);
@@ -485,8 +484,8 @@ static int ray_config(struct pcmcia_device *link)
strcpy(local->node.dev_name, dev->name);
link->dev_node = &local->node;
- printk(KERN_INFO "%s: RayLink, irq %d, hw_addr %s\n",
- dev->name, dev->irq, print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "%s: RayLink, irq %d, hw_addr %pM\n",
+ dev->name, dev->irq, dev->dev_addr);
return 0;
@@ -829,7 +828,7 @@ static int ray_resume(struct pcmcia_device *link)
}
/*===========================================================================*/
-int ray_dev_init(struct net_device *dev)
+static int ray_dev_init(struct net_device *dev)
{
#ifdef RAY_IMMEDIATE_INIT
int i;
@@ -2285,7 +2284,6 @@ static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, unsigned i
skb->protocol = eth_type_trans(skb,dev);
netif_rx(skb);
- dev->last_rx = jiffies;
local->stats.rx_packets++;
local->stats.rx_bytes += total_len;
@@ -2595,7 +2593,6 @@ static int ray_cs_proc_show(struct seq_file *m, void *v)
UCHAR *p;
struct freq_hop_element *pfh;
UCHAR c[33];
- DECLARE_MAC_BUF(mac);
link = this_device;
if (!link)
@@ -2623,8 +2620,7 @@ static int ray_cs_proc_show(struct seq_file *m, void *v)
nettype[local->sparm.b5.a_network_type], c);
p = local->bss_id;
- seq_printf(m, "BSSID = %s\n",
- print_mac(mac, p));
+ seq_printf(m, "BSSID = %pM\n", p);
seq_printf(m, "Country code = %d\n",
local->sparm.b5.a_curr_country_code);
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 2b414899dfa0..607ce9f61b54 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -37,11 +37,11 @@
#include <linux/usb.h>
#include <linux/usb/cdc.h>
#include <linux/wireless.h>
+#include <linux/ieee80211.h>
#include <linux/if_arp.h>
#include <linux/ctype.h>
#include <linux/spinlock.h>
#include <net/iw_handler.h>
-#include <net/ieee80211.h>
#include <linux/usb/usbnet.h>
#include <linux/usb/rndis_host.h>
@@ -1104,7 +1104,7 @@ static int rndis_iw_get_range(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
struct iw_range *range = (struct iw_range *)extra;
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
int len, ret, i, j, num, has_80211g_rates;
u8 rates[8];
@@ -1210,7 +1210,7 @@ static int rndis_iw_get_range(struct net_device *dev,
static int rndis_iw_get_name(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
strcpy(wrqu->name, priv->name);
@@ -1223,7 +1223,7 @@ static int rndis_iw_set_essid(struct net_device *dev,
{
struct ndis_80211_ssid ssid;
int length = wrqu->essid.length;
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
devdbg(usbdev, "SIOCSIWESSID: [flags:%d,len:%d] '%.32s'",
wrqu->essid.flags, wrqu->essid.length, essid);
@@ -1250,7 +1250,7 @@ static int rndis_iw_get_essid(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *essid)
{
struct ndis_80211_ssid ssid;
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
int ret;
ret = get_essid(usbdev, &ssid);
@@ -1273,15 +1273,14 @@ static int rndis_iw_get_essid(struct net_device *dev,
static int rndis_iw_get_bssid(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
unsigned char bssid[ETH_ALEN];
int ret;
- DECLARE_MAC_BUF(mac);
ret = get_bssid(usbdev, bssid);
if (ret == 0)
- devdbg(usbdev, "SIOCGIWAP: %s", print_mac(mac, bssid));
+ devdbg(usbdev, "SIOCGIWAP: %pM", bssid);
else
devdbg(usbdev, "SIOCGIWAP: <not associated>");
@@ -1295,12 +1294,11 @@ static int rndis_iw_get_bssid(struct net_device *dev,
static int rndis_iw_set_bssid(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
u8 *bssid = (u8 *)wrqu->ap_addr.sa_data;
- DECLARE_MAC_BUF(mac);
int ret;
- devdbg(usbdev, "SIOCSIWAP: %s", print_mac(mac, bssid));
+ devdbg(usbdev, "SIOCSIWAP: %pM", bssid);
ret = rndis_set_oid(usbdev, OID_802_11_BSSID, bssid, ETH_ALEN);
@@ -1318,7 +1316,7 @@ static int rndis_iw_set_auth(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
struct iw_param *p = &wrqu->param;
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
int ret = -ENOTSUPP;
@@ -1399,7 +1397,7 @@ static int rndis_iw_get_auth(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
struct iw_param *p = &wrqu->param;
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
switch (p->flags & IW_AUTH_INDEX) {
@@ -1431,7 +1429,7 @@ static int rndis_iw_get_mode(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
switch (priv->infra_mode) {
@@ -1454,7 +1452,7 @@ static int rndis_iw_get_mode(struct net_device *dev,
static int rndis_iw_set_mode(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
int mode;
devdbg(usbdev, "SIOCSIWMODE: %08x", wrqu->mode);
@@ -1479,7 +1477,7 @@ static int rndis_iw_set_mode(struct net_device *dev,
static int rndis_iw_set_encode(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
int ret, index, key_len;
u8 *key;
@@ -1542,7 +1540,7 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
struct ndis_80211_key ndis_key;
int keyidx, ret;
@@ -1627,7 +1625,7 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
static int rndis_iw_set_scan(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
union iwreq_data evt;
int ret = -EINVAL;
__le32 tmp;
@@ -1652,19 +1650,18 @@ static char *rndis_translate_scan(struct net_device *dev,
struct ndis_80211_bssid_ex *bssid)
{
#ifdef DEBUG
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
#endif
- struct ieee80211_info_element *ie;
+ u8 *ie;
char *current_val;
int bssid_len, ie_len, i;
u32 beacon, atim;
struct iw_event iwe;
unsigned char sbuf[32];
- DECLARE_MAC_BUF(mac);
bssid_len = le32_to_cpu(bssid->length);
- devdbg(usbdev, "BSSID %s", print_mac(mac, bssid->mac));
+ devdbg(usbdev, "BSSID %pM", bssid->mac);
iwe.cmd = SIOCGIWAP;
iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
memcpy(iwe.u.ap_addr.sa_data, bssid->mac, ETH_ALEN);
@@ -1753,20 +1750,20 @@ static char *rndis_translate_scan(struct net_device *dev,
ie_len = min(bssid_len - (int)sizeof(*bssid),
(int)le32_to_cpu(bssid->ie_length));
ie_len -= sizeof(struct ndis_80211_fixed_ies);
- while (ie_len >= sizeof(*ie) && sizeof(*ie) + ie->len <= ie_len) {
- if ((ie->id == MFIE_TYPE_GENERIC && ie->len >= 4 &&
- memcmp(ie->data, "\x00\x50\xf2\x01", 4) == 0) ||
- ie->id == MFIE_TYPE_RSN) {
+ while (ie_len >= 2 && 2 + ie[1] <= ie_len) {
+ if ((ie[0] == WLAN_EID_GENERIC && ie[1] >= 4 &&
+ memcmp(ie + 2, "\x00\x50\xf2\x01", 4) == 0) ||
+ ie[0] == WLAN_EID_RSN) {
devdbg(usbdev, "IE: WPA%d",
- (ie->id == MFIE_TYPE_RSN) ? 2 : 1);
+ (ie[0] == WLAN_EID_RSN) ? 2 : 1);
iwe.cmd = IWEVGENIE;
- iwe.u.data.length = min(ie->len + 2, MAX_WPA_IE_LEN);
- cev = iwe_stream_add_point(info, cev, end_buf, &iwe,
- (u8 *)ie);
+ /* arbitrary cut-off at 64 */
+ iwe.u.data.length = min(ie[1] + 2, 64);
+ cev = iwe_stream_add_point(info, cev, end_buf, &iwe, ie);
}
- ie_len -= sizeof(*ie) + ie->len;
- ie = (struct ieee80211_info_element *)&ie->data[ie->len];
+ ie_len -= 2 + ie[1];
+ ie += 2 + ie[1];
}
return cev;
@@ -1776,7 +1773,7 @@ static char *rndis_translate_scan(struct net_device *dev,
static int rndis_iw_get_scan(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
void *buf = NULL;
char *cev = extra;
struct ndis_80211_bssid_list_ex *bssid_list;
@@ -1822,7 +1819,7 @@ out:
static int rndis_iw_set_genie(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
int ret = 0;
@@ -1856,7 +1853,7 @@ static int rndis_iw_set_genie(struct net_device *dev,
static int rndis_iw_get_genie(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
devdbg(usbdev, "SIOCGIWGENIE");
@@ -1879,7 +1876,7 @@ static int rndis_iw_get_genie(struct net_device *dev,
static int rndis_iw_set_rts(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
__le32 tmp;
devdbg(usbdev, "SIOCSIWRTS");
@@ -1892,7 +1889,7 @@ static int rndis_iw_set_rts(struct net_device *dev,
static int rndis_iw_get_rts(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
__le32 tmp;
int len, ret;
@@ -1913,7 +1910,7 @@ static int rndis_iw_get_rts(struct net_device *dev,
static int rndis_iw_set_frag(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
__le32 tmp;
devdbg(usbdev, "SIOCSIWFRAG");
@@ -1927,7 +1924,7 @@ static int rndis_iw_set_frag(struct net_device *dev,
static int rndis_iw_get_frag(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
__le32 tmp;
int len, ret;
@@ -1947,7 +1944,7 @@ static int rndis_iw_get_frag(struct net_device *dev,
static int rndis_iw_set_nick(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
devdbg(usbdev, "SIOCSIWNICK");
@@ -1964,7 +1961,7 @@ static int rndis_iw_set_nick(struct net_device *dev,
static int rndis_iw_get_nick(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
wrqu->data.flags = 1;
@@ -1980,7 +1977,7 @@ static int rndis_iw_get_nick(struct net_device *dev,
static int rndis_iw_set_freq(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
struct ndis_80211_conf config;
unsigned int dsconfig;
int len, ret;
@@ -2011,7 +2008,7 @@ static int rndis_iw_set_freq(struct net_device *dev,
static int rndis_iw_get_freq(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
struct ndis_80211_conf config;
int len, ret;
@@ -2028,7 +2025,7 @@ static int rndis_iw_get_freq(struct net_device *dev,
static int rndis_iw_get_txpower(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
__le32 tx_power;
int ret = 0, len;
@@ -2062,7 +2059,7 @@ static int rndis_iw_get_txpower(struct net_device *dev,
static int rndis_iw_set_txpower(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
__le32 tx_power = 0;
int ret = 0;
@@ -2114,7 +2111,7 @@ static int rndis_iw_set_txpower(struct net_device *dev,
static int rndis_iw_get_rate(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
__le32 tmp;
int ret, len;
@@ -2132,7 +2129,7 @@ static int rndis_iw_get_rate(struct net_device *dev,
static int rndis_iw_set_mlme(struct net_device *dev,
struct iw_request_info *info, union iwreq_data *wrqu, char *extra)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
struct iw_mlme *mlme = (struct iw_mlme *)extra;
unsigned char bssid[ETH_ALEN];
@@ -2157,7 +2154,7 @@ static int rndis_iw_set_mlme(struct net_device *dev,
static struct iw_statistics *rndis_get_wireless_stats(struct net_device *dev)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
unsigned long flags;
@@ -2287,7 +2284,7 @@ get_bssid:
static void rndis_wext_set_multicast_list(struct net_device *dev)
{
- struct usbnet *usbdev = dev->priv;
+ struct usbnet *usbdev = netdev_priv(dev);
struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
if (test_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending))
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index 95511ac22470..178b313293b4 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -57,6 +57,7 @@ config RT2500USB
tristate "Ralink rt2500 (USB) support"
depends on USB
select RT2X00_LIB_USB
+ select RT2X00_LIB_CRYPTO
---help---
This adds support for rt2500 wireless chipset family.
Supported chips: RT2571 & RT2572.
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 08cb9eec16a6..6a977679124d 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -49,45 +49,33 @@
* the access attempt is considered to have failed,
* and we will print an error.
*/
-static u32 rt2400pci_bbp_check(struct rt2x00_dev *rt2x00dev)
-{
- u32 reg;
- unsigned int i;
-
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, BBPCSR, &reg);
- if (!rt2x00_get_field32(reg, BBPCSR_BUSY))
- break;
- udelay(REGISTER_BUSY_DELAY);
- }
-
- return reg;
-}
+#define WAIT_FOR_BBP(__dev, __reg) \
+ rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))
+#define WAIT_FOR_RF(__dev, __reg) \
+ rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))
static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
{
u32 reg;
- /*
- * Wait until the BBP becomes ready.
- */
- reg = rt2400pci_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, BBPCSR_BUSY)) {
- ERROR(rt2x00dev, "BBPCSR register busy. Write failed.\n");
- return;
- }
+ mutex_lock(&rt2x00dev->csr_mutex);
/*
- * Write the data into the BBP.
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the new data into the register.
*/
- reg = 0;
- rt2x00_set_field32(&reg, BBPCSR_VALUE, value);
- rt2x00_set_field32(&reg, BBPCSR_REGNUM, word);
- rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
- rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 1);
+ if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+ reg = 0;
+ rt2x00_set_field32(&reg, BBPCSR_VALUE, value);
+ rt2x00_set_field32(&reg, BBPCSR_REGNUM, word);
+ rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
+ rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 1);
+
+ rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
+ }
- rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
+ mutex_unlock(&rt2x00dev->csr_mutex);
}
static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev,
@@ -95,66 +83,58 @@ static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- /*
- * Wait until the BBP becomes ready.
- */
- reg = rt2400pci_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, BBPCSR_BUSY)) {
- ERROR(rt2x00dev, "BBPCSR register busy. Read failed.\n");
- return;
- }
+ mutex_lock(&rt2x00dev->csr_mutex);
/*
- * Write the request into the BBP.
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the read request into the register.
+ * After the data has been written, we wait until hardware
+ * returns the correct value, if at any time the register
+ * doesn't become available in time, reg will be 0xffffffff
+ * which means we return 0xff to the caller.
*/
- reg = 0;
- rt2x00_set_field32(&reg, BBPCSR_REGNUM, word);
- rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
- rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 0);
+ if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+ reg = 0;
+ rt2x00_set_field32(&reg, BBPCSR_REGNUM, word);
+ rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
+ rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 0);
- rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
+ rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
- /*
- * Wait until the BBP becomes ready.
- */
- reg = rt2400pci_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, BBPCSR_BUSY)) {
- ERROR(rt2x00dev, "BBPCSR register busy. Read failed.\n");
- *value = 0xff;
- return;
+ WAIT_FOR_BBP(rt2x00dev, &reg);
}
*value = rt2x00_get_field32(reg, BBPCSR_VALUE);
+
+ mutex_unlock(&rt2x00dev->csr_mutex);
}
static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u32 value)
{
u32 reg;
- unsigned int i;
if (!word)
return;
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, RFCSR, &reg);
- if (!rt2x00_get_field32(reg, RFCSR_BUSY))
- goto rf_write;
- udelay(REGISTER_BUSY_DELAY);
- }
-
- ERROR(rt2x00dev, "RFCSR register busy. Write failed.\n");
- return;
+ mutex_lock(&rt2x00dev->csr_mutex);
-rf_write:
- reg = 0;
- rt2x00_set_field32(&reg, RFCSR_VALUE, value);
- rt2x00_set_field32(&reg, RFCSR_NUMBER_OF_BITS, 20);
- rt2x00_set_field32(&reg, RFCSR_IF_SELECT, 0);
- rt2x00_set_field32(&reg, RFCSR_BUSY, 1);
+ /*
+ * Wait until the RF becomes available, afterwards we
+ * can safely write the new data into the register.
+ */
+ if (WAIT_FOR_RF(rt2x00dev, &reg)) {
+ reg = 0;
+ rt2x00_set_field32(&reg, RFCSR_VALUE, value);
+ rt2x00_set_field32(&reg, RFCSR_NUMBER_OF_BITS, 20);
+ rt2x00_set_field32(&reg, RFCSR_IF_SELECT, 0);
+ rt2x00_set_field32(&reg, RFCSR_BUSY, 1);
+
+ rt2x00pci_register_write(rt2x00dev, RFCSR, reg);
+ rt2x00_rf_write(rt2x00dev, word, value);
+ }
- rt2x00pci_register_write(rt2x00dev, RFCSR, reg);
- rt2x00_rf_write(rt2x00dev, word, value);
+ mutex_unlock(&rt2x00dev->csr_mutex);
}
static void rt2400pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
@@ -188,43 +168,34 @@ static void rt2400pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
}
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-#define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u32)) )
-
-static void rt2400pci_read_csr(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u32 *data)
-{
- rt2x00pci_register_read(rt2x00dev, CSR_OFFSET(word), data);
-}
-
-static void rt2400pci_write_csr(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u32 data)
-{
- rt2x00pci_register_write(rt2x00dev, CSR_OFFSET(word), data);
-}
-
static const struct rt2x00debug rt2400pci_rt2x00debug = {
.owner = THIS_MODULE,
.csr = {
- .read = rt2400pci_read_csr,
- .write = rt2400pci_write_csr,
+ .read = rt2x00pci_register_read,
+ .write = rt2x00pci_register_write,
+ .flags = RT2X00DEBUGFS_OFFSET,
+ .word_base = CSR_REG_BASE,
.word_size = sizeof(u32),
.word_count = CSR_REG_SIZE / sizeof(u32),
},
.eeprom = {
.read = rt2x00_eeprom_read,
.write = rt2x00_eeprom_write,
+ .word_base = EEPROM_BASE,
.word_size = sizeof(u16),
.word_count = EEPROM_SIZE / sizeof(u16),
},
.bbp = {
.read = rt2400pci_bbp_read,
.write = rt2400pci_bbp_write,
+ .word_base = BBP_BASE,
.word_size = sizeof(u8),
.word_count = BBP_SIZE / sizeof(u8),
},
.rf = {
.read = rt2x00_rf_read,
.write = rt2400pci_rf_write,
+ .word_base = RF_BASE,
.word_size = sizeof(u32),
.word_count = RF_SIZE / sizeof(u32),
},
@@ -331,7 +302,7 @@ static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev,
/*
* Enable beacon config
*/
- bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20);
+ bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
rt2x00pci_register_read(rt2x00dev, BCNCSR1, &reg);
rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg);
@@ -376,32 +347,94 @@ static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
- rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 10));
+ rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 10));
rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg);
rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
- rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 20));
+ rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 20));
rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg);
rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
- rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 55));
+ rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 55));
rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg);
rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
- rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110));
+ rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 110));
rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
+
+ rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
+
+ rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+ rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
+ rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+
+ rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
+ rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
+ rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
+ rt2x00pci_register_write(rt2x00dev, CSR18, reg);
+
+ rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
+ rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
+ rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
+ rt2x00pci_register_write(rt2x00dev, CSR19, reg);
}
-static void rt2400pci_config_phymode(struct rt2x00_dev *rt2x00dev,
- const int basic_rate_mask)
+static void rt2400pci_config_ant(struct rt2x00_dev *rt2x00dev,
+ struct antenna_setup *ant)
{
- rt2x00pci_register_write(rt2x00dev, ARCSR1, basic_rate_mask);
+ u8 r1;
+ u8 r4;
+
+ /*
+ * We should never come here because rt2x00lib is supposed
+ * to catch this and send us the correct antenna explicitely.
+ */
+ BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
+ ant->tx == ANTENNA_SW_DIVERSITY);
+
+ rt2400pci_bbp_read(rt2x00dev, 4, &r4);
+ rt2400pci_bbp_read(rt2x00dev, 1, &r1);
+
+ /*
+ * Configure the TX antenna.
+ */
+ switch (ant->tx) {
+ case ANTENNA_HW_DIVERSITY:
+ rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 1);
+ break;
+ case ANTENNA_A:
+ rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 0);
+ break;
+ case ANTENNA_B:
+ default:
+ rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 2);
+ break;
+ }
+
+ /*
+ * Configure the RX antenna.
+ */
+ switch (ant->rx) {
+ case ANTENNA_HW_DIVERSITY:
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
+ break;
+ case ANTENNA_A:
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 0);
+ break;
+ case ANTENNA_B:
+ default:
+ rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
+ break;
+ }
+
+ rt2400pci_bbp_write(rt2x00dev, 4, r4);
+ rt2400pci_bbp_write(rt2x00dev, 1, r1);
}
static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev,
@@ -460,56 +493,17 @@ static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower)
rt2400pci_bbp_write(rt2x00dev, 3, TXPOWER_TO_DEV(txpower));
}
-static void rt2400pci_config_antenna(struct rt2x00_dev *rt2x00dev,
- struct antenna_setup *ant)
+static void rt2400pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_conf *libconf)
{
- u8 r1;
- u8 r4;
-
- /*
- * We should never come here because rt2x00lib is supposed
- * to catch this and send us the correct antenna explicitely.
- */
- BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
- ant->tx == ANTENNA_SW_DIVERSITY);
-
- rt2400pci_bbp_read(rt2x00dev, 4, &r4);
- rt2400pci_bbp_read(rt2x00dev, 1, &r1);
-
- /*
- * Configure the TX antenna.
- */
- switch (ant->tx) {
- case ANTENNA_HW_DIVERSITY:
- rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 1);
- break;
- case ANTENNA_A:
- rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 0);
- break;
- case ANTENNA_B:
- default:
- rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 2);
- break;
- }
-
- /*
- * Configure the RX antenna.
- */
- switch (ant->rx) {
- case ANTENNA_HW_DIVERSITY:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1);
- break;
- case ANTENNA_A:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 0);
- break;
- case ANTENNA_B:
- default:
- rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2);
- break;
- }
+ u32 reg;
- rt2400pci_bbp_write(rt2x00dev, 4, r4);
- rt2400pci_bbp_write(rt2x00dev, 1, r1);
+ rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+ rt2x00_set_field32(&reg, CSR11_LONG_RETRY,
+ libconf->conf->long_frame_max_tx_count);
+ rt2x00_set_field32(&reg, CSR11_SHORT_RETRY,
+ libconf->conf->short_frame_max_tx_count);
+ rt2x00pci_register_write(rt2x00dev, CSR11, reg);
}
static void rt2400pci_config_duration(struct rt2x00_dev *rt2x00dev,
@@ -517,20 +511,6 @@ static void rt2400pci_config_duration(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
- rt2x00_set_field32(&reg, CSR11_SLOT_TIME, libconf->slot_time);
- rt2x00pci_register_write(rt2x00dev, CSR11, reg);
-
- rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
- rt2x00_set_field32(&reg, CSR18_SIFS, libconf->sifs);
- rt2x00_set_field32(&reg, CSR18_PIFS, libconf->pifs);
- rt2x00pci_register_write(rt2x00dev, CSR18, reg);
-
- rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
- rt2x00_set_field32(&reg, CSR19_DIFS, libconf->difs);
- rt2x00_set_field32(&reg, CSR19_EIFS, libconf->eifs);
- rt2x00pci_register_write(rt2x00dev, CSR19, reg);
-
rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
@@ -548,16 +528,14 @@ static void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf,
const unsigned int flags)
{
- if (flags & CONFIG_UPDATE_PHYMODE)
- rt2400pci_config_phymode(rt2x00dev, libconf->basic_rates);
- if (flags & CONFIG_UPDATE_CHANNEL)
+ if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
rt2400pci_config_channel(rt2x00dev, &libconf->rf);
- if (flags & CONFIG_UPDATE_TXPOWER)
+ if (flags & IEEE80211_CONF_CHANGE_POWER)
rt2400pci_config_txpower(rt2x00dev,
libconf->conf->power_level);
- if (flags & CONFIG_UPDATE_ANTENNA)
- rt2400pci_config_antenna(rt2x00dev, &libconf->ant);
- if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
+ if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+ rt2400pci_config_retry_limit(rt2x00dev, libconf);
+ if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
rt2400pci_config_duration(rt2x00dev, libconf);
}
@@ -628,36 +606,47 @@ static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev)
/*
* Initialization functions.
*/
-static void rt2400pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
- struct queue_entry *entry)
+static bool rt2400pci_get_entry_state(struct queue_entry *entry)
{
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
- struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
u32 word;
- rt2x00_desc_read(entry_priv->desc, 2, &word);
- rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->skb->len);
- rt2x00_desc_write(entry_priv->desc, 2, word);
+ if (entry->queue->qid == QID_RX) {
+ rt2x00_desc_read(entry_priv->desc, 0, &word);
- rt2x00_desc_read(entry_priv->desc, 1, &word);
- rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
- rt2x00_desc_write(entry_priv->desc, 1, word);
+ return rt2x00_get_field32(word, RXD_W0_OWNER_NIC);
+ } else {
+ rt2x00_desc_read(entry_priv->desc, 0, &word);
- rt2x00_desc_read(entry_priv->desc, 0, &word);
- rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
- rt2x00_desc_write(entry_priv->desc, 0, word);
+ return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
+ rt2x00_get_field32(word, TXD_W0_VALID));
+ }
}
-static void rt2400pci_init_txentry(struct rt2x00_dev *rt2x00dev,
- struct queue_entry *entry)
+static void rt2400pci_clear_entry(struct queue_entry *entry)
{
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
u32 word;
- rt2x00_desc_read(entry_priv->desc, 0, &word);
- rt2x00_set_field32(&word, TXD_W0_VALID, 0);
- rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
- rt2x00_desc_write(entry_priv->desc, 0, word);
+ if (entry->queue->qid == QID_RX) {
+ rt2x00_desc_read(entry_priv->desc, 2, &word);
+ rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->skb->len);
+ rt2x00_desc_write(entry_priv->desc, 2, word);
+
+ rt2x00_desc_read(entry_priv->desc, 1, &word);
+ rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
+ rt2x00_desc_write(entry_priv->desc, 1, word);
+
+ rt2x00_desc_read(entry_priv->desc, 0, &word);
+ rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+ rt2x00_desc_write(entry_priv->desc, 0, word);
+ } else {
+ rt2x00_desc_read(entry_priv->desc, 0, &word);
+ rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+ rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+ rt2x00_desc_write(entry_priv->desc, 0, word);
+ }
}
static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev)
@@ -1313,10 +1302,8 @@ static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
*/
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
if (!is_valid_ether_addr(mac)) {
- DECLARE_MAC_BUF(macbuf);
-
random_ether_addr(mac);
- EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac));
+ EEPROM(rt2x00dev, "MAC: %pM\n", mac);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
@@ -1504,20 +1491,6 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* IEEE80211 stack callback functions.
*/
-static int rt2400pci_set_retry_limit(struct ieee80211_hw *hw,
- u32 short_retry, u32 long_retry)
-{
- struct rt2x00_dev *rt2x00dev = hw->priv;
- u32 reg;
-
- rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
- rt2x00_set_field32(&reg, CSR11_LONG_RETRY, long_retry);
- rt2x00_set_field32(&reg, CSR11_SHORT_RETRY, short_retry);
- rt2x00pci_register_write(rt2x00dev, CSR11, reg);
-
- return 0;
-}
-
static int rt2400pci_conf_tx(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
@@ -1576,7 +1549,6 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
.config_interface = rt2x00mac_config_interface,
.configure_filter = rt2x00mac_configure_filter,
.get_stats = rt2x00mac_get_stats,
- .set_retry_limit = rt2400pci_set_retry_limit,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2400pci_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
@@ -1589,8 +1561,8 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
.probe_hw = rt2400pci_probe_hw,
.initialize = rt2x00pci_initialize,
.uninitialize = rt2x00pci_uninitialize,
- .init_rxentry = rt2400pci_init_rxentry,
- .init_txentry = rt2400pci_init_txentry,
+ .get_entry_state = rt2400pci_get_entry_state,
+ .clear_entry = rt2400pci_clear_entry,
.set_device_state = rt2400pci_set_device_state,
.rfkill_poll = rt2400pci_rfkill_poll,
.link_stats = rt2400pci_link_stats,
@@ -1604,6 +1576,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
.config_filter = rt2400pci_config_filter,
.config_intf = rt2400pci_config_intf,
.config_erp = rt2400pci_config_erp,
+ .config_ant = rt2400pci_config_ant,
.config = rt2400pci_config,
};
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h
index bbff381ce396..9aefda4ab3c2 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.h
+++ b/drivers/net/wireless/rt2x00/rt2400pci.h
@@ -46,7 +46,9 @@
#define CSR_REG_SIZE 0x014c
#define EEPROM_BASE 0x0000
#define EEPROM_SIZE 0x0100
+#define BBP_BASE 0x0000
#define BBP_SIZE 0x0020
+#define RF_BASE 0x0000
#define RF_SIZE 0x0010
/*
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index ef42cc04a2d7..d3bc218ec85c 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -49,45 +49,33 @@
* the access attempt is considered to have failed,
* and we will print an error.
*/
-static u32 rt2500pci_bbp_check(struct rt2x00_dev *rt2x00dev)
-{
- u32 reg;
- unsigned int i;
-
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, BBPCSR, &reg);
- if (!rt2x00_get_field32(reg, BBPCSR_BUSY))
- break;
- udelay(REGISTER_BUSY_DELAY);
- }
-
- return reg;
-}
+#define WAIT_FOR_BBP(__dev, __reg) \
+ rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg))
+#define WAIT_FOR_RF(__dev, __reg) \
+ rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg))
static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
{
u32 reg;
- /*
- * Wait until the BBP becomes ready.
- */
- reg = rt2500pci_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, BBPCSR_BUSY)) {
- ERROR(rt2x00dev, "BBPCSR register busy. Write failed.\n");
- return;
- }
+ mutex_lock(&rt2x00dev->csr_mutex);
/*
- * Write the data into the BBP.
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the new data into the register.
*/
- reg = 0;
- rt2x00_set_field32(&reg, BBPCSR_VALUE, value);
- rt2x00_set_field32(&reg, BBPCSR_REGNUM, word);
- rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
- rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 1);
+ if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+ reg = 0;
+ rt2x00_set_field32(&reg, BBPCSR_VALUE, value);
+ rt2x00_set_field32(&reg, BBPCSR_REGNUM, word);
+ rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
+ rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 1);
+
+ rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
+ }
- rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
+ mutex_unlock(&rt2x00dev->csr_mutex);
}
static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev,
@@ -95,66 +83,58 @@ static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- /*
- * Wait until the BBP becomes ready.
- */
- reg = rt2500pci_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, BBPCSR_BUSY)) {
- ERROR(rt2x00dev, "BBPCSR register busy. Read failed.\n");
- return;
- }
+ mutex_lock(&rt2x00dev->csr_mutex);
/*
- * Write the request into the BBP.
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the read request into the register.
+ * After the data has been written, we wait until hardware
+ * returns the correct value, if at any time the register
+ * doesn't become available in time, reg will be 0xffffffff
+ * which means we return 0xff to the caller.
*/
- reg = 0;
- rt2x00_set_field32(&reg, BBPCSR_REGNUM, word);
- rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
- rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 0);
+ if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+ reg = 0;
+ rt2x00_set_field32(&reg, BBPCSR_REGNUM, word);
+ rt2x00_set_field32(&reg, BBPCSR_BUSY, 1);
+ rt2x00_set_field32(&reg, BBPCSR_WRITE_CONTROL, 0);
- rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
+ rt2x00pci_register_write(rt2x00dev, BBPCSR, reg);
- /*
- * Wait until the BBP becomes ready.
- */
- reg = rt2500pci_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, BBPCSR_BUSY)) {
- ERROR(rt2x00dev, "BBPCSR register busy. Read failed.\n");
- *value = 0xff;
- return;
+ WAIT_FOR_BBP(rt2x00dev, &reg);
}
*value = rt2x00_get_field32(reg, BBPCSR_VALUE);
+
+ mutex_unlock(&rt2x00dev->csr_mutex);
}
static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u32 value)
{
u32 reg;
- unsigned int i;
if (!word)
return;
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, RFCSR, &reg);
- if (!rt2x00_get_field32(reg, RFCSR_BUSY))
- goto rf_write;
- udelay(REGISTER_BUSY_DELAY);
- }
-
- ERROR(rt2x00dev, "RFCSR register busy. Write failed.\n");
- return;
+ mutex_lock(&rt2x00dev->csr_mutex);
-rf_write:
- reg = 0;
- rt2x00_set_field32(&reg, RFCSR_VALUE, value);
- rt2x00_set_field32(&reg, RFCSR_NUMBER_OF_BITS, 20);
- rt2x00_set_field32(&reg, RFCSR_IF_SELECT, 0);
- rt2x00_set_field32(&reg, RFCSR_BUSY, 1);
+ /*
+ * Wait until the RF becomes available, afterwards we
+ * can safely write the new data into the register.
+ */
+ if (WAIT_FOR_RF(rt2x00dev, &reg)) {
+ reg = 0;
+ rt2x00_set_field32(&reg, RFCSR_VALUE, value);
+ rt2x00_set_field32(&reg, RFCSR_NUMBER_OF_BITS, 20);
+ rt2x00_set_field32(&reg, RFCSR_IF_SELECT, 0);
+ rt2x00_set_field32(&reg, RFCSR_BUSY, 1);
+
+ rt2x00pci_register_write(rt2x00dev, RFCSR, reg);
+ rt2x00_rf_write(rt2x00dev, word, value);
+ }
- rt2x00pci_register_write(rt2x00dev, RFCSR, reg);
- rt2x00_rf_write(rt2x00dev, word, value);
+ mutex_unlock(&rt2x00dev->csr_mutex);
}
static void rt2500pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
@@ -188,43 +168,34 @@ static void rt2500pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
}
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-#define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u32)) )
-
-static void rt2500pci_read_csr(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u32 *data)
-{
- rt2x00pci_register_read(rt2x00dev, CSR_OFFSET(word), data);
-}
-
-static void rt2500pci_write_csr(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u32 data)
-{
- rt2x00pci_register_write(rt2x00dev, CSR_OFFSET(word), data);
-}
-
static const struct rt2x00debug rt2500pci_rt2x00debug = {
.owner = THIS_MODULE,
.csr = {
- .read = rt2500pci_read_csr,
- .write = rt2500pci_write_csr,
+ .read = rt2x00pci_register_read,
+ .write = rt2x00pci_register_write,
+ .flags = RT2X00DEBUGFS_OFFSET,
+ .word_base = CSR_REG_BASE,
.word_size = sizeof(u32),
.word_count = CSR_REG_SIZE / sizeof(u32),
},
.eeprom = {
.read = rt2x00_eeprom_read,
.write = rt2x00_eeprom_write,
+ .word_base = EEPROM_BASE,
.word_size = sizeof(u16),
.word_count = EEPROM_SIZE / sizeof(u16),
},
.bbp = {
.read = rt2500pci_bbp_read,
.write = rt2500pci_bbp_write,
+ .word_base = BBP_BASE,
.word_size = sizeof(u8),
.word_count = BBP_SIZE / sizeof(u8),
},
.rf = {
.read = rt2x00_rf_read,
.write = rt2500pci_rf_write,
+ .word_base = RF_BASE,
.word_size = sizeof(u32),
.word_count = RF_SIZE / sizeof(u32),
},
@@ -336,7 +307,7 @@ static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev,
/*
* Enable beacon config
*/
- bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20);
+ bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
rt2x00pci_register_read(rt2x00dev, BCNCSR1, &reg);
rt2x00_set_field32(&reg, BCNCSR1_PRELOAD, bcn_preload);
rt2x00_set_field32(&reg, BCNCSR1_BEACON_CWMIN, queue->cw_min);
@@ -382,32 +353,114 @@ static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
rt2x00_set_field32(&reg, ARCSR2_SIGNAL, 0x00);
rt2x00_set_field32(&reg, ARCSR2_SERVICE, 0x04);
- rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 10));
+ rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 10));
rt2x00pci_register_write(rt2x00dev, ARCSR2, reg);
rt2x00pci_register_read(rt2x00dev, ARCSR3, &reg);
rt2x00_set_field32(&reg, ARCSR3_SIGNAL, 0x01 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR3_SERVICE, 0x04);
- rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 20));
+ rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 20));
rt2x00pci_register_write(rt2x00dev, ARCSR3, reg);
rt2x00pci_register_read(rt2x00dev, ARCSR4, &reg);
rt2x00_set_field32(&reg, ARCSR4_SIGNAL, 0x02 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR4_SERVICE, 0x04);
- rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 55));
+ rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 55));
rt2x00pci_register_write(rt2x00dev, ARCSR4, reg);
rt2x00pci_register_read(rt2x00dev, ARCSR5, &reg);
rt2x00_set_field32(&reg, ARCSR5_SIGNAL, 0x03 | preamble_mask);
rt2x00_set_field32(&reg, ARCSR5_SERVICE, 0x84);
- rt2x00_set_field32(&reg, ARCSR2_LENGTH, get_duration(ACK_SIZE, 110));
+ rt2x00_set_field32(&reg, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 110));
rt2x00pci_register_write(rt2x00dev, ARCSR5, reg);
+
+ rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates);
+
+ rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+ rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
+ rt2x00pci_register_write(rt2x00dev, CSR11, reg);
+
+ rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
+ rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
+ rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
+ rt2x00pci_register_write(rt2x00dev, CSR18, reg);
+
+ rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
+ rt2x00_set_field32(&reg, CSR19_DIFS, erp->difs);
+ rt2x00_set_field32(&reg, CSR19_EIFS, erp->eifs);
+ rt2x00pci_register_write(rt2x00dev, CSR19, reg);
}
-static void rt2500pci_config_phymode(struct rt2x00_dev *rt2x00dev,
- const int basic_rate_mask)
+static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev,
+ struct antenna_setup *ant)
{
- rt2x00pci_register_write(rt2x00dev, ARCSR1, basic_rate_mask);
+ u32 reg;
+ u8 r14;
+ u8 r2;
+
+ /*
+ * We should never come here because rt2x00lib is supposed
+ * to catch this and send us the correct antenna explicitely.
+ */
+ BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
+ ant->tx == ANTENNA_SW_DIVERSITY);
+
+ rt2x00pci_register_read(rt2x00dev, BBPCSR1, &reg);
+ rt2500pci_bbp_read(rt2x00dev, 14, &r14);
+ rt2500pci_bbp_read(rt2x00dev, 2, &r2);
+
+ /*
+ * Configure the TX antenna.
+ */
+ switch (ant->tx) {
+ case ANTENNA_A:
+ rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 0);
+ rt2x00_set_field32(&reg, BBPCSR1_CCK, 0);
+ rt2x00_set_field32(&reg, BBPCSR1_OFDM, 0);
+ break;
+ case ANTENNA_B:
+ default:
+ rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2);
+ rt2x00_set_field32(&reg, BBPCSR1_CCK, 2);
+ rt2x00_set_field32(&reg, BBPCSR1_OFDM, 2);
+ break;
+ }
+
+ /*
+ * Configure the RX antenna.
+ */
+ switch (ant->rx) {
+ case ANTENNA_A:
+ rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0);
+ break;
+ case ANTENNA_B:
+ default:
+ rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2);
+ break;
+ }
+
+ /*
+ * RT2525E and RT5222 need to flip TX I/Q
+ */
+ if (rt2x00_rf(&rt2x00dev->chip, RF2525E) ||
+ rt2x00_rf(&rt2x00dev->chip, RF5222)) {
+ rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1);
+ rt2x00_set_field32(&reg, BBPCSR1_CCK_FLIP, 1);
+ rt2x00_set_field32(&reg, BBPCSR1_OFDM_FLIP, 1);
+
+ /*
+ * RT2525E does not need RX I/Q Flip.
+ */
+ if (rt2x00_rf(&rt2x00dev->chip, RF2525E))
+ rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0);
+ } else {
+ rt2x00_set_field32(&reg, BBPCSR1_CCK_FLIP, 0);
+ rt2x00_set_field32(&reg, BBPCSR1_OFDM_FLIP, 0);
+ }
+
+ rt2x00pci_register_write(rt2x00dev, BBPCSR1, reg);
+ rt2500pci_bbp_write(rt2x00dev, 14, r14);
+ rt2500pci_bbp_write(rt2x00dev, 2, r2);
}
static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev,
@@ -489,76 +542,17 @@ static void rt2500pci_config_txpower(struct rt2x00_dev *rt2x00dev,
rt2500pci_rf_write(rt2x00dev, 3, rf3);
}
-static void rt2500pci_config_antenna(struct rt2x00_dev *rt2x00dev,
- struct antenna_setup *ant)
+static void rt2500pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_conf *libconf)
{
u32 reg;
- u8 r14;
- u8 r2;
-
- /*
- * We should never come here because rt2x00lib is supposed
- * to catch this and send us the correct antenna explicitely.
- */
- BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY ||
- ant->tx == ANTENNA_SW_DIVERSITY);
-
- rt2x00pci_register_read(rt2x00dev, BBPCSR1, &reg);
- rt2500pci_bbp_read(rt2x00dev, 14, &r14);
- rt2500pci_bbp_read(rt2x00dev, 2, &r2);
-
- /*
- * Configure the TX antenna.
- */
- switch (ant->tx) {
- case ANTENNA_A:
- rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 0);
- rt2x00_set_field32(&reg, BBPCSR1_CCK, 0);
- rt2x00_set_field32(&reg, BBPCSR1_OFDM, 0);
- break;
- case ANTENNA_B:
- default:
- rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2);
- rt2x00_set_field32(&reg, BBPCSR1_CCK, 2);
- rt2x00_set_field32(&reg, BBPCSR1_OFDM, 2);
- break;
- }
-
- /*
- * Configure the RX antenna.
- */
- switch (ant->rx) {
- case ANTENNA_A:
- rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0);
- break;
- case ANTENNA_B:
- default:
- rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2);
- break;
- }
-
- /*
- * RT2525E and RT5222 need to flip TX I/Q
- */
- if (rt2x00_rf(&rt2x00dev->chip, RF2525E) ||
- rt2x00_rf(&rt2x00dev->chip, RF5222)) {
- rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1);
- rt2x00_set_field32(&reg, BBPCSR1_CCK_FLIP, 1);
- rt2x00_set_field32(&reg, BBPCSR1_OFDM_FLIP, 1);
- /*
- * RT2525E does not need RX I/Q Flip.
- */
- if (rt2x00_rf(&rt2x00dev->chip, RF2525E))
- rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0);
- } else {
- rt2x00_set_field32(&reg, BBPCSR1_CCK_FLIP, 0);
- rt2x00_set_field32(&reg, BBPCSR1_OFDM_FLIP, 0);
- }
-
- rt2x00pci_register_write(rt2x00dev, BBPCSR1, reg);
- rt2500pci_bbp_write(rt2x00dev, 14, r14);
- rt2500pci_bbp_write(rt2x00dev, 2, r2);
+ rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
+ rt2x00_set_field32(&reg, CSR11_LONG_RETRY,
+ libconf->conf->long_frame_max_tx_count);
+ rt2x00_set_field32(&reg, CSR11_SHORT_RETRY,
+ libconf->conf->short_frame_max_tx_count);
+ rt2x00pci_register_write(rt2x00dev, CSR11, reg);
}
static void rt2500pci_config_duration(struct rt2x00_dev *rt2x00dev,
@@ -566,20 +560,6 @@ static void rt2500pci_config_duration(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
- rt2x00_set_field32(&reg, CSR11_SLOT_TIME, libconf->slot_time);
- rt2x00pci_register_write(rt2x00dev, CSR11, reg);
-
- rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
- rt2x00_set_field32(&reg, CSR18_SIFS, libconf->sifs);
- rt2x00_set_field32(&reg, CSR18_PIFS, libconf->pifs);
- rt2x00pci_register_write(rt2x00dev, CSR18, reg);
-
- rt2x00pci_register_read(rt2x00dev, CSR19, &reg);
- rt2x00_set_field32(&reg, CSR19_DIFS, libconf->difs);
- rt2x00_set_field32(&reg, CSR19_EIFS, libconf->eifs);
- rt2x00pci_register_write(rt2x00dev, CSR19, reg);
-
rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
@@ -597,17 +577,16 @@ static void rt2500pci_config(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf,
const unsigned int flags)
{
- if (flags & CONFIG_UPDATE_PHYMODE)
- rt2500pci_config_phymode(rt2x00dev, libconf->basic_rates);
- if (flags & CONFIG_UPDATE_CHANNEL)
+ if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
rt2500pci_config_channel(rt2x00dev, &libconf->rf,
libconf->conf->power_level);
- if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL))
+ if ((flags & IEEE80211_CONF_CHANGE_POWER) &&
+ !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
rt2500pci_config_txpower(rt2x00dev,
libconf->conf->power_level);
- if (flags & CONFIG_UPDATE_ANTENNA)
- rt2500pci_config_antenna(rt2x00dev, &libconf->ant);
- if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
+ if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+ rt2500pci_config_retry_limit(rt2x00dev, libconf);
+ if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
rt2500pci_config_duration(rt2x00dev, libconf);
}
@@ -723,32 +702,43 @@ dynamic_cca_tune:
/*
* Initialization functions.
*/
-static void rt2500pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
- struct queue_entry *entry)
+static bool rt2500pci_get_entry_state(struct queue_entry *entry)
{
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
- struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
u32 word;
- rt2x00_desc_read(entry_priv->desc, 1, &word);
- rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
- rt2x00_desc_write(entry_priv->desc, 1, word);
+ if (entry->queue->qid == QID_RX) {
+ rt2x00_desc_read(entry_priv->desc, 0, &word);
+
+ return rt2x00_get_field32(word, RXD_W0_OWNER_NIC);
+ } else {
+ rt2x00_desc_read(entry_priv->desc, 0, &word);
- rt2x00_desc_read(entry_priv->desc, 0, &word);
- rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
- rt2x00_desc_write(entry_priv->desc, 0, word);
+ return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
+ rt2x00_get_field32(word, TXD_W0_VALID));
+ }
}
-static void rt2500pci_init_txentry(struct rt2x00_dev *rt2x00dev,
- struct queue_entry *entry)
+static void rt2500pci_clear_entry(struct queue_entry *entry)
{
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
u32 word;
- rt2x00_desc_read(entry_priv->desc, 0, &word);
- rt2x00_set_field32(&word, TXD_W0_VALID, 0);
- rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
- rt2x00_desc_write(entry_priv->desc, 0, word);
+ if (entry->queue->qid == QID_RX) {
+ rt2x00_desc_read(entry_priv->desc, 1, &word);
+ rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
+ rt2x00_desc_write(entry_priv->desc, 1, word);
+
+ rt2x00_desc_read(entry_priv->desc, 0, &word);
+ rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+ rt2x00_desc_write(entry_priv->desc, 0, word);
+ } else {
+ rt2x00_desc_read(entry_priv->desc, 0, &word);
+ rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+ rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+ rt2x00_desc_write(entry_priv->desc, 0, word);
+ }
}
static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev)
@@ -1451,11 +1441,8 @@ static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
*/
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
if (!is_valid_ether_addr(mac)) {
- DECLARE_MAC_BUF(macbuf);
-
random_ether_addr(mac);
- EEPROM(rt2x00dev, "MAC: %s\n",
- print_mac(macbuf, mac));
+ EEPROM(rt2x00dev, "MAC: %pM\n", mac);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
@@ -1830,20 +1817,6 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* IEEE80211 stack callback functions.
*/
-static int rt2500pci_set_retry_limit(struct ieee80211_hw *hw,
- u32 short_retry, u32 long_retry)
-{
- struct rt2x00_dev *rt2x00dev = hw->priv;
- u32 reg;
-
- rt2x00pci_register_read(rt2x00dev, CSR11, &reg);
- rt2x00_set_field32(&reg, CSR11_LONG_RETRY, long_retry);
- rt2x00_set_field32(&reg, CSR11_SHORT_RETRY, short_retry);
- rt2x00pci_register_write(rt2x00dev, CSR11, reg);
-
- return 0;
-}
-
static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -1877,7 +1850,6 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
.config_interface = rt2x00mac_config_interface,
.configure_filter = rt2x00mac_configure_filter,
.get_stats = rt2x00mac_get_stats,
- .set_retry_limit = rt2500pci_set_retry_limit,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2x00mac_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
@@ -1890,8 +1862,8 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
.probe_hw = rt2500pci_probe_hw,
.initialize = rt2x00pci_initialize,
.uninitialize = rt2x00pci_uninitialize,
- .init_rxentry = rt2500pci_init_rxentry,
- .init_txentry = rt2500pci_init_txentry,
+ .get_entry_state = rt2500pci_get_entry_state,
+ .clear_entry = rt2500pci_clear_entry,
.set_device_state = rt2500pci_set_device_state,
.rfkill_poll = rt2500pci_rfkill_poll,
.link_stats = rt2500pci_link_stats,
@@ -1905,6 +1877,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
.config_filter = rt2500pci_config_filter,
.config_intf = rt2500pci_config_intf,
.config_erp = rt2500pci_config_erp,
+ .config_ant = rt2500pci_config_ant,
.config = rt2500pci_config,
};
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h
index 8c26bef6cf49..e135247f7f89 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.h
+++ b/drivers/net/wireless/rt2x00/rt2500pci.h
@@ -57,7 +57,9 @@
#define CSR_REG_SIZE 0x0174
#define EEPROM_BASE 0x0000
#define EEPROM_SIZE 0x0200
+#define BBP_BASE 0x0000
#define BBP_SIZE 0x0040
+#define RF_BASE 0x0000
#define RF_SIZE 0x0014
/*
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index d3bf7bba611a..30028e2422fc 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -36,6 +36,13 @@
#include "rt2500usb.h"
/*
+ * Allow hardware encryption to be disabled.
+ */
+static int modparam_nohwcrypt = 1;
+module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
+MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
+
+/*
* Register access.
* All access to the CSR registers will go through the methods
* rt2500usb_register_read and rt2500usb_register_write.
@@ -47,7 +54,7 @@
* between each attampt. When the busy bit is still set at that time,
* the access attempt is considered to have failed,
* and we will print an error.
- * If the usb_cache_mutex is already held then the _lock variants must
+ * If the csr_mutex is already held then the _lock variants must
* be used instead.
*/
static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
@@ -57,7 +64,7 @@ static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
__le16 reg;
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset,
- &reg, sizeof(u16), REGISTER_TIMEOUT);
+ &reg, sizeof(reg), REGISTER_TIMEOUT);
*value = le16_to_cpu(reg);
}
@@ -68,7 +75,7 @@ static inline void rt2500usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
__le16 reg;
rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset,
- &reg, sizeof(u16), REGISTER_TIMEOUT);
+ &reg, sizeof(reg), REGISTER_TIMEOUT);
*value = le16_to_cpu(reg);
}
@@ -89,7 +96,7 @@ static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
__le16 reg = cpu_to_le16(value);
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT, offset,
- &reg, sizeof(u16), REGISTER_TIMEOUT);
+ &reg, sizeof(reg), REGISTER_TIMEOUT);
}
static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
@@ -99,7 +106,7 @@ static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
__le16 reg = cpu_to_le16(value);
rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT, offset,
- &reg, sizeof(u16), REGISTER_TIMEOUT);
+ &reg, sizeof(reg), REGISTER_TIMEOUT);
}
static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
@@ -112,53 +119,53 @@ static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
REGISTER_TIMEOUT16(length));
}
-static u16 rt2500usb_bbp_check(struct rt2x00_dev *rt2x00dev)
+static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ struct rt2x00_field16 field,
+ u16 *reg)
{
- u16 reg;
unsigned int i;
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2500usb_register_read_lock(rt2x00dev, PHY_CSR8, &reg);
- if (!rt2x00_get_field16(reg, PHY_CSR8_BUSY))
- break;
+ rt2500usb_register_read_lock(rt2x00dev, offset, reg);
+ if (!rt2x00_get_field16(*reg, field))
+ return 1;
udelay(REGISTER_BUSY_DELAY);
}
- return reg;
+ ERROR(rt2x00dev, "Indirect register access failed: "
+ "offset=0x%.08x, value=0x%.08x\n", offset, *reg);
+ *reg = ~0;
+
+ return 0;
}
+#define WAIT_FOR_BBP(__dev, __reg) \
+ rt2500usb_regbusy_read((__dev), PHY_CSR8, PHY_CSR8_BUSY, (__reg))
+#define WAIT_FOR_RF(__dev, __reg) \
+ rt2500usb_regbusy_read((__dev), PHY_CSR10, PHY_CSR10_RF_BUSY, (__reg))
+
static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
{
u16 reg;
- mutex_lock(&rt2x00dev->usb_cache_mutex);
+ mutex_lock(&rt2x00dev->csr_mutex);
/*
- * Wait until the BBP becomes ready.
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the new data into the register.
*/
- reg = rt2500usb_bbp_check(rt2x00dev);
- if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
- goto exit_fail;
-
- /*
- * Write the data into the BBP.
- */
- reg = 0;
- rt2x00_set_field16(&reg, PHY_CSR7_DATA, value);
- rt2x00_set_field16(&reg, PHY_CSR7_REG_ID, word);
- rt2x00_set_field16(&reg, PHY_CSR7_READ_CONTROL, 0);
-
- rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
-
- mutex_unlock(&rt2x00dev->usb_cache_mutex);
-
- return;
+ if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+ reg = 0;
+ rt2x00_set_field16(&reg, PHY_CSR7_DATA, value);
+ rt2x00_set_field16(&reg, PHY_CSR7_REG_ID, word);
+ rt2x00_set_field16(&reg, PHY_CSR7_READ_CONTROL, 0);
-exit_fail:
- mutex_unlock(&rt2x00dev->usb_cache_mutex);
+ rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
+ }
- ERROR(rt2x00dev, "PHY_CSR8 register busy. Write failed.\n");
+ mutex_unlock(&rt2x00dev->csr_mutex);
}
static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
@@ -166,122 +173,107 @@ static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev,
{
u16 reg;
- mutex_lock(&rt2x00dev->usb_cache_mutex);
+ mutex_lock(&rt2x00dev->csr_mutex);
/*
- * Wait until the BBP becomes ready.
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the read request into the register.
+ * After the data has been written, we wait until hardware
+ * returns the correct value, if at any time the register
+ * doesn't become available in time, reg will be 0xffffffff
+ * which means we return 0xff to the caller.
*/
- reg = rt2500usb_bbp_check(rt2x00dev);
- if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
- goto exit_fail;
-
- /*
- * Write the request into the BBP.
- */
- reg = 0;
- rt2x00_set_field16(&reg, PHY_CSR7_REG_ID, word);
- rt2x00_set_field16(&reg, PHY_CSR7_READ_CONTROL, 1);
+ if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+ reg = 0;
+ rt2x00_set_field16(&reg, PHY_CSR7_REG_ID, word);
+ rt2x00_set_field16(&reg, PHY_CSR7_READ_CONTROL, 1);
- rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
+ rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg);
- /*
- * Wait until the BBP becomes ready.
- */
- reg = rt2500usb_bbp_check(rt2x00dev);
- if (rt2x00_get_field16(reg, PHY_CSR8_BUSY))
- goto exit_fail;
+ if (WAIT_FOR_BBP(rt2x00dev, &reg))
+ rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, &reg);
+ }
- rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, &reg);
*value = rt2x00_get_field16(reg, PHY_CSR7_DATA);
- mutex_unlock(&rt2x00dev->usb_cache_mutex);
-
- return;
-
-exit_fail:
- mutex_unlock(&rt2x00dev->usb_cache_mutex);
-
- ERROR(rt2x00dev, "PHY_CSR8 register busy. Read failed.\n");
- *value = 0xff;
+ mutex_unlock(&rt2x00dev->csr_mutex);
}
static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u32 value)
{
u16 reg;
- unsigned int i;
if (!word)
return;
- mutex_lock(&rt2x00dev->usb_cache_mutex);
-
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2500usb_register_read_lock(rt2x00dev, PHY_CSR10, &reg);
- if (!rt2x00_get_field16(reg, PHY_CSR10_RF_BUSY))
- goto rf_write;
- udelay(REGISTER_BUSY_DELAY);
- }
+ mutex_lock(&rt2x00dev->csr_mutex);
- mutex_unlock(&rt2x00dev->usb_cache_mutex);
- ERROR(rt2x00dev, "PHY_CSR10 register busy. Write failed.\n");
- return;
-
-rf_write:
- reg = 0;
- rt2x00_set_field16(&reg, PHY_CSR9_RF_VALUE, value);
- rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg);
+ /*
+ * Wait until the RF becomes available, afterwards we
+ * can safely write the new data into the register.
+ */
+ if (WAIT_FOR_RF(rt2x00dev, &reg)) {
+ reg = 0;
+ rt2x00_set_field16(&reg, PHY_CSR9_RF_VALUE, value);
+ rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg);
- reg = 0;
- rt2x00_set_field16(&reg, PHY_CSR10_RF_VALUE, value >> 16);
- rt2x00_set_field16(&reg, PHY_CSR10_RF_NUMBER_OF_BITS, 20);
- rt2x00_set_field16(&reg, PHY_CSR10_RF_IF_SELECT, 0);
- rt2x00_set_field16(&reg, PHY_CSR10_RF_BUSY, 1);
+ reg = 0;
+ rt2x00_set_field16(&reg, PHY_CSR10_RF_VALUE, value >> 16);
+ rt2x00_set_field16(&reg, PHY_CSR10_RF_NUMBER_OF_BITS, 20);
+ rt2x00_set_field16(&reg, PHY_CSR10_RF_IF_SELECT, 0);
+ rt2x00_set_field16(&reg, PHY_CSR10_RF_BUSY, 1);
- rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg);
- rt2x00_rf_write(rt2x00dev, word, value);
+ rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg);
+ rt2x00_rf_write(rt2x00dev, word, value);
+ }
- mutex_unlock(&rt2x00dev->usb_cache_mutex);
+ mutex_unlock(&rt2x00dev->csr_mutex);
}
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-#define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u16)) )
-
-static void rt2500usb_read_csr(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u32 *data)
+static void _rt2500usb_register_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ u32 *value)
{
- rt2500usb_register_read(rt2x00dev, CSR_OFFSET(word), (u16 *) data);
+ rt2500usb_register_read(rt2x00dev, offset, (u16 *)value);
}
-static void rt2500usb_write_csr(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u32 data)
+static void _rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ u32 value)
{
- rt2500usb_register_write(rt2x00dev, CSR_OFFSET(word), data);
+ rt2500usb_register_write(rt2x00dev, offset, value);
}
static const struct rt2x00debug rt2500usb_rt2x00debug = {
.owner = THIS_MODULE,
.csr = {
- .read = rt2500usb_read_csr,
- .write = rt2500usb_write_csr,
+ .read = _rt2500usb_register_read,
+ .write = _rt2500usb_register_write,
+ .flags = RT2X00DEBUGFS_OFFSET,
+ .word_base = CSR_REG_BASE,
.word_size = sizeof(u16),
.word_count = CSR_REG_SIZE / sizeof(u16),
},
.eeprom = {
.read = rt2x00_eeprom_read,
.write = rt2x00_eeprom_write,
+ .word_base = EEPROM_BASE,
.word_size = sizeof(u16),
.word_count = EEPROM_SIZE / sizeof(u16),
},
.bbp = {
.read = rt2500usb_bbp_read,
.write = rt2500usb_bbp_write,
+ .word_base = BBP_BASE,
.word_size = sizeof(u8),
.word_count = BBP_SIZE / sizeof(u8),
},
.rf = {
.read = rt2x00_rf_read,
.write = rt2500usb_rf_write,
+ .word_base = RF_BASE,
.word_size = sizeof(u32),
.word_count = RF_SIZE / sizeof(u32),
},
@@ -338,6 +330,82 @@ static void rt2500usb_init_led(struct rt2x00_dev *rt2x00dev,
/*
* Configuration handlers.
*/
+
+/*
+ * rt2500usb does not differentiate between shared and pairwise
+ * keys, so we should use the same function for both key types.
+ */
+static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_crypto *crypto,
+ struct ieee80211_key_conf *key)
+{
+ int timeout;
+ u32 mask;
+ u16 reg;
+
+ if (crypto->cmd == SET_KEY) {
+ /*
+ * Pairwise key will always be entry 0, but this
+ * could collide with a shared key on the same
+ * position...
+ */
+ mask = TXRX_CSR0_KEY_ID.bit_mask;
+
+ rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ reg &= mask;
+
+ if (reg && reg == mask)
+ return -ENOSPC;
+
+ reg = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID);
+
+ key->hw_key_idx += reg ? ffz(reg) : 0;
+
+ /*
+ * The encryption key doesn't fit within the CSR cache,
+ * this means we should allocate it seperately and use
+ * rt2x00usb_vendor_request() to send the key to the hardware.
+ */
+ reg = KEY_ENTRY(key->hw_key_idx);
+ timeout = REGISTER_TIMEOUT32(sizeof(crypto->key));
+ rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE,
+ USB_VENDOR_REQUEST_OUT, reg,
+ crypto->key,
+ sizeof(crypto->key),
+ timeout);
+
+ /*
+ * The driver does not support the IV/EIV generation
+ * in hardware. However it doesn't support the IV/EIV
+ * inside the ieee80211 frame either, but requires it
+ * to be provided seperately for the descriptor.
+ * rt2x00lib will cut the IV/EIV data out of all frames
+ * given to us by mac80211, but we must tell mac80211
+ * to generate the IV/EIV data.
+ */
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+ }
+
+ /*
+ * TXRX_CSR0_KEY_ID contains only single-bit fields to indicate
+ * a particular key is valid.
+ */
+ rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ rt2x00_set_field16(&reg, TXRX_CSR0_ALGORITHM, crypto->cipher);
+ rt2x00_set_field16(&reg, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER);
+
+ mask = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID);
+ if (crypto->cmd == SET_KEY)
+ mask |= 1 << key->hw_key_idx;
+ else if (crypto->cmd == DISABLE_KEY)
+ mask &= ~(1 << key->hw_key_idx);
+ rt2x00_set_field16(&reg, TXRX_CSR0_KEY_ID, mask);
+ rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+
+ return 0;
+}
+
static void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev,
const unsigned int filter_flags)
{
@@ -380,7 +448,7 @@ static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev,
/*
* Enable beacon config
*/
- bcn_preload = PREAMBLE + get_duration(IEEE80211_HEADER, 20);
+ bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20);
rt2500usb_register_read(rt2x00dev, TXRX_CSR20, &reg);
rt2x00_set_field16(&reg, TXRX_CSR20_OFFSET, bcn_preload >> 6);
rt2x00_set_field16(&reg, TXRX_CSR20_BCN_EXPECT_WINDOW,
@@ -423,57 +491,16 @@ static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field16(&reg, TXRX_CSR10_AUTORESPOND_PREAMBLE,
!!erp->short_preamble);
rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg);
-}
-
-static void rt2500usb_config_phymode(struct rt2x00_dev *rt2x00dev,
- const int basic_rate_mask)
-{
- rt2500usb_register_write(rt2x00dev, TXRX_CSR11, basic_rate_mask);
-}
-
-static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev,
- struct rf_channel *rf, const int txpower)
-{
- /*
- * Set TXpower.
- */
- rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
-
- /*
- * For RT2525E we should first set the channel to half band higher.
- */
- if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) {
- static const u32 vals[] = {
- 0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2,
- 0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba,
- 0x000008ba, 0x000008be, 0x000008b7, 0x00000902,
- 0x00000902, 0x00000906
- };
-
- rt2500usb_rf_write(rt2x00dev, 2, vals[rf->channel - 1]);
- if (rf->rf4)
- rt2500usb_rf_write(rt2x00dev, 4, rf->rf4);
- }
-
- rt2500usb_rf_write(rt2x00dev, 1, rf->rf1);
- rt2500usb_rf_write(rt2x00dev, 2, rf->rf2);
- rt2500usb_rf_write(rt2x00dev, 3, rf->rf3);
- if (rf->rf4)
- rt2500usb_rf_write(rt2x00dev, 4, rf->rf4);
-}
-static void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev,
- const int txpower)
-{
- u32 rf3;
+ rt2500usb_register_write(rt2x00dev, TXRX_CSR11, erp->basic_rates);
- rt2x00_rf_read(rt2x00dev, 3, &rf3);
- rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
- rt2500usb_rf_write(rt2x00dev, 3, rf3);
+ rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time);
+ rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs);
+ rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs);
}
-static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev,
- struct antenna_setup *ant)
+static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev,
+ struct antenna_setup *ant)
{
u8 r2;
u8 r14;
@@ -555,15 +582,52 @@ static void rt2500usb_config_antenna(struct rt2x00_dev *rt2x00dev,
rt2500usb_register_write(rt2x00dev, PHY_CSR6, csr6);
}
+static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev,
+ struct rf_channel *rf, const int txpower)
+{
+ /*
+ * Set TXpower.
+ */
+ rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
+
+ /*
+ * For RT2525E we should first set the channel to half band higher.
+ */
+ if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) {
+ static const u32 vals[] = {
+ 0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2,
+ 0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba,
+ 0x000008ba, 0x000008be, 0x000008b7, 0x00000902,
+ 0x00000902, 0x00000906
+ };
+
+ rt2500usb_rf_write(rt2x00dev, 2, vals[rf->channel - 1]);
+ if (rf->rf4)
+ rt2500usb_rf_write(rt2x00dev, 4, rf->rf4);
+ }
+
+ rt2500usb_rf_write(rt2x00dev, 1, rf->rf1);
+ rt2500usb_rf_write(rt2x00dev, 2, rf->rf2);
+ rt2500usb_rf_write(rt2x00dev, 3, rf->rf3);
+ if (rf->rf4)
+ rt2500usb_rf_write(rt2x00dev, 4, rf->rf4);
+}
+
+static void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev,
+ const int txpower)
+{
+ u32 rf3;
+
+ rt2x00_rf_read(rt2x00dev, 3, &rf3);
+ rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
+ rt2500usb_rf_write(rt2x00dev, 3, rf3);
+}
+
static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf)
{
u16 reg;
- rt2500usb_register_write(rt2x00dev, MAC_CSR10, libconf->slot_time);
- rt2500usb_register_write(rt2x00dev, MAC_CSR11, libconf->sifs);
- rt2500usb_register_write(rt2x00dev, MAC_CSR12, libconf->eifs);
-
rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL,
libconf->conf->beacon_int * 4);
@@ -574,17 +638,14 @@ static void rt2500usb_config(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf,
const unsigned int flags)
{
- if (flags & CONFIG_UPDATE_PHYMODE)
- rt2500usb_config_phymode(rt2x00dev, libconf->basic_rates);
- if (flags & CONFIG_UPDATE_CHANNEL)
+ if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
rt2500usb_config_channel(rt2x00dev, &libconf->rf,
libconf->conf->power_level);
- if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL))
+ if ((flags & IEEE80211_CONF_CHANGE_POWER) &&
+ !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
rt2500usb_config_txpower(rt2x00dev,
libconf->conf->power_level);
- if (flags & CONFIG_UPDATE_ANTENNA)
- rt2500usb_config_antenna(rt2x00dev, &libconf->ant);
- if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
+ if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
rt2500usb_config_duration(rt2x00dev, libconf);
}
@@ -866,7 +927,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev)
rt2500usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field16(&reg, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER);
- rt2x00_set_field16(&reg, TXRX_CSR0_KEY_ID, 0xff);
+ rt2x00_set_field16(&reg, TXRX_CSR0_KEY_ID, 0);
rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg);
rt2500usb_register_read(rt2x00dev, MAC_CSR18, &reg);
@@ -1088,7 +1149,7 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
* Start writing the descriptor words.
*/
rt2x00_desc_read(txd, 1, &word);
- rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, IEEE80211_HEADER);
+ rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset);
rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs);
rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min);
rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max);
@@ -1101,6 +1162,11 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
rt2x00_desc_write(txd, 2, word);
+ if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
+ _rt2x00_desc_write(txd, 3, skbdesc->iv[0]);
+ _rt2x00_desc_write(txd, 4, skbdesc->iv[1]);
+ }
+
rt2x00_desc_read(txd, 0, &word);
rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, txdesc->retry_limit);
rt2x00_set_field32(&word, TXD_W0_MORE_FRAG,
@@ -1115,7 +1181,8 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags));
rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len);
- rt2x00_set_field32(&word, TXD_W0_CIPHER, CIPHER_NONE);
+ rt2x00_set_field32(&word, TXD_W0_CIPHER, txdesc->cipher);
+ rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx);
rt2x00_desc_write(txd, 0, word);
}
@@ -1130,7 +1197,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry)
struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
- int pipe = usb_sndbulkpipe(usb_dev, 1);
+ int pipe = usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint);
int length;
u16 reg;
@@ -1156,7 +1223,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry)
* length of the data to usb_fill_bulk_urb. Pass the skb
* to the driver to determine what the length should be.
*/
- length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, entry->skb);
+ length = rt2x00dev->ops->lib->get_tx_data_len(entry);
usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe,
entry->skb->data, length, rt2500usb_beacondone,
@@ -1178,8 +1245,7 @@ static void rt2500usb_write_beacon(struct queue_entry *entry)
usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC);
}
-static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
- struct sk_buff *skb)
+static int rt2500usb_get_tx_data_len(struct queue_entry *entry)
{
int length;
@@ -1187,8 +1253,8 @@ static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
* The length _must_ be a multiple of 2,
* but it must _not_ be a multiple of the USB packet size.
*/
- length = roundup(skb->len, 2);
- length += (2 * !(length % rt2x00dev->usb_maxpacket));
+ length = roundup(entry->skb->len, 2);
+ length += (2 * !(length % entry->queue->usb_maxpacket));
return length;
}
@@ -1227,6 +1293,7 @@ static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
static void rt2500usb_fill_rxdone(struct queue_entry *entry,
struct rxdone_entry_desc *rxdesc)
{
+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct queue_entry_priv_usb *entry_priv = entry->priv_data;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
__le32 *rxd =
@@ -1254,6 +1321,33 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry,
if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR))
rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC;
+ if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
+ rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER);
+ if (rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR))
+ rxdesc->cipher_status = RX_CRYPTO_FAIL_KEY;
+ }
+
+ if (rxdesc->cipher != CIPHER_NONE) {
+ _rt2x00_desc_read(rxd, 2, &rxdesc->iv[0]);
+ _rt2x00_desc_read(rxd, 3, &rxdesc->iv[1]);
+ rxdesc->dev_flags |= RXDONE_CRYPTO_IV;
+
+ /* ICV is located at the end of frame */
+
+ /*
+ * Hardware has stripped IV/EIV data from 802.11 frame during
+ * decryption. It has provided the data seperately but rt2x00lib
+ * should decide if it should be reinserted.
+ */
+ rxdesc->flags |= RX_FLAG_IV_STRIPPED;
+ if (rxdesc->cipher != CIPHER_TKIP)
+ rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
+ if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS)
+ rxdesc->flags |= RX_FLAG_DECRYPTED;
+ else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC)
+ rxdesc->flags |= RX_FLAG_MMIC_ERROR;
+ }
+
/*
* Obtain the status about this packet.
* When frame was received with an OFDM bitrate,
@@ -1261,8 +1355,8 @@ static void rt2500usb_fill_rxdone(struct queue_entry *entry,
* a CCK bitrate the signal is the rate in 100kbit/s.
*/
rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL);
- rxdesc->rssi = rt2x00_get_field32(word1, RXD_W1_RSSI) -
- entry->queue->rt2x00dev->rssi_offset;
+ rxdesc->rssi =
+ rt2x00_get_field32(word1, RXD_W1_RSSI) - rt2x00dev->rssi_offset;
rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT);
if (rt2x00_get_field32(word0, RXD_W0_OFDM))
@@ -1319,10 +1413,8 @@ static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
*/
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
if (!is_valid_ether_addr(mac)) {
- DECLARE_MAC_BUF(macbuf);
-
random_ether_addr(mac);
- EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac));
+ EEPROM(rt2x00dev, "MAC: %pM\n", mac);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
@@ -1752,6 +1844,10 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags);
__set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags);
+ if (!modparam_nohwcrypt) {
+ __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
+ __set_bit(CONFIG_CRYPTO_COPY_IV, &rt2x00dev->flags);
+ }
__set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags);
/*
@@ -1771,6 +1867,7 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
.config = rt2x00mac_config,
.config_interface = rt2x00mac_config_interface,
.configure_filter = rt2x00mac_configure_filter,
+ .set_key = rt2x00mac_set_key,
.get_stats = rt2x00mac_get_stats,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt2x00mac_conf_tx,
@@ -1781,8 +1878,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
.probe_hw = rt2500usb_probe_hw,
.initialize = rt2x00usb_initialize,
.uninitialize = rt2x00usb_uninitialize,
- .init_rxentry = rt2x00usb_init_rxentry,
- .init_txentry = rt2x00usb_init_txentry,
+ .clear_entry = rt2x00usb_clear_entry,
.set_device_state = rt2500usb_set_device_state,
.link_stats = rt2500usb_link_stats,
.reset_tuner = rt2500usb_reset_tuner,
@@ -1793,9 +1889,12 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
.get_tx_data_len = rt2500usb_get_tx_data_len,
.kick_tx_queue = rt2500usb_kick_tx_queue,
.fill_rxdone = rt2500usb_fill_rxdone,
+ .config_shared_key = rt2500usb_config_key,
+ .config_pairwise_key = rt2500usb_config_key,
.config_filter = rt2500usb_config_filter,
.config_intf = rt2500usb_config_intf,
.config_erp = rt2500usb_config_erp,
+ .config_ant = rt2500usb_config_ant,
.config = rt2500usb_config,
};
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h
index 89e5ed24e4f7..4347dfdabcd4 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.h
+++ b/drivers/net/wireless/rt2x00/rt2500usb.h
@@ -57,7 +57,9 @@
#define CSR_REG_SIZE 0x0100
#define EEPROM_BASE 0x0000
#define EEPROM_SIZE 0x006a
+#define BBP_BASE 0x0000
#define BBP_SIZE 0x0060
+#define RF_BASE 0x0000
#define RF_SIZE 0x0014
/*
@@ -445,6 +447,9 @@
#define SEC_CSR30 0x04bc
#define SEC_CSR31 0x04be
+#define KEY_ENTRY(__idx) \
+ ( SEC_CSR0 + ((__idx) * 16) )
+
/*
* PHY control registers.
*/
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 1359a3768404..39ecf3b82ca1 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -44,7 +44,7 @@
/*
* Module information.
*/
-#define DRV_VERSION "2.2.1"
+#define DRV_VERSION "2.2.3"
#define DRV_PROJECT "http://rt2x00.serialmonkey.com"
/*
@@ -92,6 +92,16 @@
DEBUG_PRINTK(__dev, KERN_DEBUG, "EEPROM recovery", __msg, ##__args)
/*
+ * Duration calculations
+ * The rate variable passed is: 100kbs.
+ * To convert from bytes to bits we multiply size with 8,
+ * then the size is multiplied with 10 to make the
+ * real rate -> rate argument correction.
+ */
+#define GET_DURATION(__size, __rate) (((__size) * 8 * 10) / (__rate))
+#define GET_DURATION_RES(__size, __rate)(((__size) * 8 * 10) % (__rate))
+
+/*
* Standard timing and size defines.
* These values should follow the ieee80211 specifications.
*/
@@ -109,9 +119,9 @@
#define DIFS ( PIFS + SLOT_TIME )
#define SHORT_DIFS ( SHORT_PIFS + SHORT_SLOT_TIME )
#define EIFS ( SIFS + DIFS + \
- (8 * (IEEE80211_HEADER + ACK_SIZE)) )
+ GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) )
#define SHORT_EIFS ( SIFS + SHORT_DIFS + \
- (8 * (IEEE80211_HEADER + ACK_SIZE)) )
+ GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) )
/*
* Chipset identification
@@ -348,13 +358,6 @@ struct rt2x00_intf {
spinlock_t lock;
/*
- * BSS configuration. Copied from the structure
- * passed to us through the bss_info_changed()
- * callback funtion.
- */
- struct ieee80211_bss_conf conf;
-
- /*
* MAC of the device.
*/
u8 mac[ETH_ALEN];
@@ -433,18 +436,6 @@ struct rt2x00lib_conf {
struct rf_channel rf;
struct channel_info channel;
-
- struct antenna_setup ant;
-
- enum ieee80211_band band;
-
- u32 basic_rates;
- u32 slot_time;
-
- short sifs;
- short pifs;
- short difs;
- short eifs;
};
/*
@@ -456,6 +447,15 @@ struct rt2x00lib_erp {
int ack_timeout;
int ack_consume_time;
+
+ u64 basic_rates;
+
+ int slot_time;
+
+ short sifs;
+ short pifs;
+ short difs;
+ short eifs;
};
/*
@@ -533,10 +533,8 @@ struct rt2x00lib_ops {
/*
* queue initialization handlers
*/
- void (*init_rxentry) (struct rt2x00_dev *rt2x00dev,
- struct queue_entry *entry);
- void (*init_txentry) (struct rt2x00_dev *rt2x00dev,
- struct queue_entry *entry);
+ bool (*get_entry_state) (struct queue_entry *entry);
+ void (*clear_entry) (struct queue_entry *entry);
/*
* Radio control handlers.
@@ -557,8 +555,7 @@ struct rt2x00lib_ops {
struct txentry_desc *txdesc);
int (*write_tx_data) (struct queue_entry *entry);
void (*write_beacon) (struct queue_entry *entry);
- int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev,
- struct sk_buff *skb);
+ int (*get_tx_data_len) (struct queue_entry *entry);
void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev,
const enum data_queue_qid queue);
@@ -589,16 +586,11 @@ struct rt2x00lib_ops {
void (*config_erp) (struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_erp *erp);
+ void (*config_ant) (struct rt2x00_dev *rt2x00dev,
+ struct antenna_setup *ant);
void (*config) (struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf,
- const unsigned int flags);
-#define CONFIG_UPDATE_PHYMODE ( 1 << 1 )
-#define CONFIG_UPDATE_CHANNEL ( 1 << 2 )
-#define CONFIG_UPDATE_TXPOWER ( 1 << 3 )
-#define CONFIG_UPDATE_ANTENNA ( 1 << 4 )
-#define CONFIG_UPDATE_SLOT_TIME ( 1 << 5 )
-#define CONFIG_UPDATE_BEACON_INT ( 1 << 6 )
-#define CONFIG_UPDATE_ALL 0xffff
+ const unsigned int changed_flags);
};
/*
@@ -661,6 +653,7 @@ enum rt2x00_flags {
CONFIG_EXTERNAL_LNA_BG,
CONFIG_DOUBLE_ANTENNA,
CONFIG_DISABLE_LINK_TUNING,
+ CONFIG_CRYPTO_COPY_IV,
};
/*
@@ -738,8 +731,7 @@ struct rt2x00_dev {
/*
* This is the default TX/RX antenna setup as indicated
- * by the device's EEPROM. When mac80211 sets its
- * antenna value to 0 we should be using these values.
+ * by the device's EEPROM.
*/
struct antenna_setup default_ant;
@@ -754,16 +746,15 @@ struct rt2x00_dev {
} csr;
/*
- * Mutex to protect register accesses on USB devices.
- * There are 2 reasons this is needed, one is to ensure
- * use of the csr_cache (for USB devices) by one thread
- * isn't corrupted by another thread trying to access it.
- * The other is that access to BBP and RF registers
- * require multiple BUS transactions and if another thread
- * attempted to access one of those registers at the same
- * time one of the writes could silently fail.
+ * Mutex to protect register accesses.
+ * For PCI and USB devices it protects against concurrent indirect
+ * register access (BBP, RF, MCU) since accessing those
+ * registers require multiple calls to the CSR registers.
+ * For USB devices it also protects the csr_cache since that
+ * field is used for normal CSR access and it cannot support
+ * multiple callers simultaneously.
*/
- struct mutex usb_cache_mutex;
+ struct mutex csr_mutex;
/*
* Current packet filter configuration for the device.
@@ -808,14 +799,15 @@ struct rt2x00_dev {
short lna_gain;
/*
- * USB Max frame size (for rt2500usb & rt73usb).
+ * Current TX power value.
*/
- u16 usb_maxpacket;
+ u16 tx_power;
/*
- * Current TX power value.
+ * Current retry values.
*/
- u16 tx_power;
+ u8 short_retry;
+ u8 long_retry;
/*
* Rssi <-> Dbm offset
@@ -938,23 +930,6 @@ static inline u16 rt2x00_check_rev(const struct rt2x00_chip *chipset,
!!(chipset->rev & 0x0000f));
}
-/*
- * Duration calculations
- * The rate variable passed is: 100kbs.
- * To convert from bytes to bits we multiply size with 8,
- * then the size is multiplied with 10 to make the
- * real rate -> rate argument correction.
- */
-static inline u16 get_duration(const unsigned int size, const u8 rate)
-{
- return ((size * 8 * 10) / rate);
-}
-
-static inline u16 get_duration_res(const unsigned int size, const u8 rate)
-{
- return ((size * 8 * 10) % rate);
-}
-
/**
* rt2x00queue_map_txskb - Map a skb into DMA for TX purposes.
* @rt2x00dev: Pointer to &struct rt2x00_dev.
@@ -997,7 +972,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf);
void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
struct ieee80211_if_init_conf *conf);
-int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
+int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed);
int rt2x00mac_config_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_if_conf *conf);
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index 4d5e87b015a0..e66fb316cd61 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -86,13 +86,14 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
erp.short_preamble = bss_conf->use_short_preamble;
erp.cts_protection = bss_conf->use_cts_prot;
- erp.ack_timeout = PLCP + get_duration(ACK_SIZE, 10);
- erp.ack_consume_time = SIFS + PLCP + get_duration(ACK_SIZE, 10);
+ erp.slot_time = bss_conf->use_short_slot ? SHORT_SLOT_TIME : SLOT_TIME;
+ erp.sifs = SIFS;
+ erp.pifs = bss_conf->use_short_slot ? SHORT_PIFS : PIFS;
+ erp.difs = bss_conf->use_short_slot ? SHORT_DIFS : DIFS;
+ erp.eifs = bss_conf->use_short_slot ? SHORT_EIFS : EIFS;
- if (rt2x00dev->hw->conf.flags & IEEE80211_CONF_SHORT_SLOT_TIME)
- erp.ack_timeout += SHORT_DIFS;
- else
- erp.ack_timeout += DIFS;
+ erp.ack_timeout = PLCP + erp.difs + GET_DURATION(ACK_SIZE, 10);
+ erp.ack_consume_time = SIFS + PLCP + GET_DURATION(ACK_SIZE, 10);
if (bss_conf->use_short_preamble) {
erp.ack_timeout += SHORT_PREAMBLE;
@@ -102,19 +103,39 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
erp.ack_consume_time += PREAMBLE;
}
+ erp.basic_rates = bss_conf->basic_rates;
+
rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp);
}
+static inline
+enum antenna rt2x00lib_config_antenna_check(enum antenna current_ant,
+ enum antenna default_ant)
+{
+ if (current_ant != ANTENNA_SW_DIVERSITY)
+ return current_ant;
+ return (default_ant != ANTENNA_SW_DIVERSITY) ? default_ant : ANTENNA_B;
+}
+
void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
- enum antenna rx, enum antenna tx)
+ struct antenna_setup *ant)
{
- struct rt2x00lib_conf libconf;
+ struct antenna_setup *def = &rt2x00dev->default_ant;
+ struct antenna_setup *active = &rt2x00dev->link.ant.active;
- libconf.ant.rx = rx;
- libconf.ant.tx = tx;
+ /*
+ * Failsafe: Make sure we are not sending the
+ * ANTENNA_SW_DIVERSITY state to the driver.
+ * If that happes fallback to hardware default,
+ * or our own default.
+ * The calls to rt2x00lib_config_antenna_check()
+ * might have caused that we restore back to the already
+ * active setting. If that has happened we can quit.
+ */
+ ant->rx = rt2x00lib_config_antenna_check(ant->rx, def->rx);
+ ant->tx = rt2x00lib_config_antenna_check(ant->tx, def->tx);
- if (rx == rt2x00dev->link.ant.active.rx &&
- tx == rt2x00dev->link.ant.active.tx)
+ if (ant->rx == active->rx && ant->tx == active->tx)
return;
/*
@@ -129,119 +150,28 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
* The latter is required since we need to recalibrate the
* noise-sensitivity ratio for the new setup.
*/
- rt2x00dev->ops->lib->config(rt2x00dev, &libconf, CONFIG_UPDATE_ANTENNA);
+ rt2x00dev->ops->lib->config_ant(rt2x00dev, ant);
+
rt2x00lib_reset_link_tuner(rt2x00dev);
rt2x00_reset_link_ant_rssi(&rt2x00dev->link);
- rt2x00dev->link.ant.active.rx = libconf.ant.rx;
- rt2x00dev->link.ant.active.tx = libconf.ant.tx;
+ memcpy(active, ant, sizeof(*ant));
if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK);
}
-static u32 rt2x00lib_get_basic_rates(struct ieee80211_supported_band *band)
-{
- const struct rt2x00_rate *rate;
- unsigned int i;
- u32 mask = 0;
-
- for (i = 0; i < band->n_bitrates; i++) {
- rate = rt2x00_get_rate(band->bitrates[i].hw_value);
- if (rate->flags & DEV_RATE_BASIC)
- mask |= rate->ratemask;
- }
-
- return mask;
-}
-
void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
- struct ieee80211_conf *conf, const int force_config)
+ struct ieee80211_conf *conf,
+ unsigned int ieee80211_flags)
{
struct rt2x00lib_conf libconf;
- struct ieee80211_supported_band *band;
- struct antenna_setup *default_ant = &rt2x00dev->default_ant;
- struct antenna_setup *active_ant = &rt2x00dev->link.ant.active;
- int flags = 0;
- int short_slot_time;
-
- /*
- * In some situations we want to force all configurations
- * to be reloaded (When resuming for instance).
- */
- if (force_config) {
- flags = CONFIG_UPDATE_ALL;
- goto config;
- }
- /*
- * Check which configuration options have been
- * updated and should be send to the device.
- */
- if (rt2x00dev->rx_status.band != conf->channel->band)
- flags |= CONFIG_UPDATE_PHYMODE;
- if (rt2x00dev->rx_status.freq != conf->channel->center_freq)
- flags |= CONFIG_UPDATE_CHANNEL;
- if (rt2x00dev->tx_power != conf->power_level)
- flags |= CONFIG_UPDATE_TXPOWER;
-
- /*
- * Determining changes in the antenna setups request several checks:
- * antenna_sel_{r,t}x = 0
- * -> Does active_{r,t}x match default_{r,t}x
- * -> Is default_{r,t}x SW_DIVERSITY
- * antenna_sel_{r,t}x = 1/2
- * -> Does active_{r,t}x match antenna_sel_{r,t}x
- * The reason for not updating the antenna while SW diversity
- * should be used is simple: Software diversity means that
- * we should switch between the antenna's based on the
- * quality. This means that the current antenna is good enough
- * to work with untill the link tuner decides that an antenna
- * switch should be performed.
- */
- if (!conf->antenna_sel_rx &&
- default_ant->rx != ANTENNA_SW_DIVERSITY &&
- default_ant->rx != active_ant->rx)
- flags |= CONFIG_UPDATE_ANTENNA;
- else if (conf->antenna_sel_rx &&
- conf->antenna_sel_rx != active_ant->rx)
- flags |= CONFIG_UPDATE_ANTENNA;
- else if (active_ant->rx == ANTENNA_SW_DIVERSITY)
- flags |= CONFIG_UPDATE_ANTENNA;
-
- if (!conf->antenna_sel_tx &&
- default_ant->tx != ANTENNA_SW_DIVERSITY &&
- default_ant->tx != active_ant->tx)
- flags |= CONFIG_UPDATE_ANTENNA;
- else if (conf->antenna_sel_tx &&
- conf->antenna_sel_tx != active_ant->tx)
- flags |= CONFIG_UPDATE_ANTENNA;
- else if (active_ant->tx == ANTENNA_SW_DIVERSITY)
- flags |= CONFIG_UPDATE_ANTENNA;
-
- /*
- * The following configuration options are never
- * stored anywhere and will always be updated.
- */
- flags |= CONFIG_UPDATE_SLOT_TIME;
- flags |= CONFIG_UPDATE_BEACON_INT;
-
- /*
- * We have determined what options should be updated,
- * now precalculate device configuration values depending
- * on what configuration options need to be updated.
- */
-config:
memset(&libconf, 0, sizeof(libconf));
- if (flags & CONFIG_UPDATE_PHYMODE) {
- band = &rt2x00dev->bands[conf->channel->band];
-
- libconf.band = conf->channel->band;
- libconf.basic_rates = rt2x00lib_get_basic_rates(band);
- }
+ libconf.conf = conf;
- if (flags & CONFIG_UPDATE_CHANNEL) {
+ if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) {
memcpy(&libconf.rf,
&rt2x00dev->spec.channels[conf->channel->hw_value],
sizeof(libconf.rf));
@@ -251,61 +181,23 @@ config:
sizeof(libconf.channel));
}
- if (flags & CONFIG_UPDATE_ANTENNA) {
- if (conf->antenna_sel_rx)
- libconf.ant.rx = conf->antenna_sel_rx;
- else if (default_ant->rx != ANTENNA_SW_DIVERSITY)
- libconf.ant.rx = default_ant->rx;
- else if (active_ant->rx == ANTENNA_SW_DIVERSITY)
- libconf.ant.rx = ANTENNA_B;
- else
- libconf.ant.rx = active_ant->rx;
-
- if (conf->antenna_sel_tx)
- libconf.ant.tx = conf->antenna_sel_tx;
- else if (default_ant->tx != ANTENNA_SW_DIVERSITY)
- libconf.ant.tx = default_ant->tx;
- else if (active_ant->tx == ANTENNA_SW_DIVERSITY)
- libconf.ant.tx = ANTENNA_B;
- else
- libconf.ant.tx = active_ant->tx;
- }
-
- if (flags & CONFIG_UPDATE_SLOT_TIME) {
- short_slot_time = conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME;
-
- libconf.slot_time =
- short_slot_time ? SHORT_SLOT_TIME : SLOT_TIME;
- libconf.sifs = SIFS;
- libconf.pifs = short_slot_time ? SHORT_PIFS : PIFS;
- libconf.difs = short_slot_time ? SHORT_DIFS : DIFS;
- libconf.eifs = short_slot_time ? SHORT_EIFS : EIFS;
- }
-
- libconf.conf = conf;
-
/*
* Start configuration.
*/
- rt2x00dev->ops->lib->config(rt2x00dev, &libconf, flags);
+ rt2x00dev->ops->lib->config(rt2x00dev, &libconf, ieee80211_flags);
/*
* Some configuration changes affect the link quality
* which means we need to reset the link tuner.
*/
- if (flags & (CONFIG_UPDATE_CHANNEL | CONFIG_UPDATE_ANTENNA))
+ if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL)
rt2x00lib_reset_link_tuner(rt2x00dev);
- if (flags & CONFIG_UPDATE_PHYMODE) {
- rt2x00dev->curr_band = conf->channel->band;
- rt2x00dev->rx_status.band = conf->channel->band;
- }
-
- rt2x00dev->rx_status.freq = conf->channel->center_freq;
+ rt2x00dev->curr_band = conf->channel->band;
rt2x00dev->tx_power = conf->power_level;
+ rt2x00dev->short_retry = conf->short_frame_max_tx_count;
+ rt2x00dev->long_retry = conf->long_frame_max_tx_count;
- if (flags & CONFIG_UPDATE_ANTENNA) {
- rt2x00dev->link.ant.active.rx = libconf.ant.rx;
- rt2x00dev->link.ant.active.tx = libconf.ant.tx;
- }
+ rt2x00dev->rx_status.band = conf->channel->band;
+ rt2x00dev->rx_status.freq = conf->channel->center_freq;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index 5a858e5106c4..37ad0d2fb64c 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -46,6 +46,29 @@ enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key)
}
}
+void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
+ struct txentry_desc *txdesc)
+{
+ struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+ struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
+
+ __set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags);
+
+ txdesc->cipher = rt2x00crypto_key_to_cipher(hw_key);
+
+ if (hw_key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
+ __set_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags);
+
+ txdesc->key_idx = hw_key->hw_key_idx;
+ txdesc->iv_offset = ieee80211_get_hdrlen_from_skb(entry->skb);
+
+ if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV))
+ __set_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags);
+
+ if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC))
+ __set_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags);
+}
+
unsigned int rt2x00crypto_tx_overhead(struct ieee80211_tx_info *tx_info)
{
struct ieee80211_key_conf *key = tx_info->control.hw_key;
@@ -69,6 +92,18 @@ unsigned int rt2x00crypto_tx_overhead(struct ieee80211_tx_info *tx_info)
return overhead;
}
+void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, unsigned int iv_len)
+{
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
+ unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb);
+
+ if (unlikely(!iv_len))
+ return;
+
+ /* Copy IV/EIV data */
+ memcpy(skbdesc->iv, skb->data + header_length, iv_len);
+}
+
void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, unsigned int iv_len)
{
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
@@ -78,10 +113,7 @@ void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, unsigned int iv_len)
return;
/* Copy IV/EIV data */
- if (iv_len >= 4)
- memcpy(&skbdesc->iv, skb->data + header_length, 4);
- if (iv_len >= 8)
- memcpy(&skbdesc->eiv, skb->data + header_length + 4, 4);
+ memcpy(skbdesc->iv, skb->data + header_length, iv_len);
/* Move ieee80211 header */
memmove(skb->data + iv_len, skb->data, header_length);
@@ -98,7 +130,7 @@ void rt2x00crypto_tx_insert_iv(struct sk_buff *skb)
struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
unsigned int header_length = ieee80211_get_hdrlen_from_skb(skb);
const unsigned int iv_len =
- ((!!(skbdesc->iv)) * 4) + ((!!(skbdesc->eiv)) * 4);
+ ((!!(skbdesc->iv[0])) * 4) + ((!!(skbdesc->iv[1])) * 4);
if (!(skbdesc->flags & FRAME_DESC_IV_STRIPPED))
return;
@@ -109,10 +141,7 @@ void rt2x00crypto_tx_insert_iv(struct sk_buff *skb)
memmove(skb->data, skb->data + iv_len, header_length);
/* Copy IV/EIV data */
- if (iv_len >= 4)
- memcpy(skb->data + header_length, &skbdesc->iv, 4);
- if (iv_len >= 8)
- memcpy(skb->data + header_length + 4, &skbdesc->eiv, 4);
+ memcpy(skb->data + header_length, skbdesc->iv, iv_len);
/* IV/EIV data has returned into the frame */
skbdesc->flags &= ~FRAME_DESC_IV_STRIPPED;
@@ -172,17 +201,9 @@ void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align,
header_length);
transfer += header_length;
- /* Copy IV data */
- if (iv_len >= 4) {
- memcpy(skb->data + transfer, &rxdesc->iv, 4);
- transfer += 4;
- }
-
- /* Copy EIV data */
- if (iv_len >= 8) {
- memcpy(skb->data + transfer, &rxdesc->eiv, 4);
- transfer += 4;
- }
+ /* Copy IV/EIV data */
+ memcpy(skb->data + transfer, rxdesc->iv, iv_len);
+ transfer += iv_len;
/* Move payload */
if (align) {
@@ -198,16 +219,14 @@ void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align,
*/
transfer += payload_len;
- /* Copy ICV data */
- if (icv_len >= 4) {
- memcpy(skb->data + transfer, &rxdesc->icv, 4);
- /*
- * AES appends 8 bytes, we can't fill the upper
- * 4 bytes, but mac80211 doesn't care about what
- * we provide here anyway and strips it immediately.
- */
- transfer += icv_len;
- }
+ /*
+ * Copy ICV data
+ * AES appends 8 bytes, we can't fill the upper
+ * 4 bytes, but mac80211 doesn't care about what
+ * we provide here anyway and strips it immediately.
+ */
+ memcpy(skb->data + transfer, &rxdesc->icv, 4);
+ transfer += icv_len;
/* IV/EIV/ICV has been inserted into frame */
rxdesc->size = transfer;
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c
index 5cf4c859e39d..54dd10060bf1 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.c
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.c
@@ -285,7 +285,7 @@ exit:
}
static unsigned int rt2x00debug_poll_queue_dump(struct file *file,
- poll_table *wait)
+ poll_table *wait)
{
struct rt2x00debug_intf *intf = file->private_data;
@@ -377,7 +377,7 @@ static ssize_t rt2x00debug_read_crypto_stats(struct file *file,
if (*offset)
return 0;
- data = kzalloc((1 + CIPHER_MAX)* MAX_LINE_LENGTH, GFP_KERNEL);
+ data = kzalloc((1 + CIPHER_MAX) * MAX_LINE_LENGTH, GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -424,16 +424,21 @@ static ssize_t rt2x00debug_read_##__name(struct file *file, \
const struct rt2x00debug *debug = intf->debug; \
char line[16]; \
size_t size; \
+ unsigned int index = intf->offset_##__name; \
__type value; \
\
if (*offset) \
return 0; \
\
- if (intf->offset_##__name >= debug->__name.word_count) \
+ if (index >= debug->__name.word_count) \
return -EINVAL; \
\
- debug->__name.read(intf->rt2x00dev, \
- intf->offset_##__name, &value); \
+ if (debug->__name.flags & RT2X00DEBUGFS_OFFSET) \
+ index *= debug->__name.word_size; \
+ \
+ index += debug->__name.word_base; \
+ \
+ debug->__name.read(intf->rt2x00dev, index, &value); \
\
size = sprintf(line, __format, value); \
\
@@ -454,12 +459,13 @@ static ssize_t rt2x00debug_write_##__name(struct file *file, \
const struct rt2x00debug *debug = intf->debug; \
char line[16]; \
size_t size; \
+ unsigned int index = intf->offset_##__name; \
__type value; \
\
if (*offset) \
return 0; \
\
- if (intf->offset_##__name >= debug->__name.word_count) \
+ if (index >= debug->__name.word_count) \
return -EINVAL; \
\
if (copy_from_user(line, buf, length)) \
@@ -468,8 +474,12 @@ static ssize_t rt2x00debug_write_##__name(struct file *file, \
size = strlen(line); \
value = simple_strtoul(line, NULL, 0); \
\
- debug->__name.write(intf->rt2x00dev, \
- intf->offset_##__name, value); \
+ if (debug->__name.flags & RT2X00DEBUGFS_OFFSET) \
+ index *= debug->__name.word_size; \
+ \
+ index += debug->__name.word_base; \
+ \
+ debug->__name.write(intf->rt2x00dev, index, value); \
\
*offset += size; \
return size; \
@@ -587,29 +597,29 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
intf->driver_folder =
debugfs_create_dir(intf->rt2x00dev->ops->name,
rt2x00dev->hw->wiphy->debugfsdir);
- if (IS_ERR(intf->driver_folder))
+ if (IS_ERR(intf->driver_folder) || !intf->driver_folder)
goto exit;
intf->driver_entry =
rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob);
- if (IS_ERR(intf->driver_entry))
+ if (IS_ERR(intf->driver_entry) || !intf->driver_entry)
goto exit;
intf->chipset_entry =
rt2x00debug_create_file_chipset("chipset",
intf, &intf->chipset_blob);
- if (IS_ERR(intf->chipset_entry))
+ if (IS_ERR(intf->chipset_entry) || !intf->chipset_entry)
goto exit;
intf->dev_flags = debugfs_create_file("dev_flags", S_IRUSR,
intf->driver_folder, intf,
&rt2x00debug_fop_dev_flags);
- if (IS_ERR(intf->dev_flags))
+ if (IS_ERR(intf->dev_flags) || !intf->dev_flags)
goto exit;
intf->register_folder =
debugfs_create_dir("register", intf->driver_folder);
- if (IS_ERR(intf->register_folder))
+ if (IS_ERR(intf->register_folder) || !intf->register_folder)
goto exit;
#define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name) \
@@ -619,7 +629,8 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
S_IRUSR | S_IWUSR, \
(__intf)->register_folder, \
&(__intf)->offset_##__name); \
- if (IS_ERR((__intf)->__name##_off_entry)) \
+ if (IS_ERR((__intf)->__name##_off_entry) \
+ || !(__intf)->__name##_off_entry) \
goto exit; \
\
(__intf)->__name##_val_entry = \
@@ -627,7 +638,8 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
S_IRUSR | S_IWUSR, \
(__intf)->register_folder, \
(__intf), &rt2x00debug_fop_##__name);\
- if (IS_ERR((__intf)->__name##_val_entry)) \
+ if (IS_ERR((__intf)->__name##_val_entry) \
+ || !(__intf)->__name##_val_entry) \
goto exit; \
})
@@ -640,13 +652,14 @@ void rt2x00debug_register(struct rt2x00_dev *rt2x00dev)
intf->queue_folder =
debugfs_create_dir("queue", intf->driver_folder);
- if (IS_ERR(intf->queue_folder))
+ if (IS_ERR(intf->queue_folder) || !intf->queue_folder)
goto exit;
intf->queue_frame_dump_entry =
debugfs_create_file("dump", S_IRUSR, intf->queue_folder,
intf, &rt2x00debug_fop_queue_dump);
- if (IS_ERR(intf->queue_frame_dump_entry))
+ if (IS_ERR(intf->queue_frame_dump_entry)
+ || !intf->queue_frame_dump_entry)
goto exit;
skb_queue_head_init(&intf->frame_dump_skbqueue);
diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.h b/drivers/net/wireless/rt2x00/rt2x00debug.h
index c4ce895aa1c7..a92104dfee9a 100644
--- a/drivers/net/wireless/rt2x00/rt2x00debug.h
+++ b/drivers/net/wireless/rt2x00/rt2x00debug.h
@@ -28,6 +28,16 @@
struct rt2x00_dev;
+/**
+ * enum rt2x00debugfs_entry_flags: Flags for debugfs registry entry
+ *
+ * @RT2X00DEBUGFS_OFFSET: rt2x00lib should pass the register offset
+ * as argument when using the callback function read()/write()
+ */
+enum rt2x00debugfs_entry_flags {
+ RT2X00DEBUGFS_OFFSET = (1 << 0),
+};
+
#define RT2X00DEBUGFS_REGISTER_ENTRY(__name, __type) \
struct reg##__name { \
void (*read)(struct rt2x00_dev *rt2x00dev, \
@@ -35,6 +45,9 @@ struct reg##__name { \
void (*write)(struct rt2x00_dev *rt2x00dev, \
const unsigned int word, __type data); \
\
+ unsigned int flags; \
+ \
+ unsigned int word_base; \
unsigned int word_size; \
unsigned int word_count; \
} __name
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 86840e3585e8..6d92542fcf0d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -101,8 +101,7 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
/*
* Initialize all data queues.
*/
- rt2x00queue_init_rx(rt2x00dev);
- rt2x00queue_init_tx(rt2x00dev);
+ rt2x00queue_init_queues(rt2x00dev);
/*
* Enable radio.
@@ -176,13 +175,14 @@ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state)
static void rt2x00lib_evaluate_antenna_sample(struct rt2x00_dev *rt2x00dev)
{
- enum antenna rx = rt2x00dev->link.ant.active.rx;
- enum antenna tx = rt2x00dev->link.ant.active.tx;
+ struct antenna_setup ant;
int sample_a =
rt2x00_get_link_ant_rssi_history(&rt2x00dev->link, ANTENNA_A);
int sample_b =
rt2x00_get_link_ant_rssi_history(&rt2x00dev->link, ANTENNA_B);
+ memcpy(&ant, &rt2x00dev->link.ant.active, sizeof(ant));
+
/*
* We are done sampling. Now we should evaluate the results.
*/
@@ -200,21 +200,22 @@ static void rt2x00lib_evaluate_antenna_sample(struct rt2x00_dev *rt2x00dev)
return;
if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY)
- rx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B;
+ ant.rx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B;
if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY)
- tx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B;
+ ant.tx = (sample_a > sample_b) ? ANTENNA_A : ANTENNA_B;
- rt2x00lib_config_antenna(rt2x00dev, rx, tx);
+ rt2x00lib_config_antenna(rt2x00dev, &ant);
}
static void rt2x00lib_evaluate_antenna_eval(struct rt2x00_dev *rt2x00dev)
{
- enum antenna rx = rt2x00dev->link.ant.active.rx;
- enum antenna tx = rt2x00dev->link.ant.active.tx;
+ struct antenna_setup ant;
int rssi_curr = rt2x00_get_link_ant_rssi(&rt2x00dev->link);
int rssi_old = rt2x00_update_ant_rssi(&rt2x00dev->link, rssi_curr);
+ memcpy(&ant, &rt2x00dev->link.ant.active, sizeof(ant));
+
/*
* Legacy driver indicates that we should swap antenna's
* when the difference in RSSI is greater that 5. This
@@ -230,12 +231,12 @@ static void rt2x00lib_evaluate_antenna_eval(struct rt2x00_dev *rt2x00dev)
rt2x00dev->link.ant.flags |= ANTENNA_MODE_SAMPLE;
if (rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY)
- rx = (rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
+ ant.rx = (ant.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
if (rt2x00dev->link.ant.flags & ANTENNA_TX_DIVERSITY)
- tx = (tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
+ ant.tx = (ant.tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A;
- rt2x00lib_config_antenna(rt2x00dev, rx, tx);
+ rt2x00lib_config_antenna(rt2x00dev, &ant);
}
static void rt2x00lib_evaluate_antenna(struct rt2x00_dev *rt2x00dev)
@@ -249,11 +250,9 @@ static void rt2x00lib_evaluate_antenna(struct rt2x00_dev *rt2x00dev)
rt2x00dev->link.ant.flags &= ~ANTENNA_RX_DIVERSITY;
rt2x00dev->link.ant.flags &= ~ANTENNA_TX_DIVERSITY;
- if (rt2x00dev->hw->conf.antenna_sel_rx == 0 &&
- rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
+ if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY)
rt2x00dev->link.ant.flags |= ANTENNA_RX_DIVERSITY;
- if (rt2x00dev->hw->conf.antenna_sel_tx == 0 &&
- rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
+ if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY)
rt2x00dev->link.ant.flags |= ANTENNA_TX_DIVERSITY;
if (!(rt2x00dev->link.ant.flags & ANTENNA_RX_DIVERSITY) &&
@@ -419,7 +418,7 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
*/
spin_lock(&intf->lock);
- memcpy(&conf, &intf->conf, sizeof(conf));
+ memcpy(&conf, &vif->bss_conf, sizeof(conf));
delayed_flags = intf->delayed_flags;
intf->delayed_flags = 0;
@@ -500,7 +499,9 @@ void rt2x00lib_txdone(struct queue_entry *entry,
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
enum data_queue_qid qid = skb_get_queue_mapping(entry->skb);
+ u8 rate_idx, rate_flags;
/*
* Unmap the skb.
@@ -530,14 +531,18 @@ void rt2x00lib_txdone(struct queue_entry *entry,
rt2x00dev->link.qual.tx_failed +=
test_bit(TXDONE_FAILURE, &txdesc->flags);
+ rate_idx = skbdesc->tx_rate_idx;
+ rate_flags = skbdesc->tx_rate_flags;
+
/*
* Initialize TX status
*/
memset(&tx_info->status, 0, sizeof(tx_info->status));
tx_info->status.ack_signal = 0;
- tx_info->status.excessive_retries =
- test_bit(TXDONE_EXCESSIVE_RETRY, &txdesc->flags);
- tx_info->status.retry_count = txdesc->retry;
+ tx_info->status.rates[0].idx = rate_idx;
+ tx_info->status.rates[0].flags = rate_flags;
+ tx_info->status.rates[0].count = txdesc->retry + 1;
+ tx_info->status.rates[1].idx = -1; /* terminate */
if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
if (test_bit(TXDONE_SUCCESS, &txdesc->flags))
@@ -546,7 +551,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
rt2x00dev->low_level_stats.dot11ACKFailureCount++;
}
- if (tx_info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
+ if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
if (test_bit(TXDONE_SUCCESS, &txdesc->flags))
rt2x00dev->low_level_stats.dot11RTSSuccessCount++;
else if (test_bit(TXDONE_FAILURE, &txdesc->flags))
@@ -570,7 +575,7 @@ void rt2x00lib_txdone(struct queue_entry *entry,
entry->skb = NULL;
entry->flags = 0;
- rt2x00dev->ops->lib->init_txentry(rt2x00dev, entry);
+ rt2x00dev->ops->lib->clear_entry(entry);
clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE);
@@ -631,7 +636,8 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
* provided seperately (through hardware descriptor)
* in which case we should reinsert the data into the frame.
*/
- if ((rxdesc.flags & RX_FLAG_IV_STRIPPED)) {
+ if ((rxdesc.dev_flags & RXDONE_CRYPTO_IV) &&
+ (rxdesc.flags & RX_FLAG_IV_STRIPPED)) {
rt2x00crypto_rx_insert_iv(entry->skb, align,
header_length, &rxdesc);
} else if (align) {
@@ -702,7 +708,7 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
entry->skb = skb;
entry->flags = 0;
- rt2x00dev->ops->lib->init_rxentry(rt2x00dev, entry);
+ rt2x00dev->ops->lib->clear_entry(entry);
rt2x00queue_index_inc(entry->queue, Q_INDEX);
}
@@ -713,31 +719,31 @@ EXPORT_SYMBOL_GPL(rt2x00lib_rxdone);
*/
const struct rt2x00_rate rt2x00_supported_rates[12] = {
{
- .flags = DEV_RATE_CCK | DEV_RATE_BASIC,
+ .flags = DEV_RATE_CCK,
.bitrate = 10,
.ratemask = BIT(0),
.plcp = 0x00,
},
{
- .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC,
+ .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE,
.bitrate = 20,
.ratemask = BIT(1),
.plcp = 0x01,
},
{
- .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC,
+ .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE,
.bitrate = 55,
.ratemask = BIT(2),
.plcp = 0x02,
},
{
- .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE | DEV_RATE_BASIC,
+ .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE,
.bitrate = 110,
.ratemask = BIT(3),
.plcp = 0x03,
},
{
- .flags = DEV_RATE_OFDM | DEV_RATE_BASIC,
+ .flags = DEV_RATE_OFDM,
.bitrate = 60,
.ratemask = BIT(4),
.plcp = 0x0b,
@@ -749,7 +755,7 @@ const struct rt2x00_rate rt2x00_supported_rates[12] = {
.plcp = 0x0f,
},
{
- .flags = DEV_RATE_OFDM | DEV_RATE_BASIC,
+ .flags = DEV_RATE_OFDM,
.bitrate = 120,
.ratemask = BIT(6),
.plcp = 0x0a,
@@ -761,7 +767,7 @@ const struct rt2x00_rate rt2x00_supported_rates[12] = {
.plcp = 0x0e,
},
{
- .flags = DEV_RATE_OFDM | DEV_RATE_BASIC,
+ .flags = DEV_RATE_OFDM,
.bitrate = 240,
.ratemask = BIT(8),
.plcp = 0x09,
@@ -1046,16 +1052,24 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
{
int retval = -ENOMEM;
+ mutex_init(&rt2x00dev->csr_mutex);
+
/*
* Make room for rt2x00_intf inside the per-interface
* structure ieee80211_vif.
*/
rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf);
- rt2x00dev->hw->wiphy->interface_modes =
- BIT(NL80211_IFTYPE_AP) |
- BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC);
+ /*
+ * Determine which operating modes are supported, all modes
+ * which require beaconing, depend on the availability of
+ * beacon entries.
+ */
+ rt2x00dev->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+ if (rt2x00dev->ops->bcn->entry_num > 0)
+ rt2x00dev->hw->wiphy->interface_modes |=
+ BIT(NL80211_IFTYPE_ADHOC) |
+ BIT(NL80211_IFTYPE_AP);
/*
* Let the driver probe the device to detect the capabilities.
@@ -1247,7 +1261,7 @@ int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev)
/*
* Reconfigure device.
*/
- retval = rt2x00mac_config(rt2x00dev->hw, &rt2x00dev->hw->conf);
+ retval = rt2x00mac_config(rt2x00dev->hw, ~0);
if (retval)
goto exit;
diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c
index b362a1cf3f8d..68f4e0fc35b9 100644
--- a/drivers/net/wireless/rt2x00/rt2x00leds.c
+++ b/drivers/net/wireless/rt2x00/rt2x00leds.c
@@ -72,49 +72,33 @@ void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi)
}
}
-void rt2x00led_led_activity(struct rt2x00_dev *rt2x00dev, bool enabled)
+static void rt2x00led_led_simple(struct rt2x00_led *led, bool enabled)
{
- struct rt2x00_led *led = &rt2x00dev->led_qual;
- unsigned int brightness;
+ unsigned int brightness = enabled ? LED_FULL : LED_OFF;
- if ((led->type != LED_TYPE_ACTIVITY) || !(led->flags & LED_REGISTERED))
+ if (!(led->flags & LED_REGISTERED))
return;
- brightness = enabled ? LED_FULL : LED_OFF;
- if (brightness != led->led_dev.brightness) {
- led->led_dev.brightness_set(&led->led_dev, brightness);
- led->led_dev.brightness = brightness;
- }
+ led->led_dev.brightness_set(&led->led_dev, brightness);
+ led->led_dev.brightness = brightness;
}
-void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled)
+void rt2x00led_led_activity(struct rt2x00_dev *rt2x00dev, bool enabled)
{
- struct rt2x00_led *led = &rt2x00dev->led_assoc;
- unsigned int brightness;
-
- if ((led->type != LED_TYPE_ASSOC) || !(led->flags & LED_REGISTERED))
- return;
+ if (rt2x00dev->led_qual.type == LED_TYPE_ACTIVITY)
+ rt2x00led_led_simple(&rt2x00dev->led_qual, enabled);
+}
- brightness = enabled ? LED_FULL : LED_OFF;
- if (brightness != led->led_dev.brightness) {
- led->led_dev.brightness_set(&led->led_dev, brightness);
- led->led_dev.brightness = brightness;
- }
+void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled)
+{
+ if (rt2x00dev->led_assoc.type == LED_TYPE_ASSOC)
+ rt2x00led_led_simple(&rt2x00dev->led_assoc, enabled);
}
void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled)
{
- struct rt2x00_led *led = &rt2x00dev->led_radio;
- unsigned int brightness;
-
- if ((led->type != LED_TYPE_RADIO) || !(led->flags & LED_REGISTERED))
- return;
-
- brightness = enabled ? LED_FULL : LED_OFF;
- if (brightness != led->led_dev.brightness) {
- led->led_dev.brightness_set(&led->led_dev, brightness);
- led->led_dev.brightness = brightness;
- }
+ if (rt2x00dev->led_radio.type == LED_TYPE_ASSOC)
+ rt2x00led_led_simple(&rt2x00dev->led_radio, enabled);
}
static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,
@@ -125,6 +109,7 @@ static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev,
int retval;
led->led_dev.name = name;
+ led->led_dev.brightness = LED_OFF;
retval = led_classdev_register(device, &led->led_dev);
if (retval) {
@@ -199,7 +184,16 @@ exit_fail:
static void rt2x00leds_unregister_led(struct rt2x00_led *led)
{
led_classdev_unregister(&led->led_dev);
- led->led_dev.brightness_set(&led->led_dev, LED_OFF);
+
+ /*
+ * This might look weird, but when we are unregistering while
+ * suspended the led is already off, and since we haven't
+ * fully resumed yet, access to the device might not be
+ * possible yet.
+ */
+ if (!(led->led_dev.flags & LED_SUSPENDED))
+ led->led_dev.brightness_set(&led->led_dev, LED_OFF);
+
led->flags &= ~LED_REGISTERED;
}
@@ -213,22 +207,40 @@ void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev)
rt2x00leds_unregister_led(&rt2x00dev->led_radio);
}
+static inline void rt2x00leds_suspend_led(struct rt2x00_led *led)
+{
+ led_classdev_suspend(&led->led_dev);
+
+ /* This shouldn't be needed, but just to be safe */
+ led->led_dev.brightness_set(&led->led_dev, LED_OFF);
+ led->led_dev.brightness = LED_OFF;
+}
+
void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev)
{
if (rt2x00dev->led_qual.flags & LED_REGISTERED)
- led_classdev_suspend(&rt2x00dev->led_qual.led_dev);
+ rt2x00leds_suspend_led(&rt2x00dev->led_qual);
if (rt2x00dev->led_assoc.flags & LED_REGISTERED)
- led_classdev_suspend(&rt2x00dev->led_assoc.led_dev);
+ rt2x00leds_suspend_led(&rt2x00dev->led_assoc);
if (rt2x00dev->led_radio.flags & LED_REGISTERED)
- led_classdev_suspend(&rt2x00dev->led_radio.led_dev);
+ rt2x00leds_suspend_led(&rt2x00dev->led_radio);
+}
+
+static inline void rt2x00leds_resume_led(struct rt2x00_led *led)
+{
+ led_classdev_resume(&led->led_dev);
+
+ /* Device might have enabled the LEDS during resume */
+ led->led_dev.brightness_set(&led->led_dev, LED_OFF);
+ led->led_dev.brightness = LED_OFF;
}
void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev)
{
if (rt2x00dev->led_radio.flags & LED_REGISTERED)
- led_classdev_resume(&rt2x00dev->led_radio.led_dev);
+ rt2x00leds_resume_led(&rt2x00dev->led_radio);
if (rt2x00dev->led_assoc.flags & LED_REGISTERED)
- led_classdev_resume(&rt2x00dev->led_assoc.led_dev);
+ rt2x00leds_resume_led(&rt2x00dev->led_assoc);
if (rt2x00dev->led_qual.flags & LED_REGISTERED)
- led_classdev_resume(&rt2x00dev->led_qual.led_dev);
+ rt2x00leds_resume_led(&rt2x00dev->led_qual);
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 797eb619aa0a..03024327767b 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -43,7 +43,6 @@ struct rt2x00_rate {
#define DEV_RATE_CCK 0x0001
#define DEV_RATE_OFDM 0x0002
#define DEV_RATE_SHORT_PREAMBLE 0x0004
-#define DEV_RATE_BASIC 0x0008
unsigned short bitrate; /* In 100kbit/s */
unsigned short ratemask;
@@ -94,9 +93,10 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
struct rt2x00_intf *intf,
struct ieee80211_bss_conf *conf);
void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev,
- enum antenna rx, enum antenna tx);
+ struct antenna_setup *ant);
void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
- struct ieee80211_conf *conf, const int force_config);
+ struct ieee80211_conf *conf,
+ const unsigned int changed_flags);
/**
* DOC: Queue handlers
@@ -150,8 +150,16 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
*/
void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index);
-void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev);
-void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev);
+/**
+ * rt2x00queue_init_queues - Initialize all data queues
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ *
+ * This function will loop through all available queues to clear all
+ * index numbers and set the queue entry to the correct initialization
+ * state.
+ */
+void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev);
+
int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev);
void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev);
int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev);
@@ -210,7 +218,10 @@ static inline void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev,
*/
#ifdef CONFIG_RT2X00_LIB_CRYPTO
enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key);
+void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
+ struct txentry_desc *txdesc);
unsigned int rt2x00crypto_tx_overhead(struct ieee80211_tx_info *tx_info);
+void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, unsigned int iv_len);
void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, unsigned int iv_len);
void rt2x00crypto_tx_insert_iv(struct sk_buff *skb);
void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, unsigned int align,
@@ -222,11 +233,21 @@ static inline enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *
return CIPHER_NONE;
}
+static inline void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry,
+ struct txentry_desc *txdesc)
+{
+}
+
static inline unsigned int rt2x00crypto_tx_overhead(struct ieee80211_tx_info *tx_info)
{
return 0;
}
+static inline void rt2x00crypto_tx_copy_iv(struct sk_buff *skb,
+ unsigned int iv_len)
+{
+}
+
static inline void rt2x00crypto_tx_remove_iv(struct sk_buff *skb,
unsigned int iv_len)
{
@@ -242,7 +263,7 @@ static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb,
struct rxdone_entry_desc *rxdesc)
{
}
-#endif
+#endif /* CONFIG_RT2X00_LIB_CRYPTO */
/*
* RFkill handlers.
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 2c6cc5c374ff..38edee5fe168 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -39,7 +39,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
unsigned int data_length;
int retval = 0;
- if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
+ if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
data_length = sizeof(struct ieee80211_cts);
else
data_length = sizeof(struct ieee80211_rts);
@@ -64,11 +64,11 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
*/
memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb));
rts_info = IEEE80211_SKB_CB(skb);
- rts_info->flags &= ~IEEE80211_TX_CTL_USE_RTS_CTS;
- rts_info->flags &= ~IEEE80211_TX_CTL_USE_CTS_PROTECT;
+ rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_RTS_CTS;
+ rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_CTS_PROTECT;
rts_info->flags &= ~IEEE80211_TX_CTL_REQ_TX_STATUS;
- if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
+ if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
rts_info->flags |= IEEE80211_TX_CTL_NO_ACK;
else
rts_info->flags &= ~IEEE80211_TX_CTL_NO_ACK;
@@ -79,12 +79,10 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev,
* RTS/CTS frame should use the length of the frame plus any
* encryption overhead that will be added by the hardware.
*/
-#ifdef CONFIG_RT2X00_LIB_CRYPTO
if (!frag_skb->do_not_encrypt)
data_length += rt2x00crypto_tx_overhead(tx_info);
-#endif /* CONFIG_RT2X00_LIB_CRYPTO */
- if (tx_info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
+ if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif,
frag_skb->data, data_length, tx_info,
(struct ieee80211_cts *)(skb->data));
@@ -132,8 +130,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
ERROR(rt2x00dev,
"Attempt to send packet over invalid queue %d.\n"
"Please file bug report to %s.\n", qid, DRV_PROJECT);
- dev_kfree_skb_any(skb);
- return NETDEV_TX_OK;
+ goto exit_fail;
}
/*
@@ -146,8 +143,8 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
* inside the hardware.
*/
frame_control = le16_to_cpu(ieee80211hdr->frame_control);
- if ((tx_info->flags & (IEEE80211_TX_CTL_USE_RTS_CTS |
- IEEE80211_TX_CTL_USE_CTS_PROTECT)) &&
+ if ((tx_info->control.rates[0].flags & (IEEE80211_TX_RC_USE_RTS_CTS |
+ IEEE80211_TX_RC_USE_CTS_PROTECT)) &&
!rt2x00dev->ops->hw->set_rts_threshold) {
if (rt2x00queue_available(queue) <= 1)
goto exit_fail;
@@ -335,10 +332,10 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw,
}
EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface);
-int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
- int radio_on;
+ struct ieee80211_conf *conf = &hw->conf;
int status;
/*
@@ -355,7 +352,6 @@ int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
* some configuration parameters (e.g. channel and antenna values) can
* only be set when the radio is enabled.
*/
- radio_on = test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags);
if (conf->radio_enabled) {
/* For programming the values, we have to turn RX off */
rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF);
@@ -369,7 +365,18 @@ int rt2x00mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
* When we've just turned on the radio, we want to reprogram
* everything to ensure a consistent state
*/
- rt2x00lib_config(rt2x00dev, conf, !radio_on);
+ rt2x00lib_config(rt2x00dev, conf, changed);
+
+ /*
+ * The radio was enabled, configure the antenna to the
+ * default settings, the link tuner will later start
+ * continue configuring the antenna based on the software
+ * diversity. But for non-diversity configurations, we need
+ * to have configured the correct state now.
+ */
+ if (changed & IEEE80211_CONF_CHANGE_RADIO_ENABLED)
+ rt2x00lib_config_antenna(rt2x00dev,
+ &rt2x00dev->default_ant);
/* Turn RX back on */
rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON);
@@ -480,12 +487,15 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_key_conf *key)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
+ struct ieee80211_sta *sta;
int (*set_key) (struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_crypto *crypto,
struct ieee80211_key_conf *key);
struct rt2x00lib_crypto crypto;
- if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
+ if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
+ return 0;
+ else if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags))
return -EOPNOTSUPP;
else if (key->keylen > 32)
return -ENOSPC;
@@ -528,6 +538,17 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
memcpy(&crypto.key, &key->key[0], key->keylen);
/*
+ * Discover the Association ID from mac80211.
+ * Some drivers need this information when updating the
+ * hardware key (either adding or removing).
+ */
+ rcu_read_lock();
+ sta = ieee80211_find_sta(hw, address);
+ if (sta)
+ crypto.aid = sta->aid;
+ rcu_read_unlock();
+
+ /*
* Each BSS has a maximum of 4 shared keys.
* Shared key index values:
* 0) BSS0 key0
@@ -625,7 +646,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
* When the erp information has changed, we should perform
* additional configuration steps. For all other changes we are done.
*/
- if (changes & (BSS_CHANGED_ERP_PREAMBLE | BSS_CHANGED_ERP_CTS_PROT)) {
+ if (changes & ~(BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) {
if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
rt2x00lib_config_erp(rt2x00dev, intf, bss_conf);
else
@@ -633,7 +654,6 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
}
spin_lock(&intf->lock);
- memcpy(&intf->conf, bss_conf, sizeof(*bss_conf));
if (delayed) {
intf->delayed_flags |= delayed;
schedule_work(&rt2x00dev->intf_work);
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index adf2876ed8ab..d52b22b82d1f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -32,24 +32,46 @@
#include "rt2x00pci.h"
/*
+ * Register access.
+ */
+int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ const struct rt2x00_field32 field,
+ u32 *reg)
+{
+ unsigned int i;
+
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+ rt2x00pci_register_read(rt2x00dev, offset, reg);
+ if (!rt2x00_get_field32(*reg, field))
+ return 1;
+ udelay(REGISTER_BUSY_DELAY);
+ }
+
+ ERROR(rt2x00dev, "Indirect register access failed: "
+ "offset=0x%.08x, value=0x%.08x\n", offset, *reg);
+ *reg = ~0;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read);
+
+/*
* TX data handlers.
*/
int rt2x00pci_write_tx_data(struct queue_entry *entry)
{
+ struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
struct skb_frame_desc *skbdesc;
- u32 word;
-
- rt2x00_desc_read(entry_priv->desc, 0, &word);
/*
* This should not happen, we already checked the entry
* was ours. When the hardware disagrees there has been
* a queue corruption!
*/
- if (unlikely(rt2x00_get_field32(word, TXD_ENTRY_OWNER_NIC) ||
- rt2x00_get_field32(word, TXD_ENTRY_VALID))) {
- ERROR(entry->queue->rt2x00dev,
+ if (unlikely(rt2x00dev->ops->lib->get_entry_state(entry))) {
+ ERROR(rt2x00dev,
"Corrupt queue %d, accessing entry which is not ours.\n"
"Please file bug report to %s.\n",
entry->queue->qid, DRV_PROJECT);
@@ -76,14 +98,12 @@ void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev)
struct queue_entry *entry;
struct queue_entry_priv_pci *entry_priv;
struct skb_frame_desc *skbdesc;
- u32 word;
while (1) {
entry = rt2x00queue_get_entry(queue, Q_INDEX);
entry_priv = entry->priv_data;
- rt2x00_desc_read(entry_priv->desc, 0, &word);
- if (rt2x00_get_field32(word, RXD_ENTRY_OWNER_NIC))
+ if (rt2x00dev->ops->lib->get_entry_state(entry))
break;
/*
@@ -222,8 +242,7 @@ static int rt2x00pci_alloc_reg(struct rt2x00_dev *rt2x00dev)
{
struct pci_dev *pci_dev = to_pci_dev(rt2x00dev->dev);
- rt2x00dev->csr.base = ioremap(pci_resource_start(pci_dev, 0),
- pci_resource_len(pci_dev, 0));
+ rt2x00dev->csr.base = pci_ioremap_bar(pci_dev, 0);
if (!rt2x00dev->csr.base)
goto exit;
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h
index 80bf97c03e2d..9c0a4d77bc1b 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.h
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.h
@@ -44,21 +44,10 @@
#define REGISTER_BUSY_DELAY 100
/*
- * Descriptor availability flags.
- * All PCI device descriptors have these 2 flags
- * with the exact same definition.
- * By storing them here we can use them inside rt2x00pci
- * for some simple entry availability checking.
- */
-#define TXD_ENTRY_OWNER_NIC FIELD32(0x00000001)
-#define TXD_ENTRY_VALID FIELD32(0x00000002)
-#define RXD_ENTRY_OWNER_NIC FIELD32(0x00000001)
-
-/*
* Register access.
*/
static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev,
- const unsigned long offset,
+ const unsigned int offset,
u32 *value)
{
*value = readl(rt2x00dev->csr.base + offset);
@@ -66,14 +55,14 @@ static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev,
static inline void
rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev,
- const unsigned long offset,
+ const unsigned int offset,
void *value, const u16 length)
{
memcpy_fromio(value, rt2x00dev->csr.base + offset, length);
}
static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev,
- const unsigned long offset,
+ const unsigned int offset,
u32 value)
{
writel(value, rt2x00dev->csr.base + offset);
@@ -81,13 +70,31 @@ static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev,
static inline void
rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev,
- const unsigned long offset,
+ const unsigned int offset,
const void *value, const u16 length)
{
memcpy_toio(rt2x00dev->csr.base + offset, value, length);
}
/**
+ * rt2x00pci_regbusy_read - Read from register with busy check
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @field: Field to check if register is busy
+ * @reg: Pointer to where register contents should be stored
+ *
+ * This function will read the given register, and checks if the
+ * register is busy. If it is, it will sleep for a couple of
+ * microseconds before reading the register again. If the register
+ * is not read after a certain timeout, this function will return
+ * FALSE.
+ */
+int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ const struct rt2x00_field32 field,
+ u32 *reg);
+
+/**
* rt2x00pci_write_tx_data - Initialize data for TX operation
* @entry: The entry where the frame is located
*
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 451d410ecdae..eaec6bd93ed5 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -55,14 +55,12 @@ struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev,
/*
* For IV/EIV/ICV assembly we must make sure there is
* at least 8 bytes bytes available in headroom for IV/EIV
- * and 4 bytes for ICV data as tailroon.
+ * and 8 bytes for ICV data as tailroon.
*/
-#ifdef CONFIG_RT2X00_LIB_CRYPTO
if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) {
head_size += 8;
- tail_size += 4;
+ tail_size += 8;
}
-#endif /* CONFIG_RT2X00_LIB_CRYPTO */
/*
* Allocate skbuffer.
@@ -174,7 +172,7 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
txdesc->cw_max = entry->queue->cw_max;
txdesc->aifs = entry->queue->aifs;
- /* Data length + CRC + IV/EIV/ICV/MMIC (when using encryption) */
+ /* Data length + CRC */
data_length = entry->skb->len + 4;
/*
@@ -183,34 +181,17 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK))
__set_bit(ENTRY_TXD_ACK, &txdesc->flags);
-#ifdef CONFIG_RT2X00_LIB_CRYPTO
if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) &&
!entry->skb->do_not_encrypt) {
- struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
-
- __set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags);
-
- txdesc->cipher = rt2x00crypto_key_to_cipher(hw_key);
-
- if (hw_key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
- __set_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags);
-
- txdesc->key_idx = hw_key->hw_key_idx;
- txdesc->iv_offset = ieee80211_get_hdrlen_from_skb(entry->skb);
+ /* Apply crypto specific descriptor information */
+ rt2x00crypto_create_tx_descriptor(entry, txdesc);
/*
* Extend frame length to include all encryption overhead
* that will be added by the hardware.
*/
data_length += rt2x00crypto_tx_overhead(tx_info);
-
- if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV))
- __set_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags);
-
- if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC))
- __set_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags);
}
-#endif /* CONFIG_RT2X00_LIB_CRYPTO */
/*
* Check if this is a RTS/CTS frame
@@ -230,8 +211,8 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
/*
* Determine retry information.
*/
- txdesc->retry_limit = tx_info->control.retry_limit;
- if (tx_info->flags & IEEE80211_TX_CTL_LONG_RETRY_LIMIT)
+ txdesc->retry_limit = tx_info->control.rates[0].count - 1;
+ if (txdesc->retry_limit >= rt2x00dev->long_retry)
__set_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags);
/*
@@ -312,8 +293,8 @@ static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
/*
* Convert length to microseconds.
*/
- residual = get_duration_res(data_length, hwrate->bitrate);
- duration = get_duration(data_length, hwrate->bitrate);
+ residual = GET_DURATION_RES(data_length, hwrate->bitrate);
+ duration = GET_DURATION(data_length, hwrate->bitrate);
if (residual != 0) {
duration++;
@@ -371,13 +352,15 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
{
+ struct ieee80211_tx_info *tx_info;
struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
struct txentry_desc txdesc;
struct skb_frame_desc *skbdesc;
unsigned int iv_len = 0;
+ u8 rate_idx, rate_flags;
if (unlikely(rt2x00queue_full(queue)))
- return -EINVAL;
+ return -ENOBUFS;
if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) {
ERROR(queue->rt2x00dev,
@@ -399,13 +382,18 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len;
/*
- * All information is retreived from the skb->cb array,
+ * All information is retrieved from the skb->cb array,
* now we should claim ownership of the driver part of that
- * array.
+ * array, preserving the bitrate index and flags.
*/
- skbdesc = get_skb_frame_desc(entry->skb);
+ tx_info = IEEE80211_SKB_CB(skb);
+ rate_idx = tx_info->control.rates[0].idx;
+ rate_flags = tx_info->control.rates[0].flags;
+ skbdesc = get_skb_frame_desc(skb);
memset(skbdesc, 0, sizeof(*skbdesc));
skbdesc->entry = entry;
+ skbdesc->tx_rate_idx = rate_idx;
+ skbdesc->tx_rate_flags = rate_flags;
/*
* When hardware encryption is supported, and this frame
@@ -414,19 +402,21 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
*/
if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) &&
!test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) {
- rt2x00crypto_tx_remove_iv(skb, iv_len);
+ if (test_bit(CONFIG_CRYPTO_COPY_IV, &queue->rt2x00dev->flags))
+ rt2x00crypto_tx_copy_iv(skb, iv_len);
+ else
+ rt2x00crypto_tx_remove_iv(skb, iv_len);
}
/*
* It could be possible that the queue was corrupted and this
- * call failed. Just drop the frame, we cannot rollback and pass
- * the frame to mac80211 because the skb->cb has now been tainted.
+ * call failed. Since we always return NETDEV_TX_OK to mac80211,
+ * this frame will simply be dropped.
*/
if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) {
clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
- dev_kfree_skb_any(entry->skb);
entry->skb = NULL;
- return 0;
+ return -EIO;
}
if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags))
@@ -556,7 +546,7 @@ void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index)
queue->length++;
} else if (index == Q_INDEX_DONE) {
queue->length--;
- queue->count ++;
+ queue->count++;
}
spin_unlock_irqrestore(&queue->lock, irqflags);
@@ -575,40 +565,18 @@ static void rt2x00queue_reset(struct data_queue *queue)
spin_unlock_irqrestore(&queue->lock, irqflags);
}
-void rt2x00queue_init_rx(struct rt2x00_dev *rt2x00dev)
-{
- struct data_queue *queue = rt2x00dev->rx;
- unsigned int i;
-
- rt2x00queue_reset(queue);
-
- if (!rt2x00dev->ops->lib->init_rxentry)
- return;
-
- for (i = 0; i < queue->limit; i++) {
- queue->entries[i].flags = 0;
-
- rt2x00dev->ops->lib->init_rxentry(rt2x00dev,
- &queue->entries[i]);
- }
-}
-
-void rt2x00queue_init_tx(struct rt2x00_dev *rt2x00dev)
+void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev)
{
struct data_queue *queue;
unsigned int i;
- txall_queue_for_each(rt2x00dev, queue) {
+ queue_for_each(rt2x00dev, queue) {
rt2x00queue_reset(queue);
- if (!rt2x00dev->ops->lib->init_txentry)
- continue;
-
for (i = 0; i < queue->limit; i++) {
queue->entries[i].flags = 0;
- rt2x00dev->ops->lib->init_txentry(rt2x00dev,
- &queue->entries[i]);
+ rt2x00dev->ops->lib->clear_entry(&queue->entries[i]);
}
}
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h
index 9dbf04f0f04c..282937153408 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
@@ -104,22 +104,25 @@ enum skb_frame_desc_flags {
*
* @flags: Frame flags, see &enum skb_frame_desc_flags.
* @desc_len: Length of the frame descriptor.
+ * @tx_rate_idx: the index of the TX rate, used for TX status reporting
+ * @tx_rate_flags: the TX rate flags, used for TX status reporting
* @desc: Pointer to descriptor part of the frame.
* Note that this pointer could point to something outside
* of the scope of the skb->data pointer.
- * @iv: IV data used during encryption/decryption.
- * @eiv: EIV data used during encryption/decryption.
+ * @iv: IV/EIV data used during encryption/decryption.
* @skb_dma: (PCI-only) the DMA address associated with the sk buffer.
* @entry: The entry to which this sk buffer belongs.
*/
struct skb_frame_desc {
- unsigned int flags;
+ u8 flags;
+
+ u8 desc_len;
+ u8 tx_rate_idx;
+ u8 tx_rate_flags;
- unsigned int desc_len;
void *desc;
- __le32 iv;
- __le32 eiv;
+ __le32 iv[2];
dma_addr_t skb_dma;
@@ -143,11 +146,15 @@ static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb)
* @RXDONE_SIGNAL_PLCP: Signal field contains the plcp value.
* @RXDONE_SIGNAL_BITRATE: Signal field contains the bitrate value.
* @RXDONE_MY_BSS: Does this frame originate from device's BSS.
+ * @RXDONE_CRYPTO_IV: Driver provided IV/EIV data.
+ * @RXDONE_CRYPTO_ICV: Driver provided ICV data.
*/
enum rxdone_entry_desc_flags {
RXDONE_SIGNAL_PLCP = 1 << 0,
RXDONE_SIGNAL_BITRATE = 1 << 1,
RXDONE_MY_BSS = 1 << 2,
+ RXDONE_CRYPTO_IV = 1 << 3,
+ RXDONE_CRYPTO_ICV = 1 << 4,
};
/**
@@ -163,8 +170,7 @@ enum rxdone_entry_desc_flags {
* @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags).
* @cipher: Cipher type used during decryption.
* @cipher_status: Decryption status.
- * @iv: IV data used during decryption.
- * @eiv: EIV data used during decryption.
+ * @iv: IV/EIV data used during decryption.
* @icv: ICV data used during decryption.
*/
struct rxdone_entry_desc {
@@ -177,8 +183,7 @@ struct rxdone_entry_desc {
u8 cipher;
u8 cipher_status;
- __le32 iv;
- __le32 eiv;
+ __le32 iv[2];
__le32 icv;
};
@@ -375,6 +380,8 @@ enum queue_index {
* @cw_max: The cw max value for outgoing frames (field ignored in RX queue).
* @data_size: Maximum data size for the frames in this queue.
* @desc_size: Hardware descriptor size for the data in this queue.
+ * @usb_endpoint: Device endpoint used for communication (USB only)
+ * @usb_maxpacket: Max packet size for given endpoint (USB only)
*/
struct data_queue {
struct rt2x00_dev *rt2x00dev;
@@ -396,6 +403,9 @@ struct data_queue {
unsigned short data_size;
unsigned short desc_size;
+
+ unsigned short usb_endpoint;
+ unsigned short usb_maxpacket;
};
/**
@@ -439,6 +449,19 @@ struct data_queue_desc {
&(__dev)->tx[(__dev)->ops->tx_queues]
/**
+ * queue_next - Return pointer to next queue in list (HELPER MACRO).
+ * @__queue: Current queue for which we need the next queue
+ *
+ * Using the current queue address we take the address directly
+ * after the queue to take the next queue. Note that this macro
+ * should be used carefully since it does not protect against
+ * moving past the end of the list. (See macros &queue_end and
+ * &tx_queue_end for determining the end of the queue).
+ */
+#define queue_next(__queue) \
+ &(__queue)[1]
+
+/**
* queue_loop - Loop through the queues within a specific range (HELPER MACRO).
* @__entry: Pointer where the current queue entry will be stored in.
* @__start: Start queue pointer.
@@ -448,8 +471,8 @@ struct data_queue_desc {
*/
#define queue_loop(__entry, __start, __end) \
for ((__entry) = (__start); \
- prefetch(&(__entry)[1]), (__entry) != (__end); \
- (__entry) = &(__entry)[1])
+ prefetch(queue_next(__entry)), (__entry) != (__end);\
+ (__entry) = queue_next(__entry))
/**
* queue_for_each - Loop through all queues
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index b73a7e0aeed4..83df312ac56f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -79,7 +79,7 @@ int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev,
{
int status;
- BUG_ON(!mutex_is_locked(&rt2x00dev->usb_cache_mutex));
+ BUG_ON(!mutex_is_locked(&rt2x00dev->csr_mutex));
/*
* Check for Cache availability.
@@ -110,13 +110,13 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
{
int status;
- mutex_lock(&rt2x00dev->usb_cache_mutex);
+ mutex_lock(&rt2x00dev->csr_mutex);
status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request,
requesttype, offset, buffer,
buffer_length, timeout);
- mutex_unlock(&rt2x00dev->usb_cache_mutex);
+ mutex_unlock(&rt2x00dev->csr_mutex);
return status;
}
@@ -132,7 +132,7 @@ int rt2x00usb_vendor_request_large_buff(struct rt2x00_dev *rt2x00dev,
unsigned char *tb;
u16 off, len, bsize;
- mutex_lock(&rt2x00dev->usb_cache_mutex);
+ mutex_lock(&rt2x00dev->csr_mutex);
tb = (char *)buffer;
off = offset;
@@ -148,12 +148,34 @@ int rt2x00usb_vendor_request_large_buff(struct rt2x00_dev *rt2x00dev,
off += bsize;
}
- mutex_unlock(&rt2x00dev->usb_cache_mutex);
+ mutex_unlock(&rt2x00dev->csr_mutex);
return status;
}
EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_large_buff);
+int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ struct rt2x00_field32 field,
+ u32 *reg)
+{
+ unsigned int i;
+
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
+ rt2x00usb_register_read_lock(rt2x00dev, offset, reg);
+ if (!rt2x00_get_field32(*reg, field))
+ return 1;
+ udelay(REGISTER_BUSY_DELAY);
+ }
+
+ ERROR(rt2x00dev, "Indirect register access failed: "
+ "offset=0x%.08x, value=0x%.08x\n", offset, *reg);
+ *reg = ~0;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read);
+
/*
* TX data handlers.
*/
@@ -212,10 +234,10 @@ int rt2x00usb_write_tx_data(struct queue_entry *entry)
* length of the data to usb_fill_bulk_urb. Pass the skb
* to the driver to determine what the length should be.
*/
- length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, entry->skb);
+ length = rt2x00dev->ops->lib->get_tx_data_len(entry);
usb_fill_bulk_urb(entry_priv->urb, usb_dev,
- usb_sndbulkpipe(usb_dev, 1),
+ usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint),
entry->skb->data, length,
rt2x00usb_interrupt_txdone, entry);
@@ -351,28 +373,96 @@ EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio);
/*
* Device initialization handlers.
*/
-void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev,
- struct queue_entry *entry)
+void rt2x00usb_clear_entry(struct queue_entry *entry)
{
- struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
+ struct usb_device *usb_dev =
+ to_usb_device_intf(entry->queue->rt2x00dev->dev);
struct queue_entry_priv_usb *entry_priv = entry->priv_data;
+ int pipe;
- usb_fill_bulk_urb(entry_priv->urb, usb_dev,
- usb_rcvbulkpipe(usb_dev, 1),
- entry->skb->data, entry->skb->len,
- rt2x00usb_interrupt_rxdone, entry);
+ if (entry->queue->qid == QID_RX) {
+ pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint);
+ usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe,
+ entry->skb->data, entry->skb->len,
+ rt2x00usb_interrupt_rxdone, entry);
- set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
- usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
+ set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
+ usb_submit_urb(entry_priv->urb, GFP_ATOMIC);
+ } else {
+ entry->flags = 0;
+ }
}
-EXPORT_SYMBOL_GPL(rt2x00usb_init_rxentry);
+EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry);
-void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev,
- struct queue_entry *entry)
+static void rt2x00usb_assign_endpoint(struct data_queue *queue,
+ struct usb_endpoint_descriptor *ep_desc)
{
- entry->flags = 0;
+ struct usb_device *usb_dev = to_usb_device_intf(queue->rt2x00dev->dev);
+ int pipe;
+
+ queue->usb_endpoint = usb_endpoint_num(ep_desc);
+
+ if (queue->qid == QID_RX) {
+ pipe = usb_rcvbulkpipe(usb_dev, queue->usb_endpoint);
+ queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe, 0);
+ } else {
+ pipe = usb_sndbulkpipe(usb_dev, queue->usb_endpoint);
+ queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe, 1);
+ }
+
+ if (!queue->usb_maxpacket)
+ queue->usb_maxpacket = 1;
+}
+
+static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev)
+{
+ struct usb_interface *intf = to_usb_interface(rt2x00dev->dev);
+ struct usb_host_interface *intf_desc = intf->cur_altsetting;
+ struct usb_endpoint_descriptor *ep_desc;
+ struct data_queue *queue = rt2x00dev->tx;
+ struct usb_endpoint_descriptor *tx_ep_desc = NULL;
+ unsigned int i;
+
+ /*
+ * Walk through all available endpoints to search for "bulk in"
+ * and "bulk out" endpoints. When we find such endpoints collect
+ * the information we need from the descriptor and assign it
+ * to the queue.
+ */
+ for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) {
+ ep_desc = &intf_desc->endpoint[i].desc;
+
+ if (usb_endpoint_is_bulk_in(ep_desc)) {
+ rt2x00usb_assign_endpoint(rt2x00dev->rx, ep_desc);
+ } else if (usb_endpoint_is_bulk_out(ep_desc)) {
+ rt2x00usb_assign_endpoint(queue, ep_desc);
+
+ if (queue != queue_end(rt2x00dev))
+ queue = queue_next(queue);
+ tx_ep_desc = ep_desc;
+ }
+ }
+
+ /*
+ * At least 1 endpoint for RX and 1 endpoint for TX must be available.
+ */
+ if (!rt2x00dev->rx->usb_endpoint || !rt2x00dev->tx->usb_endpoint) {
+ ERROR(rt2x00dev, "Bulk-in/Bulk-out endpoints not found\n");
+ return -EPIPE;
+ }
+
+ /*
+ * It might be possible not all queues have a dedicated endpoint.
+ * Loop through all TX queues and copy the endpoint information
+ * which we have gathered from already assigned endpoints.
+ */
+ txall_queue_for_each(rt2x00dev, queue) {
+ if (!queue->usb_endpoint)
+ rt2x00usb_assign_endpoint(queue, tx_ep_desc);
+ }
+
+ return 0;
}
-EXPORT_SYMBOL_GPL(rt2x00usb_init_txentry);
static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev,
struct data_queue *queue)
@@ -445,6 +535,13 @@ int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev)
int status;
/*
+ * Find endpoints for each queue
+ */
+ status = rt2x00usb_find_endpoints(rt2x00dev);
+ if (status)
+ goto exit;
+
+ /*
* Allocate DMA
*/
queue_for_each(rt2x00dev, queue) {
@@ -534,12 +631,6 @@ int rt2x00usb_probe(struct usb_interface *usb_intf,
rt2x00dev->dev = &usb_intf->dev;
rt2x00dev->ops = ops;
rt2x00dev->hw = hw;
- mutex_init(&rt2x00dev->usb_cache_mutex);
-
- rt2x00dev->usb_maxpacket =
- usb_maxpacket(usb_dev, usb_sndbulkpipe(usb_dev, 1), 1);
- if (!rt2x00dev->usb_maxpacket)
- rt2x00dev->usb_maxpacket = 1;
retval = rt2x00usb_alloc_reg(rt2x00dev);
if (retval)
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index 3b4a67417f95..2bd4ac855f52 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -231,6 +231,142 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev,
REGISTER_TIMEOUT16(length));
}
+/**
+ * rt2x00usb_regbusy_read - Read 32bit register word
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @value: Pointer to where register contents should be stored
+ *
+ * This function is a simple wrapper for 32bit register access
+ * through rt2x00usb_vendor_request_buff().
+ */
+static inline void rt2x00usb_register_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ u32 *value)
+{
+ __le32 reg;
+ rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
+ USB_VENDOR_REQUEST_IN, offset,
+ &reg, sizeof(reg), REGISTER_TIMEOUT);
+ *value = le32_to_cpu(reg);
+}
+
+/**
+ * rt2x00usb_register_read_lock - Read 32bit register word
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @value: Pointer to where register contents should be stored
+ *
+ * This function is a simple wrapper for 32bit register access
+ * through rt2x00usb_vendor_req_buff_lock().
+ */
+static inline void rt2x00usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ u32 *value)
+{
+ __le32 reg;
+ rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
+ USB_VENDOR_REQUEST_IN, offset,
+ &reg, sizeof(reg), REGISTER_TIMEOUT);
+ *value = le32_to_cpu(reg);
+}
+
+/**
+ * rt2x00usb_register_multiread - Read 32bit register words
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @value: Pointer to where register contents should be stored
+ * @length: Length of the data
+ *
+ * This function is a simple wrapper for 32bit register access
+ * through rt2x00usb_vendor_request_buff().
+ */
+static inline void rt2x00usb_register_multiread(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ void *value, const u32 length)
+{
+ rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
+ USB_VENDOR_REQUEST_IN, offset,
+ value, length,
+ REGISTER_TIMEOUT32(length));
+}
+
+/**
+ * rt2x00usb_register_write - Write 32bit register word
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @value: Data which should be written
+ *
+ * This function is a simple wrapper for 32bit register access
+ * through rt2x00usb_vendor_request_buff().
+ */
+static inline void rt2x00usb_register_write(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ u32 value)
+{
+ __le32 reg = cpu_to_le32(value);
+ rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
+ USB_VENDOR_REQUEST_OUT, offset,
+ &reg, sizeof(reg), REGISTER_TIMEOUT);
+}
+
+/**
+ * rt2x00usb_register_write_lock - Write 32bit register word
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @value: Data which should be written
+ *
+ * This function is a simple wrapper for 32bit register access
+ * through rt2x00usb_vendor_req_buff_lock().
+ */
+static inline void rt2x00usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ u32 value)
+{
+ __le32 reg = cpu_to_le32(value);
+ rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
+ USB_VENDOR_REQUEST_OUT, offset,
+ &reg, sizeof(reg), REGISTER_TIMEOUT);
+}
+
+/**
+ * rt2x00usb_register_multiwrite - Write 32bit register words
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @value: Data which should be written
+ * @length: Length of the data
+ *
+ * This function is a simple wrapper for 32bit register access
+ * through rt2x00usb_vendor_request_buff().
+ */
+static inline void rt2x00usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ void *value, const u32 length)
+{
+ rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
+ USB_VENDOR_REQUEST_OUT, offset,
+ value, length,
+ REGISTER_TIMEOUT32(length));
+}
+
+/**
+ * rt2x00usb_regbusy_read - Read from register with busy check
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ * @offset: Register offset
+ * @field: Field to check if register is busy
+ * @reg: Pointer to where register contents should be stored
+ *
+ * This function will read the given register, and checks if the
+ * register is busy. If it is, it will sleep for a couple of
+ * microseconds before reading the register again. If the register
+ * is not read after a certain timeout, this function will return
+ * FALSE.
+ */
+int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
+ const unsigned int offset,
+ struct rt2x00_field32 field,
+ u32 *reg);
+
/*
* Radio handlers
*/
@@ -286,10 +422,7 @@ void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
/*
* Device initialization handlers.
*/
-void rt2x00usb_init_rxentry(struct rt2x00_dev *rt2x00dev,
- struct queue_entry *entry);
-void rt2x00usb_init_txentry(struct rt2x00_dev *rt2x00dev,
- struct queue_entry *entry);
+void rt2x00usb_clear_entry(struct queue_entry *entry);
int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev);
void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev);
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index a461620b489f..987e89009f74 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -55,45 +55,36 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
* the access attempt is considered to have failed,
* and we will print an error.
*/
-static u32 rt61pci_bbp_check(struct rt2x00_dev *rt2x00dev)
-{
- u32 reg;
- unsigned int i;
-
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, PHY_CSR3, &reg);
- if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY))
- break;
- udelay(REGISTER_BUSY_DELAY);
- }
-
- return reg;
-}
+#define WAIT_FOR_BBP(__dev, __reg) \
+ rt2x00pci_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg))
+#define WAIT_FOR_RF(__dev, __reg) \
+ rt2x00pci_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg))
+#define WAIT_FOR_MCU(__dev, __reg) \
+ rt2x00pci_regbusy_read((__dev), H2M_MAILBOX_CSR, \
+ H2M_MAILBOX_CSR_OWNER, (__reg))
static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
{
u32 reg;
- /*
- * Wait until the BBP becomes ready.
- */
- reg = rt61pci_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) {
- ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n");
- return;
- }
+ mutex_lock(&rt2x00dev->csr_mutex);
/*
- * Write the data into the BBP.
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the new data into the register.
*/
- reg = 0;
- rt2x00_set_field32(&reg, PHY_CSR3_VALUE, value);
- rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
- rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
- rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 0);
+ if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+ reg = 0;
+ rt2x00_set_field32(&reg, PHY_CSR3_VALUE, value);
+ rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
+ rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
+ rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 0);
+
+ rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg);
+ }
- rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg);
+ mutex_unlock(&rt2x00dev->csr_mutex);
}
static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev,
@@ -101,66 +92,58 @@ static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- /*
- * Wait until the BBP becomes ready.
- */
- reg = rt61pci_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) {
- ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
- return;
- }
+ mutex_lock(&rt2x00dev->csr_mutex);
/*
- * Write the request into the BBP.
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the read request into the register.
+ * After the data has been written, we wait until hardware
+ * returns the correct value, if at any time the register
+ * doesn't become available in time, reg will be 0xffffffff
+ * which means we return 0xff to the caller.
*/
- reg = 0;
- rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
- rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
- rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 1);
+ if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+ reg = 0;
+ rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
+ rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
+ rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 1);
- rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg);
+ rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg);
- /*
- * Wait until the BBP becomes ready.
- */
- reg = rt61pci_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, PHY_CSR3_BUSY)) {
- ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
- *value = 0xff;
- return;
+ WAIT_FOR_BBP(rt2x00dev, &reg);
}
*value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
+
+ mutex_unlock(&rt2x00dev->csr_mutex);
}
static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u32 value)
{
u32 reg;
- unsigned int i;
if (!word)
return;
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt2x00pci_register_read(rt2x00dev, PHY_CSR4, &reg);
- if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY))
- goto rf_write;
- udelay(REGISTER_BUSY_DELAY);
- }
+ mutex_lock(&rt2x00dev->csr_mutex);
- ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n");
- return;
+ /*
+ * Wait until the RF becomes available, afterwards we
+ * can safely write the new data into the register.
+ */
+ if (WAIT_FOR_RF(rt2x00dev, &reg)) {
+ reg = 0;
+ rt2x00_set_field32(&reg, PHY_CSR4_VALUE, value);
+ rt2x00_set_field32(&reg, PHY_CSR4_NUMBER_OF_BITS, 21);
+ rt2x00_set_field32(&reg, PHY_CSR4_IF_SELECT, 0);
+ rt2x00_set_field32(&reg, PHY_CSR4_BUSY, 1);
-rf_write:
- reg = 0;
- rt2x00_set_field32(&reg, PHY_CSR4_VALUE, value);
- rt2x00_set_field32(&reg, PHY_CSR4_NUMBER_OF_BITS, 21);
- rt2x00_set_field32(&reg, PHY_CSR4_IF_SELECT, 0);
- rt2x00_set_field32(&reg, PHY_CSR4_BUSY, 1);
+ rt2x00pci_register_write(rt2x00dev, PHY_CSR4, reg);
+ rt2x00_rf_write(rt2x00dev, word, value);
+ }
- rt2x00pci_register_write(rt2x00dev, PHY_CSR4, reg);
- rt2x00_rf_write(rt2x00dev, word, value);
+ mutex_unlock(&rt2x00dev->csr_mutex);
}
#ifdef CONFIG_RT2X00_LIB_LEDS
@@ -175,25 +158,27 @@ static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, H2M_MAILBOX_CSR, &reg);
+ mutex_lock(&rt2x00dev->csr_mutex);
- if (rt2x00_get_field32(reg, H2M_MAILBOX_CSR_OWNER)) {
- ERROR(rt2x00dev, "mcu request error. "
- "Request 0x%02x failed for token 0x%02x.\n",
- command, token);
- return;
+ /*
+ * Wait until the MCU becomes available, afterwards we
+ * can safely write the new data into the register.
+ */
+ if (WAIT_FOR_MCU(rt2x00dev, &reg)) {
+ rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_OWNER, 1);
+ rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_CMD_TOKEN, token);
+ rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG0, arg0);
+ rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG1, arg1);
+ rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg);
+
+ rt2x00pci_register_read(rt2x00dev, HOST_CMD_CSR, &reg);
+ rt2x00_set_field32(&reg, HOST_CMD_CSR_HOST_COMMAND, command);
+ rt2x00_set_field32(&reg, HOST_CMD_CSR_INTERRUPT_MCU, 1);
+ rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg);
}
- rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_OWNER, 1);
- rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_CMD_TOKEN, token);
- rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG0, arg0);
- rt2x00_set_field32(&reg, H2M_MAILBOX_CSR_ARG1, arg1);
- rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg);
+ mutex_unlock(&rt2x00dev->csr_mutex);
- rt2x00pci_register_read(rt2x00dev, HOST_CMD_CSR, &reg);
- rt2x00_set_field32(&reg, HOST_CMD_CSR_HOST_COMMAND, command);
- rt2x00_set_field32(&reg, HOST_CMD_CSR_INTERRUPT_MCU, 1);
- rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg);
}
#endif /* CONFIG_RT2X00_LIB_LEDS */
@@ -228,43 +213,34 @@ static void rt61pci_eepromregister_write(struct eeprom_93cx6 *eeprom)
}
#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-#define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u32)) )
-
-static void rt61pci_read_csr(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u32 *data)
-{
- rt2x00pci_register_read(rt2x00dev, CSR_OFFSET(word), data);
-}
-
-static void rt61pci_write_csr(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u32 data)
-{
- rt2x00pci_register_write(rt2x00dev, CSR_OFFSET(word), data);
-}
-
static const struct rt2x00debug rt61pci_rt2x00debug = {
.owner = THIS_MODULE,
.csr = {
- .read = rt61pci_read_csr,
- .write = rt61pci_write_csr,
+ .read = rt2x00pci_register_read,
+ .write = rt2x00pci_register_write,
+ .flags = RT2X00DEBUGFS_OFFSET,
+ .word_base = CSR_REG_BASE,
.word_size = sizeof(u32),
.word_count = CSR_REG_SIZE / sizeof(u32),
},
.eeprom = {
.read = rt2x00_eeprom_read,
.write = rt2x00_eeprom_write,
+ .word_base = EEPROM_BASE,
.word_size = sizeof(u16),
.word_count = EEPROM_SIZE / sizeof(u16),
},
.bbp = {
.read = rt61pci_bbp_read,
.write = rt61pci_bbp_write,
+ .word_base = BBP_BASE,
.word_size = sizeof(u8),
.word_count = BBP_SIZE / sizeof(u8),
},
.rf = {
.read = rt2x00_rf_read,
.write = rt61pci_rf_write,
+ .word_base = RF_BASE,
.word_size = sizeof(u32),
.word_count = RF_SIZE / sizeof(u32),
},
@@ -643,95 +619,18 @@ static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
!!erp->short_preamble);
rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
-}
-
-
-static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_conf *libconf)
-{
- u16 eeprom;
- short lna_gain = 0;
-
- if (libconf->band == IEEE80211_BAND_2GHZ) {
- if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
- lna_gain += 14;
-
- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
- lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
- } else {
- if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
- lna_gain += 14;
-
- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
- lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
- }
-
- rt2x00dev->lna_gain = lna_gain;
-}
-
-static void rt61pci_config_phymode(struct rt2x00_dev *rt2x00dev,
- const int basic_rate_mask)
-{
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, basic_rate_mask);
-}
-
-static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev,
- struct rf_channel *rf, const int txpower)
-{
- u8 r3;
- u8 r94;
- u8 smart;
- rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
- rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
-
- smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) ||
- rt2x00_rf(&rt2x00dev->chip, RF2527));
-
- rt61pci_bbp_read(rt2x00dev, 3, &r3);
- rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
- rt61pci_bbp_write(rt2x00dev, 3, r3);
-
- r94 = 6;
- if (txpower > MAX_TXPOWER && txpower <= (MAX_TXPOWER + r94))
- r94 += txpower - MAX_TXPOWER;
- else if (txpower < MIN_TXPOWER && txpower >= (MIN_TXPOWER - r94))
- r94 += txpower;
- rt61pci_bbp_write(rt2x00dev, 94, r94);
+ rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates);
- rt61pci_rf_write(rt2x00dev, 1, rf->rf1);
- rt61pci_rf_write(rt2x00dev, 2, rf->rf2);
- rt61pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
- rt61pci_rf_write(rt2x00dev, 4, rf->rf4);
-
- udelay(200);
-
- rt61pci_rf_write(rt2x00dev, 1, rf->rf1);
- rt61pci_rf_write(rt2x00dev, 2, rf->rf2);
- rt61pci_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004);
- rt61pci_rf_write(rt2x00dev, 4, rf->rf4);
-
- udelay(200);
-
- rt61pci_rf_write(rt2x00dev, 1, rf->rf1);
- rt61pci_rf_write(rt2x00dev, 2, rf->rf2);
- rt61pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
- rt61pci_rf_write(rt2x00dev, 4, rf->rf4);
-
- msleep(1);
-}
-
-static void rt61pci_config_txpower(struct rt2x00_dev *rt2x00dev,
- const int txpower)
-{
- struct rf_channel rf;
-
- rt2x00_rf_read(rt2x00dev, 1, &rf.rf1);
- rt2x00_rf_read(rt2x00dev, 2, &rf.rf2);
- rt2x00_rf_read(rt2x00dev, 3, &rf.rf3);
- rt2x00_rf_read(rt2x00dev, 4, &rf.rf4);
+ rt2x00pci_register_read(rt2x00dev, MAC_CSR9, &reg);
+ rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
+ rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
- rt61pci_config_channel(rt2x00dev, &rf, txpower);
+ rt2x00pci_register_read(rt2x00dev, MAC_CSR8, &reg);
+ rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
+ rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
+ rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
+ rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg);
}
static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
@@ -906,8 +805,8 @@ static const struct antenna_sel antenna_sel_bg[] = {
{ 98, { 0x48, 0x48 } },
};
-static void rt61pci_config_antenna(struct rt2x00_dev *rt2x00dev,
- struct antenna_setup *ant)
+static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev,
+ struct antenna_setup *ant)
{
const struct antenna_sel *sel;
unsigned int lna;
@@ -954,20 +853,105 @@ static void rt61pci_config_antenna(struct rt2x00_dev *rt2x00dev,
}
}
-static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev,
+static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_conf *libconf)
+{
+ u16 eeprom;
+ short lna_gain = 0;
+
+ if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) {
+ if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
+ lna_gain += 14;
+
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
+ lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
+ } else {
+ if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags))
+ lna_gain += 14;
+
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
+ lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
+ }
+
+ rt2x00dev->lna_gain = lna_gain;
+}
+
+static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev,
+ struct rf_channel *rf, const int txpower)
+{
+ u8 r3;
+ u8 r94;
+ u8 smart;
+
+ rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
+ rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
+
+ smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) ||
+ rt2x00_rf(&rt2x00dev->chip, RF2527));
+
+ rt61pci_bbp_read(rt2x00dev, 3, &r3);
+ rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
+ rt61pci_bbp_write(rt2x00dev, 3, r3);
+
+ r94 = 6;
+ if (txpower > MAX_TXPOWER && txpower <= (MAX_TXPOWER + r94))
+ r94 += txpower - MAX_TXPOWER;
+ else if (txpower < MIN_TXPOWER && txpower >= (MIN_TXPOWER - r94))
+ r94 += txpower;
+ rt61pci_bbp_write(rt2x00dev, 94, r94);
+
+ rt61pci_rf_write(rt2x00dev, 1, rf->rf1);
+ rt61pci_rf_write(rt2x00dev, 2, rf->rf2);
+ rt61pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
+ rt61pci_rf_write(rt2x00dev, 4, rf->rf4);
+
+ udelay(200);
+
+ rt61pci_rf_write(rt2x00dev, 1, rf->rf1);
+ rt61pci_rf_write(rt2x00dev, 2, rf->rf2);
+ rt61pci_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004);
+ rt61pci_rf_write(rt2x00dev, 4, rf->rf4);
+
+ udelay(200);
+
+ rt61pci_rf_write(rt2x00dev, 1, rf->rf1);
+ rt61pci_rf_write(rt2x00dev, 2, rf->rf2);
+ rt61pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
+ rt61pci_rf_write(rt2x00dev, 4, rf->rf4);
+
+ msleep(1);
+}
+
+static void rt61pci_config_txpower(struct rt2x00_dev *rt2x00dev,
+ const int txpower)
+{
+ struct rf_channel rf;
+
+ rt2x00_rf_read(rt2x00dev, 1, &rf.rf1);
+ rt2x00_rf_read(rt2x00dev, 2, &rf.rf2);
+ rt2x00_rf_read(rt2x00dev, 3, &rf.rf3);
+ rt2x00_rf_read(rt2x00dev, 4, &rf.rf4);
+
+ rt61pci_config_channel(rt2x00dev, &rf, txpower);
+}
+
+static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf)
{
u32 reg;
- rt2x00pci_register_read(rt2x00dev, MAC_CSR9, &reg);
- rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, libconf->slot_time);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
+ rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
+ rt2x00_set_field32(&reg, TXRX_CSR4_LONG_RETRY_LIMIT,
+ libconf->conf->long_frame_max_tx_count);
+ rt2x00_set_field32(&reg, TXRX_CSR4_SHORT_RETRY_LIMIT,
+ libconf->conf->short_frame_max_tx_count);
+ rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
+}
- rt2x00pci_register_read(rt2x00dev, MAC_CSR8, &reg);
- rt2x00_set_field32(&reg, MAC_CSR8_SIFS, libconf->sifs);
- rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
- rt2x00_set_field32(&reg, MAC_CSR8_EIFS, libconf->eifs);
- rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg);
+static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_conf *libconf)
+{
+ u32 reg;
rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
@@ -990,16 +974,15 @@ static void rt61pci_config(struct rt2x00_dev *rt2x00dev,
/* Always recalculate LNA gain before changing configuration */
rt61pci_config_lna_gain(rt2x00dev, libconf);
- if (flags & CONFIG_UPDATE_PHYMODE)
- rt61pci_config_phymode(rt2x00dev, libconf->basic_rates);
- if (flags & CONFIG_UPDATE_CHANNEL)
+ if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
rt61pci_config_channel(rt2x00dev, &libconf->rf,
libconf->conf->power_level);
- if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL))
+ if ((flags & IEEE80211_CONF_CHANGE_POWER) &&
+ !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
rt61pci_config_txpower(rt2x00dev, libconf->conf->power_level);
- if (flags & CONFIG_UPDATE_ANTENNA)
- rt61pci_config_antenna(rt2x00dev, &libconf->ant);
- if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
+ if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+ rt61pci_config_retry_limit(rt2x00dev, libconf);
+ if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
rt61pci_config_duration(rt2x00dev, libconf);
}
@@ -1263,33 +1246,44 @@ static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data,
/*
* Initialization functions.
*/
-static void rt61pci_init_rxentry(struct rt2x00_dev *rt2x00dev,
- struct queue_entry *entry)
+static bool rt61pci_get_entry_state(struct queue_entry *entry)
{
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
- struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
u32 word;
- rt2x00_desc_read(entry_priv->desc, 5, &word);
- rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
- skbdesc->skb_dma);
- rt2x00_desc_write(entry_priv->desc, 5, word);
+ if (entry->queue->qid == QID_RX) {
+ rt2x00_desc_read(entry_priv->desc, 0, &word);
+
+ return rt2x00_get_field32(word, RXD_W0_OWNER_NIC);
+ } else {
+ rt2x00_desc_read(entry_priv->desc, 0, &word);
- rt2x00_desc_read(entry_priv->desc, 0, &word);
- rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
- rt2x00_desc_write(entry_priv->desc, 0, word);
+ return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) ||
+ rt2x00_get_field32(word, TXD_W0_VALID));
+ }
}
-static void rt61pci_init_txentry(struct rt2x00_dev *rt2x00dev,
- struct queue_entry *entry)
+static void rt61pci_clear_entry(struct queue_entry *entry)
{
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+ struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
u32 word;
- rt2x00_desc_read(entry_priv->desc, 0, &word);
- rt2x00_set_field32(&word, TXD_W0_VALID, 0);
- rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
- rt2x00_desc_write(entry_priv->desc, 0, word);
+ if (entry->queue->qid == QID_RX) {
+ rt2x00_desc_read(entry_priv->desc, 5, &word);
+ rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS,
+ skbdesc->skb_dma);
+ rt2x00_desc_write(entry_priv->desc, 5, word);
+
+ rt2x00_desc_read(entry_priv->desc, 0, &word);
+ rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1);
+ rt2x00_desc_write(entry_priv->desc, 0, word);
+ } else {
+ rt2x00_desc_read(entry_priv->desc, 0, &word);
+ rt2x00_set_field32(&word, TXD_W0_VALID, 0);
+ rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0);
+ rt2x00_desc_write(entry_priv->desc, 0, word);
+ }
}
static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev)
@@ -1784,8 +1778,8 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_desc_write(txd, 2, word);
if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
- _rt2x00_desc_write(txd, 3, skbdesc->iv);
- _rt2x00_desc_write(txd, 4, skbdesc->eiv);
+ _rt2x00_desc_write(txd, 3, skbdesc->iv[0]);
+ _rt2x00_desc_write(txd, 4, skbdesc->iv[1]);
}
rt2x00_desc_read(txd, 5, &word);
@@ -1934,7 +1928,7 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
}
static void rt61pci_fill_rxdone(struct queue_entry *entry,
- struct rxdone_entry_desc *rxdesc)
+ struct rxdone_entry_desc *rxdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct queue_entry_priv_pci *entry_priv = entry->priv_data;
@@ -1955,9 +1949,12 @@ static void rt61pci_fill_rxdone(struct queue_entry *entry,
}
if (rxdesc->cipher != CIPHER_NONE) {
- _rt2x00_desc_read(entry_priv->desc, 2, &rxdesc->iv);
- _rt2x00_desc_read(entry_priv->desc, 3, &rxdesc->eiv);
+ _rt2x00_desc_read(entry_priv->desc, 2, &rxdesc->iv[0]);
+ _rt2x00_desc_read(entry_priv->desc, 3, &rxdesc->iv[1]);
+ rxdesc->dev_flags |= RXDONE_CRYPTO_IV;
+
_rt2x00_desc_read(entry_priv->desc, 4, &rxdesc->icv);
+ rxdesc->dev_flags |= RXDONE_CRYPTO_ICV;
/*
* Hardware has stripped IV/EIV data from 802.11 frame during
@@ -2175,10 +2172,8 @@ static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
*/
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
if (!is_valid_ether_addr(mac)) {
- DECLARE_MAC_BUF(macbuf);
-
random_ether_addr(mac);
- EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac));
+ EEPROM(rt2x00dev, "MAC: %pM\n", mac);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
@@ -2630,20 +2625,6 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* IEEE80211 stack callback functions.
*/
-static int rt61pci_set_retry_limit(struct ieee80211_hw *hw,
- u32 short_retry, u32 long_retry)
-{
- struct rt2x00_dev *rt2x00dev = hw->priv;
- u32 reg;
-
- rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
- rt2x00_set_field32(&reg, TXRX_CSR4_LONG_RETRY_LIMIT, long_retry);
- rt2x00_set_field32(&reg, TXRX_CSR4_SHORT_RETRY_LIMIT, short_retry);
- rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
-
- return 0;
-}
-
static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
const struct ieee80211_tx_queue_params *params)
{
@@ -2726,7 +2707,6 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
.configure_filter = rt2x00mac_configure_filter,
.set_key = rt2x00mac_set_key,
.get_stats = rt2x00mac_get_stats,
- .set_retry_limit = rt61pci_set_retry_limit,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt61pci_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
@@ -2741,8 +2721,8 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
.load_firmware = rt61pci_load_firmware,
.initialize = rt2x00pci_initialize,
.uninitialize = rt2x00pci_uninitialize,
- .init_rxentry = rt61pci_init_rxentry,
- .init_txentry = rt61pci_init_txentry,
+ .get_entry_state = rt61pci_get_entry_state,
+ .clear_entry = rt61pci_clear_entry,
.set_device_state = rt61pci_set_device_state,
.rfkill_poll = rt61pci_rfkill_poll,
.link_stats = rt61pci_link_stats,
@@ -2758,6 +2738,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
.config_filter = rt61pci_config_filter,
.config_intf = rt61pci_config_intf,
.config_erp = rt61pci_config_erp,
+ .config_ant = rt61pci_config_ant,
.config = rt61pci_config,
};
diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h
index 8ec1451308cc..65fe3332364a 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.h
+++ b/drivers/net/wireless/rt2x00/rt61pci.h
@@ -48,7 +48,9 @@
#define CSR_REG_SIZE 0x04b0
#define EEPROM_BASE 0x0000
#define EEPROM_SIZE 0x0100
+#define BBP_BASE 0x0000
#define BBP_SIZE 0x0080
+#define RF_BASE 0x0000
#define RF_SIZE 0x0014
/*
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 934f8e03c5aa..d638a8a59370 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -46,7 +46,7 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
/*
* Register access.
* All access to the CSR registers will go through the methods
- * rt73usb_register_read and rt73usb_register_write.
+ * rt2x00usb_register_read and rt2x00usb_register_write.
* BBP and RF register require indirect register access,
* and use the CSR registers BBPCSR and RFCSR to achieve this.
* These indirect registers work with busy bits,
@@ -55,113 +55,35 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
* between each attampt. When the busy bit is still set at that time,
* the access attempt is considered to have failed,
* and we will print an error.
- * The _lock versions must be used if you already hold the usb_cache_mutex
+ * The _lock versions must be used if you already hold the csr_mutex
*/
-static inline void rt73usb_register_read(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset, u32 *value)
-{
- __le32 reg;
- rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
- USB_VENDOR_REQUEST_IN, offset,
- &reg, sizeof(u32), REGISTER_TIMEOUT);
- *value = le32_to_cpu(reg);
-}
-
-static inline void rt73usb_register_read_lock(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset, u32 *value)
-{
- __le32 reg;
- rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ,
- USB_VENDOR_REQUEST_IN, offset,
- &reg, sizeof(u32), REGISTER_TIMEOUT);
- *value = le32_to_cpu(reg);
-}
-
-static inline void rt73usb_register_multiread(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- void *value, const u32 length)
-{
- rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
- USB_VENDOR_REQUEST_IN, offset,
- value, length,
- REGISTER_TIMEOUT32(length));
-}
-
-static inline void rt73usb_register_write(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset, u32 value)
-{
- __le32 reg = cpu_to_le32(value);
- rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
- USB_VENDOR_REQUEST_OUT, offset,
- &reg, sizeof(u32), REGISTER_TIMEOUT);
-}
-
-static inline void rt73usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset, u32 value)
-{
- __le32 reg = cpu_to_le32(value);
- rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE,
- USB_VENDOR_REQUEST_OUT, offset,
- &reg, sizeof(u32), REGISTER_TIMEOUT);
-}
-
-static inline void rt73usb_register_multiwrite(struct rt2x00_dev *rt2x00dev,
- const unsigned int offset,
- void *value, const u32 length)
-{
- rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
- USB_VENDOR_REQUEST_OUT, offset,
- value, length,
- REGISTER_TIMEOUT32(length));
-}
-
-static u32 rt73usb_bbp_check(struct rt2x00_dev *rt2x00dev)
-{
- u32 reg;
- unsigned int i;
-
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt73usb_register_read_lock(rt2x00dev, PHY_CSR3, &reg);
- if (!rt2x00_get_field32(reg, PHY_CSR3_BUSY))
- break;
- udelay(REGISTER_BUSY_DELAY);
- }
-
- return reg;
-}
+#define WAIT_FOR_BBP(__dev, __reg) \
+ rt2x00usb_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg))
+#define WAIT_FOR_RF(__dev, __reg) \
+ rt2x00usb_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg))
static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u8 value)
{
u32 reg;
- mutex_lock(&rt2x00dev->usb_cache_mutex);
+ mutex_lock(&rt2x00dev->csr_mutex);
/*
- * Wait until the BBP becomes ready.
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the new data into the register.
*/
- reg = rt73usb_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
- goto exit_fail;
-
- /*
- * Write the data into the BBP.
- */
- reg = 0;
- rt2x00_set_field32(&reg, PHY_CSR3_VALUE, value);
- rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
- rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
- rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 0);
-
- rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
- mutex_unlock(&rt2x00dev->usb_cache_mutex);
-
- return;
-
-exit_fail:
- mutex_unlock(&rt2x00dev->usb_cache_mutex);
+ if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+ reg = 0;
+ rt2x00_set_field32(&reg, PHY_CSR3_VALUE, value);
+ rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
+ rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
+ rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 0);
+
+ rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
+ }
- ERROR(rt2x00dev, "PHY_CSR3 register busy. Write failed.\n");
+ mutex_unlock(&rt2x00dev->csr_mutex);
}
static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
@@ -169,123 +91,95 @@ static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- mutex_lock(&rt2x00dev->usb_cache_mutex);
-
- /*
- * Wait until the BBP becomes ready.
- */
- reg = rt73usb_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
- goto exit_fail;
+ mutex_lock(&rt2x00dev->csr_mutex);
/*
- * Write the request into the BBP.
+ * Wait until the BBP becomes available, afterwards we
+ * can safely write the read request into the register.
+ * After the data has been written, we wait until hardware
+ * returns the correct value, if at any time the register
+ * doesn't become available in time, reg will be 0xffffffff
+ * which means we return 0xff to the caller.
*/
- reg = 0;
- rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
- rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
- rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 1);
+ if (WAIT_FOR_BBP(rt2x00dev, &reg)) {
+ reg = 0;
+ rt2x00_set_field32(&reg, PHY_CSR3_REGNUM, word);
+ rt2x00_set_field32(&reg, PHY_CSR3_BUSY, 1);
+ rt2x00_set_field32(&reg, PHY_CSR3_READ_CONTROL, 1);
- rt73usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
+ rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR3, reg);
- /*
- * Wait until the BBP becomes ready.
- */
- reg = rt73usb_bbp_check(rt2x00dev);
- if (rt2x00_get_field32(reg, PHY_CSR3_BUSY))
- goto exit_fail;
+ WAIT_FOR_BBP(rt2x00dev, &reg);
+ }
*value = rt2x00_get_field32(reg, PHY_CSR3_VALUE);
- mutex_unlock(&rt2x00dev->usb_cache_mutex);
-
- return;
-
-exit_fail:
- mutex_unlock(&rt2x00dev->usb_cache_mutex);
- ERROR(rt2x00dev, "PHY_CSR3 register busy. Read failed.\n");
- *value = 0xff;
+ mutex_unlock(&rt2x00dev->csr_mutex);
}
static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev,
const unsigned int word, const u32 value)
{
u32 reg;
- unsigned int i;
if (!word)
return;
- mutex_lock(&rt2x00dev->usb_cache_mutex);
-
- for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt73usb_register_read_lock(rt2x00dev, PHY_CSR4, &reg);
- if (!rt2x00_get_field32(reg, PHY_CSR4_BUSY))
- goto rf_write;
- udelay(REGISTER_BUSY_DELAY);
- }
-
- mutex_unlock(&rt2x00dev->usb_cache_mutex);
- ERROR(rt2x00dev, "PHY_CSR4 register busy. Write failed.\n");
- return;
-
-rf_write:
- reg = 0;
- rt2x00_set_field32(&reg, PHY_CSR4_VALUE, value);
+ mutex_lock(&rt2x00dev->csr_mutex);
/*
- * RF5225 and RF2527 contain 21 bits per RF register value,
- * all others contain 20 bits.
+ * Wait until the RF becomes available, afterwards we
+ * can safely write the new data into the register.
*/
- rt2x00_set_field32(&reg, PHY_CSR4_NUMBER_OF_BITS,
- 20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
- rt2x00_rf(&rt2x00dev->chip, RF2527)));
- rt2x00_set_field32(&reg, PHY_CSR4_IF_SELECT, 0);
- rt2x00_set_field32(&reg, PHY_CSR4_BUSY, 1);
-
- rt73usb_register_write_lock(rt2x00dev, PHY_CSR4, reg);
- rt2x00_rf_write(rt2x00dev, word, value);
- mutex_unlock(&rt2x00dev->usb_cache_mutex);
-}
-
-#ifdef CONFIG_RT2X00_LIB_DEBUGFS
-#define CSR_OFFSET(__word) ( CSR_REG_BASE + ((__word) * sizeof(u32)) )
-
-static void rt73usb_read_csr(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u32 *data)
-{
- rt73usb_register_read(rt2x00dev, CSR_OFFSET(word), data);
-}
+ if (WAIT_FOR_RF(rt2x00dev, &reg)) {
+ reg = 0;
+ rt2x00_set_field32(&reg, PHY_CSR4_VALUE, value);
+ /*
+ * RF5225 and RF2527 contain 21 bits per RF register value,
+ * all others contain 20 bits.
+ */
+ rt2x00_set_field32(&reg, PHY_CSR4_NUMBER_OF_BITS,
+ 20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
+ rt2x00_rf(&rt2x00dev->chip, RF2527)));
+ rt2x00_set_field32(&reg, PHY_CSR4_IF_SELECT, 0);
+ rt2x00_set_field32(&reg, PHY_CSR4_BUSY, 1);
+
+ rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR4, reg);
+ rt2x00_rf_write(rt2x00dev, word, value);
+ }
-static void rt73usb_write_csr(struct rt2x00_dev *rt2x00dev,
- const unsigned int word, u32 data)
-{
- rt73usb_register_write(rt2x00dev, CSR_OFFSET(word), data);
+ mutex_unlock(&rt2x00dev->csr_mutex);
}
+#ifdef CONFIG_RT2X00_LIB_DEBUGFS
static const struct rt2x00debug rt73usb_rt2x00debug = {
.owner = THIS_MODULE,
.csr = {
- .read = rt73usb_read_csr,
- .write = rt73usb_write_csr,
+ .read = rt2x00usb_register_read,
+ .write = rt2x00usb_register_write,
+ .flags = RT2X00DEBUGFS_OFFSET,
+ .word_base = CSR_REG_BASE,
.word_size = sizeof(u32),
.word_count = CSR_REG_SIZE / sizeof(u32),
},
.eeprom = {
.read = rt2x00_eeprom_read,
.write = rt2x00_eeprom_write,
+ .word_base = EEPROM_BASE,
.word_size = sizeof(u16),
.word_count = EEPROM_SIZE / sizeof(u16),
},
.bbp = {
.read = rt73usb_bbp_read,
.write = rt73usb_bbp_write,
+ .word_base = BBP_BASE,
.word_size = sizeof(u8),
.word_count = BBP_SIZE / sizeof(u8),
},
.rf = {
.read = rt2x00_rf_read,
.write = rt73usb_rf_write,
+ .word_base = RF_BASE,
.word_size = sizeof(u32),
.word_count = RF_SIZE / sizeof(u32),
},
@@ -341,10 +235,10 @@ static int rt73usb_blink_set(struct led_classdev *led_cdev,
container_of(led_cdev, struct rt2x00_led, led_dev);
u32 reg;
- rt73usb_register_read(led->rt2x00dev, MAC_CSR14, &reg);
+ rt2x00usb_register_read(led->rt2x00dev, MAC_CSR14, &reg);
rt2x00_set_field32(&reg, MAC_CSR14_ON_PERIOD, *delay_on);
rt2x00_set_field32(&reg, MAC_CSR14_OFF_PERIOD, *delay_off);
- rt73usb_register_write(led->rt2x00dev, MAC_CSR14, reg);
+ rt2x00usb_register_write(led->rt2x00dev, MAC_CSR14, reg);
return 0;
}
@@ -387,7 +281,7 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
*/
mask = (0xf << crypto->bssidx);
- rt73usb_register_read(rt2x00dev, SEC_CSR0, &reg);
+ rt2x00usb_register_read(rt2x00dev, SEC_CSR0, &reg);
reg &= mask;
if (reg && reg == mask)
@@ -424,16 +318,16 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
field.bit_offset = (3 * key->hw_key_idx);
field.bit_mask = 0x7 << field.bit_offset;
- rt73usb_register_read(rt2x00dev, SEC_CSR1, &reg);
+ rt2x00usb_register_read(rt2x00dev, SEC_CSR1, &reg);
rt2x00_set_field32(&reg, field, crypto->cipher);
- rt73usb_register_write(rt2x00dev, SEC_CSR1, reg);
+ rt2x00usb_register_write(rt2x00dev, SEC_CSR1, reg);
} else {
field.bit_offset = (3 * (key->hw_key_idx - 8));
field.bit_mask = 0x7 << field.bit_offset;
- rt73usb_register_read(rt2x00dev, SEC_CSR5, &reg);
+ rt2x00usb_register_read(rt2x00dev, SEC_CSR5, &reg);
rt2x00_set_field32(&reg, field, crypto->cipher);
- rt73usb_register_write(rt2x00dev, SEC_CSR5, reg);
+ rt2x00usb_register_write(rt2x00dev, SEC_CSR5, reg);
}
/*
@@ -456,12 +350,12 @@ static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev,
*/
mask = 1 << key->hw_key_idx;
- rt73usb_register_read(rt2x00dev, SEC_CSR0, &reg);
+ rt2x00usb_register_read(rt2x00dev, SEC_CSR0, &reg);
if (crypto->cmd == SET_KEY)
reg |= mask;
else if (crypto->cmd == DISABLE_KEY)
reg &= ~mask;
- rt73usb_register_write(rt2x00dev, SEC_CSR0, reg);
+ rt2x00usb_register_write(rt2x00dev, SEC_CSR0, reg);
return 0;
}
@@ -486,10 +380,10 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
* When both registers are full, we drop the key,
* otherwise we use the first invalid entry.
*/
- rt73usb_register_read(rt2x00dev, SEC_CSR2, &reg);
+ rt2x00usb_register_read(rt2x00dev, SEC_CSR2, &reg);
if (reg && reg == ~0) {
key->hw_key_idx = 32;
- rt73usb_register_read(rt2x00dev, SEC_CSR3, &reg);
+ rt2x00usb_register_read(rt2x00dev, SEC_CSR3, &reg);
if (reg && reg == ~0)
return -ENOSPC;
}
@@ -517,14 +411,14 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
/*
* Send the address and cipher type to the hardware register.
* This data fits within the CSR cache size, so we can use
- * rt73usb_register_multiwrite() directly.
+ * rt2x00usb_register_multiwrite() directly.
*/
memset(&addr_entry, 0, sizeof(addr_entry));
memcpy(&addr_entry, crypto->address, ETH_ALEN);
addr_entry.cipher = crypto->cipher;
reg = PAIRWISE_TA_ENTRY(key->hw_key_idx);
- rt73usb_register_multiwrite(rt2x00dev, reg,
+ rt2x00usb_register_multiwrite(rt2x00dev, reg,
&addr_entry, sizeof(addr_entry));
/*
@@ -532,9 +426,9 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
* without this received frames will not be decrypted
* by the hardware.
*/
- rt73usb_register_read(rt2x00dev, SEC_CSR4, &reg);
+ rt2x00usb_register_read(rt2x00dev, SEC_CSR4, &reg);
reg |= (1 << crypto->bssidx);
- rt73usb_register_write(rt2x00dev, SEC_CSR4, reg);
+ rt2x00usb_register_write(rt2x00dev, SEC_CSR4, reg);
/*
* The driver does not support the IV/EIV generation
@@ -557,21 +451,21 @@ static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
if (key->hw_key_idx < 32) {
mask = 1 << key->hw_key_idx;
- rt73usb_register_read(rt2x00dev, SEC_CSR2, &reg);
+ rt2x00usb_register_read(rt2x00dev, SEC_CSR2, &reg);
if (crypto->cmd == SET_KEY)
reg |= mask;
else if (crypto->cmd == DISABLE_KEY)
reg &= ~mask;
- rt73usb_register_write(rt2x00dev, SEC_CSR2, reg);
+ rt2x00usb_register_write(rt2x00dev, SEC_CSR2, reg);
} else {
mask = 1 << (key->hw_key_idx - 32);
- rt73usb_register_read(rt2x00dev, SEC_CSR3, &reg);
+ rt2x00usb_register_read(rt2x00dev, SEC_CSR3, &reg);
if (crypto->cmd == SET_KEY)
reg |= mask;
else if (crypto->cmd == DISABLE_KEY)
reg &= ~mask;
- rt73usb_register_write(rt2x00dev, SEC_CSR3, reg);
+ rt2x00usb_register_write(rt2x00dev, SEC_CSR3, reg);
}
return 0;
@@ -588,7 +482,7 @@ static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev,
* and broadcast frames will always be accepted since
* there is no filter for it at this time.
*/
- rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_CRC,
!(filter_flags & FIF_FCSFAIL));
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_PHYSICAL,
@@ -606,7 +500,7 @@ static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_BROADCAST, 0);
rt2x00_set_field32(&reg, TXRX_CSR0_DROP_ACK_CTS,
!(filter_flags & FIF_CONTROL));
- rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
}
static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
@@ -625,16 +519,16 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
* bits which (when set to 0) will invalidate the entire beacon.
*/
beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
- rt73usb_register_write(rt2x00dev, beacon_base, 0);
+ rt2x00usb_register_write(rt2x00dev, beacon_base, 0);
/*
* Enable synchronisation.
*/
- rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
- rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
}
if (flags & CONFIG_UPDATE_MAC) {
@@ -642,7 +536,7 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff);
conf->mac[1] = cpu_to_le32(reg);
- rt73usb_register_multiwrite(rt2x00dev, MAC_CSR2,
+ rt2x00usb_register_multiwrite(rt2x00dev, MAC_CSR2,
conf->mac, sizeof(conf->mac));
}
@@ -651,7 +545,7 @@ static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&reg, MAC_CSR5_BSS_ID_MASK, 3);
conf->bssid[1] = cpu_to_le32(reg);
- rt73usb_register_multiwrite(rt2x00dev, MAC_CSR4,
+ rt2x00usb_register_multiwrite(rt2x00dev, MAC_CSR4,
conf->bssid, sizeof(conf->bssid));
}
}
@@ -661,95 +555,26 @@ static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout);
- rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
- rt73usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
!!erp->short_preamble);
- rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
-}
-
-static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,
- struct rt2x00lib_conf *libconf)
-{
- u16 eeprom;
- short lna_gain = 0;
-
- if (libconf->band == IEEE80211_BAND_2GHZ) {
- if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
- lna_gain += 14;
-
- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
- lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
- } else {
- rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
- lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
- }
-
- rt2x00dev->lna_gain = lna_gain;
-}
-
-static void rt73usb_config_phymode(struct rt2x00_dev *rt2x00dev,
- const int basic_rate_mask)
-{
- rt73usb_register_write(rt2x00dev, TXRX_CSR5, basic_rate_mask);
-}
-
-static void rt73usb_config_channel(struct rt2x00_dev *rt2x00dev,
- struct rf_channel *rf, const int txpower)
-{
- u8 r3;
- u8 r94;
- u8 smart;
-
- rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
- rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
-
- smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) ||
- rt2x00_rf(&rt2x00dev->chip, RF2527));
-
- rt73usb_bbp_read(rt2x00dev, 3, &r3);
- rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
- rt73usb_bbp_write(rt2x00dev, 3, r3);
-
- r94 = 6;
- if (txpower > MAX_TXPOWER && txpower <= (MAX_TXPOWER + r94))
- r94 += txpower - MAX_TXPOWER;
- else if (txpower < MIN_TXPOWER && txpower >= (MIN_TXPOWER - r94))
- r94 += txpower;
- rt73usb_bbp_write(rt2x00dev, 94, r94);
-
- rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
- rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
- rt73usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
- rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
- rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
- rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
- rt73usb_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004);
- rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates);
- rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
- rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
- rt73usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
- rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
+ rt2x00usb_register_read(rt2x00dev, MAC_CSR9, &reg);
+ rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
+ rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
- udelay(10);
-}
-
-static void rt73usb_config_txpower(struct rt2x00_dev *rt2x00dev,
- const int txpower)
-{
- struct rf_channel rf;
-
- rt2x00_rf_read(rt2x00dev, 1, &rf.rf1);
- rt2x00_rf_read(rt2x00dev, 2, &rf.rf2);
- rt2x00_rf_read(rt2x00dev, 3, &rf.rf3);
- rt2x00_rf_read(rt2x00dev, 4, &rf.rf4);
-
- rt73usb_config_channel(rt2x00dev, &rf, txpower);
+ rt2x00usb_register_read(rt2x00dev, MAC_CSR8, &reg);
+ rt2x00_set_field32(&reg, MAC_CSR8_SIFS, erp->sifs);
+ rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
+ rt2x00_set_field32(&reg, MAC_CSR8_EIFS, erp->eifs);
+ rt2x00usb_register_write(rt2x00dev, MAC_CSR8, reg);
}
static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev,
@@ -869,8 +694,8 @@ static const struct antenna_sel antenna_sel_bg[] = {
{ 98, { 0x48, 0x48 } },
};
-static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev,
- struct antenna_setup *ant)
+static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev,
+ struct antenna_setup *ant)
{
const struct antenna_sel *sel;
unsigned int lna;
@@ -895,14 +720,14 @@ static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev,
for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++)
rt73usb_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]);
- rt73usb_register_read(rt2x00dev, PHY_CSR0, &reg);
+ rt2x00usb_register_read(rt2x00dev, PHY_CSR0, &reg);
rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_BG,
(rt2x00dev->curr_band == IEEE80211_BAND_2GHZ));
rt2x00_set_field32(&reg, PHY_CSR0_PA_PE_A,
(rt2x00dev->curr_band == IEEE80211_BAND_5GHZ));
- rt73usb_register_write(rt2x00dev, PHY_CSR0, reg);
+ rt2x00usb_register_write(rt2x00dev, PHY_CSR0, reg);
if (rt2x00_rf(&rt2x00dev->chip, RF5226) ||
rt2x00_rf(&rt2x00dev->chip, RF5225))
@@ -912,33 +737,111 @@ static void rt73usb_config_antenna(struct rt2x00_dev *rt2x00dev,
rt73usb_config_antenna_2x(rt2x00dev, ant);
}
-static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev,
+static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev,
struct rt2x00lib_conf *libconf)
{
+ u16 eeprom;
+ short lna_gain = 0;
+
+ if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) {
+ if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
+ lna_gain += 14;
+
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom);
+ lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1);
+ } else {
+ rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom);
+ lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1);
+ }
+
+ rt2x00dev->lna_gain = lna_gain;
+}
+
+static void rt73usb_config_channel(struct rt2x00_dev *rt2x00dev,
+ struct rf_channel *rf, const int txpower)
+{
+ u8 r3;
+ u8 r94;
+ u8 smart;
+
+ rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower));
+ rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
+
+ smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) ||
+ rt2x00_rf(&rt2x00dev->chip, RF2527));
+
+ rt73usb_bbp_read(rt2x00dev, 3, &r3);
+ rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart);
+ rt73usb_bbp_write(rt2x00dev, 3, r3);
+
+ r94 = 6;
+ if (txpower > MAX_TXPOWER && txpower <= (MAX_TXPOWER + r94))
+ r94 += txpower - MAX_TXPOWER;
+ else if (txpower < MIN_TXPOWER && txpower >= (MIN_TXPOWER - r94))
+ r94 += txpower;
+ rt73usb_bbp_write(rt2x00dev, 94, r94);
+
+ rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
+ rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
+ rt73usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
+ rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
+
+ rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
+ rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
+ rt73usb_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004);
+ rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
+
+ rt73usb_rf_write(rt2x00dev, 1, rf->rf1);
+ rt73usb_rf_write(rt2x00dev, 2, rf->rf2);
+ rt73usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004);
+ rt73usb_rf_write(rt2x00dev, 4, rf->rf4);
+
+ udelay(10);
+}
+
+static void rt73usb_config_txpower(struct rt2x00_dev *rt2x00dev,
+ const int txpower)
+{
+ struct rf_channel rf;
+
+ rt2x00_rf_read(rt2x00dev, 1, &rf.rf1);
+ rt2x00_rf_read(rt2x00dev, 2, &rf.rf2);
+ rt2x00_rf_read(rt2x00dev, 3, &rf.rf3);
+ rt2x00_rf_read(rt2x00dev, 4, &rf.rf4);
+
+ rt73usb_config_channel(rt2x00dev, &rf, txpower);
+}
+
+static void rt73usb_config_retry_limit(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_conf *libconf)
+{
u32 reg;
- rt73usb_register_read(rt2x00dev, MAC_CSR9, &reg);
- rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, libconf->slot_time);
- rt73usb_register_write(rt2x00dev, MAC_CSR9, reg);
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
+ rt2x00_set_field32(&reg, TXRX_CSR4_LONG_RETRY_LIMIT,
+ libconf->conf->long_frame_max_tx_count);
+ rt2x00_set_field32(&reg, TXRX_CSR4_SHORT_RETRY_LIMIT,
+ libconf->conf->short_frame_max_tx_count);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
+}
- rt73usb_register_read(rt2x00dev, MAC_CSR8, &reg);
- rt2x00_set_field32(&reg, MAC_CSR8_SIFS, libconf->sifs);
- rt2x00_set_field32(&reg, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3);
- rt2x00_set_field32(&reg, MAC_CSR8_EIFS, libconf->eifs);
- rt73usb_register_write(rt2x00dev, MAC_CSR8, reg);
+static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev,
+ struct rt2x00lib_conf *libconf)
+{
+ u32 reg;
- rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
- rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
- rt73usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
- rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
- rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
libconf->conf->beacon_int * 16);
- rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
}
static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
@@ -948,16 +851,15 @@ static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
/* Always recalculate LNA gain before changing configuration */
rt73usb_config_lna_gain(rt2x00dev, libconf);
- if (flags & CONFIG_UPDATE_PHYMODE)
- rt73usb_config_phymode(rt2x00dev, libconf->basic_rates);
- if (flags & CONFIG_UPDATE_CHANNEL)
+ if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
rt73usb_config_channel(rt2x00dev, &libconf->rf,
libconf->conf->power_level);
- if ((flags & CONFIG_UPDATE_TXPOWER) && !(flags & CONFIG_UPDATE_CHANNEL))
+ if ((flags & IEEE80211_CONF_CHANGE_POWER) &&
+ !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
rt73usb_config_txpower(rt2x00dev, libconf->conf->power_level);
- if (flags & CONFIG_UPDATE_ANTENNA)
- rt73usb_config_antenna(rt2x00dev, &libconf->ant);
- if (flags & (CONFIG_UPDATE_SLOT_TIME | CONFIG_UPDATE_BEACON_INT))
+ if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
+ rt73usb_config_retry_limit(rt2x00dev, libconf);
+ if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
rt73usb_config_duration(rt2x00dev, libconf);
}
@@ -972,13 +874,13 @@ static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev,
/*
* Update FCS error count from register.
*/
- rt73usb_register_read(rt2x00dev, STA_CSR0, &reg);
+ rt2x00usb_register_read(rt2x00dev, STA_CSR0, &reg);
qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR);
/*
* Update False CCA count from register.
*/
- rt73usb_register_read(rt2x00dev, STA_CSR1, &reg);
+ rt2x00usb_register_read(rt2x00dev, STA_CSR1, &reg);
qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR);
}
@@ -1138,7 +1040,7 @@ static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, const void *data,
* Wait for stable hardware.
*/
for (i = 0; i < 100; i++) {
- rt73usb_register_read(rt2x00dev, MAC_CSR0, &reg);
+ rt2x00usb_register_read(rt2x00dev, MAC_CSR0, &reg);
if (reg)
break;
msleep(1);
@@ -1180,13 +1082,13 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
{
u32 reg;
- rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_AUTO_TX_SEQ, 1);
rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX, 0);
rt2x00_set_field32(&reg, TXRX_CSR0_TX_WITHOUT_WAITING, 0);
- rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
- rt73usb_register_read(rt2x00dev, TXRX_CSR1, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR1, &reg);
rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID0, 47); /* CCK Signal */
rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID0_VALID, 1);
rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID1, 30); /* Rssi */
@@ -1195,12 +1097,12 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID2_VALID, 1);
rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID3, 30); /* Rssi */
rt2x00_set_field32(&reg, TXRX_CSR1_BBP_ID3_VALID, 1);
- rt73usb_register_write(rt2x00dev, TXRX_CSR1, reg);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR1, reg);
/*
* CCK TXD BBP registers
*/
- rt73usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR2, &reg);
rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID0, 13);
rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID0_VALID, 1);
rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID1, 12);
@@ -1209,77 +1111,77 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID2_VALID, 1);
rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID3, 10);
rt2x00_set_field32(&reg, TXRX_CSR2_BBP_ID3_VALID, 1);
- rt73usb_register_write(rt2x00dev, TXRX_CSR2, reg);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR2, reg);
/*
* OFDM TXD BBP registers
*/
- rt73usb_register_read(rt2x00dev, TXRX_CSR3, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR3, &reg);
rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID0, 7);
rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID0_VALID, 1);
rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID1, 6);
rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID1_VALID, 1);
rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID2, 5);
rt2x00_set_field32(&reg, TXRX_CSR3_BBP_ID2_VALID, 1);
- rt73usb_register_write(rt2x00dev, TXRX_CSR3, reg);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR3, reg);
- rt73usb_register_read(rt2x00dev, TXRX_CSR7, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR7, &reg);
rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_6MBS, 59);
rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_9MBS, 53);
rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_12MBS, 49);
rt2x00_set_field32(&reg, TXRX_CSR7_ACK_CTS_18MBS, 46);
- rt73usb_register_write(rt2x00dev, TXRX_CSR7, reg);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR7, reg);
- rt73usb_register_read(rt2x00dev, TXRX_CSR8, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR8, &reg);
rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_24MBS, 44);
rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_36MBS, 42);
rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_48MBS, 42);
rt2x00_set_field32(&reg, TXRX_CSR8_ACK_CTS_54MBS, 42);
- rt73usb_register_write(rt2x00dev, TXRX_CSR8, reg);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR8, reg);
- rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0);
- rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
- rt73usb_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f);
- rt73usb_register_read(rt2x00dev, MAC_CSR6, &reg);
+ rt2x00usb_register_read(rt2x00dev, MAC_CSR6, &reg);
rt2x00_set_field32(&reg, MAC_CSR6_MAX_FRAME_UNIT, 0xfff);
- rt73usb_register_write(rt2x00dev, MAC_CSR6, reg);
+ rt2x00usb_register_write(rt2x00dev, MAC_CSR6, reg);
- rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00000718);
+ rt2x00usb_register_write(rt2x00dev, MAC_CSR10, 0x00000718);
if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE))
return -EBUSY;
- rt73usb_register_write(rt2x00dev, MAC_CSR13, 0x00007f00);
+ rt2x00usb_register_write(rt2x00dev, MAC_CSR13, 0x00007f00);
/*
* Invalidate all Shared Keys (SEC_CSR0),
* and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5)
*/
- rt73usb_register_write(rt2x00dev, SEC_CSR0, 0x00000000);
- rt73usb_register_write(rt2x00dev, SEC_CSR1, 0x00000000);
- rt73usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000);
+ rt2x00usb_register_write(rt2x00dev, SEC_CSR0, 0x00000000);
+ rt2x00usb_register_write(rt2x00dev, SEC_CSR1, 0x00000000);
+ rt2x00usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000);
reg = 0x000023b0;
if (rt2x00_rf(&rt2x00dev->chip, RF5225) ||
rt2x00_rf(&rt2x00dev->chip, RF2527))
rt2x00_set_field32(&reg, PHY_CSR1_RF_RPI, 1);
- rt73usb_register_write(rt2x00dev, PHY_CSR1, reg);
+ rt2x00usb_register_write(rt2x00dev, PHY_CSR1, reg);
- rt73usb_register_write(rt2x00dev, PHY_CSR5, 0x00040a06);
- rt73usb_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
- rt73usb_register_write(rt2x00dev, PHY_CSR7, 0x00000408);
+ rt2x00usb_register_write(rt2x00dev, PHY_CSR5, 0x00040a06);
+ rt2x00usb_register_write(rt2x00dev, PHY_CSR6, 0x00080606);
+ rt2x00usb_register_write(rt2x00dev, PHY_CSR7, 0x00000408);
- rt73usb_register_read(rt2x00dev, MAC_CSR9, &reg);
+ rt2x00usb_register_read(rt2x00dev, MAC_CSR9, &reg);
rt2x00_set_field32(&reg, MAC_CSR9_CW_SELECT, 0);
- rt73usb_register_write(rt2x00dev, MAC_CSR9, reg);
+ rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
/*
* Clear all beacons
@@ -1287,36 +1189,36 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev)
* the first byte since that byte contains the VALID and OWNER
* bits which (when set to 0) will invalidate the entire beacon.
*/
- rt73usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
- rt73usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
- rt73usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
- rt73usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
+ rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0);
+ rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0);
+ rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0);
+ rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0);
/*
* We must clear the error counters.
* These registers are cleared on read,
* so we may pass a useless variable to store the value.
*/
- rt73usb_register_read(rt2x00dev, STA_CSR0, &reg);
- rt73usb_register_read(rt2x00dev, STA_CSR1, &reg);
- rt73usb_register_read(rt2x00dev, STA_CSR2, &reg);
+ rt2x00usb_register_read(rt2x00dev, STA_CSR0, &reg);
+ rt2x00usb_register_read(rt2x00dev, STA_CSR1, &reg);
+ rt2x00usb_register_read(rt2x00dev, STA_CSR2, &reg);
/*
* Reset MAC and BBP registers.
*/
- rt73usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+ rt2x00usb_register_read(rt2x00dev, MAC_CSR1, &reg);
rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 1);
rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 1);
- rt73usb_register_write(rt2x00dev, MAC_CSR1, reg);
+ rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
- rt73usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+ rt2x00usb_register_read(rt2x00dev, MAC_CSR1, &reg);
rt2x00_set_field32(&reg, MAC_CSR1_SOFT_RESET, 0);
rt2x00_set_field32(&reg, MAC_CSR1_BBP_RESET, 0);
- rt73usb_register_write(rt2x00dev, MAC_CSR1, reg);
+ rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
- rt73usb_register_read(rt2x00dev, MAC_CSR1, &reg);
+ rt2x00usb_register_read(rt2x00dev, MAC_CSR1, &reg);
rt2x00_set_field32(&reg, MAC_CSR1_HOST_READY, 1);
- rt73usb_register_write(rt2x00dev, MAC_CSR1, reg);
+ rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg);
return 0;
}
@@ -1394,11 +1296,11 @@ static void rt73usb_toggle_rx(struct rt2x00_dev *rt2x00dev,
{
u32 reg;
- rt73usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
rt2x00_set_field32(&reg, TXRX_CSR0_DISABLE_RX,
(state == STATE_RADIO_RX_OFF) ||
(state == STATE_RADIO_RX_OFF_LINK));
- rt73usb_register_write(rt2x00dev, TXRX_CSR0, reg);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
}
static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev)
@@ -1415,12 +1317,12 @@ static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev)
static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev)
{
- rt73usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
+ rt2x00usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818);
/*
* Disable synchronisation.
*/
- rt73usb_register_write(rt2x00dev, TXRX_CSR9, 0);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, 0);
rt2x00usb_disable_radio(rt2x00dev);
}
@@ -1433,10 +1335,10 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
put_to_sleep = (state != STATE_AWAKE);
- rt73usb_register_read(rt2x00dev, MAC_CSR12, &reg);
+ rt2x00usb_register_read(rt2x00dev, MAC_CSR12, &reg);
rt2x00_set_field32(&reg, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep);
rt2x00_set_field32(&reg, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep);
- rt73usb_register_write(rt2x00dev, MAC_CSR12, reg);
+ rt2x00usb_register_write(rt2x00dev, MAC_CSR12, reg);
/*
* Device is not guaranteed to be in the requested state yet.
@@ -1444,7 +1346,7 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state)
* device has entered the correct state.
*/
for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
- rt73usb_register_read(rt2x00dev, MAC_CSR12, &reg);
+ rt2x00usb_register_read(rt2x00dev, MAC_CSR12, &reg);
state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE);
if (state == !put_to_sleep)
return 0;
@@ -1526,8 +1428,8 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_desc_write(txd, 2, word);
if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
- _rt2x00_desc_write(txd, 3, skbdesc->iv);
- _rt2x00_desc_write(txd, 4, skbdesc->eiv);
+ _rt2x00_desc_write(txd, 3, skbdesc->iv[0]);
+ _rt2x00_desc_write(txd, 4, skbdesc->iv[1]);
}
rt2x00_desc_read(txd, 5, &word);
@@ -1584,11 +1486,11 @@ static void rt73usb_write_beacon(struct queue_entry *entry)
* Disable beaconing while we are reloading the beacon data,
* otherwise we might be sending out invalid data.
*/
- rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
- rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
/*
* Write entire beacon with descriptor to register.
@@ -1606,8 +1508,7 @@ static void rt73usb_write_beacon(struct queue_entry *entry)
entry->skb = NULL;
}
-static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
- struct sk_buff *skb)
+static int rt73usb_get_tx_data_len(struct queue_entry *entry)
{
int length;
@@ -1615,8 +1516,8 @@ static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
* The length _must_ be a multiple of 4,
* but it must _not_ be a multiple of the USB packet size.
*/
- length = roundup(skb->len, 4);
- length += (4 * !(length % rt2x00dev->usb_maxpacket));
+ length = roundup(entry->skb->len, 4);
+ length += (4 * !(length % entry->queue->usb_maxpacket));
return length;
}
@@ -1635,14 +1536,14 @@ static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
* For Wi-Fi faily generated beacons between participating stations.
* Set TBTT phase adaptive adjustment step to 8us (default 16us)
*/
- rt73usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
- rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) {
rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
- rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+ rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
}
}
@@ -1685,7 +1586,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1)
}
static void rt73usb_fill_rxdone(struct queue_entry *entry,
- struct rxdone_entry_desc *rxdesc)
+ struct rxdone_entry_desc *rxdesc)
{
struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
@@ -1717,9 +1618,12 @@ static void rt73usb_fill_rxdone(struct queue_entry *entry,
}
if (rxdesc->cipher != CIPHER_NONE) {
- _rt2x00_desc_read(rxd, 2, &rxdesc->iv);
- _rt2x00_desc_read(rxd, 3, &rxdesc->eiv);
+ _rt2x00_desc_read(rxd, 2, &rxdesc->iv[0]);
+ _rt2x00_desc_read(rxd, 3, &rxdesc->iv[1]);
+ rxdesc->dev_flags |= RXDONE_CRYPTO_IV;
+
_rt2x00_desc_read(rxd, 4, &rxdesc->icv);
+ rxdesc->dev_flags |= RXDONE_CRYPTO_ICV;
/*
* Hardware has stripped IV/EIV data from 802.11 frame during
@@ -1781,10 +1685,8 @@ static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
*/
mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0);
if (!is_valid_ether_addr(mac)) {
- DECLARE_MAC_BUF(macbuf);
-
random_ether_addr(mac);
- EEPROM(rt2x00dev, "MAC: %s\n", print_mac(macbuf, mac));
+ EEPROM(rt2x00dev, "MAC: %pM\n", mac);
}
rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word);
@@ -1883,7 +1785,7 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev)
* Identify RF chipset.
*/
value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE);
- rt73usb_register_read(rt2x00dev, MAC_CSR0, &reg);
+ rt2x00usb_register_read(rt2x00dev, MAC_CSR0, &reg);
rt2x00_set_chip(rt2x00dev, RT2571, value, reg);
if (!rt2x00_check_rev(&rt2x00dev->chip, 0x25730)) {
@@ -2211,20 +2113,6 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
/*
* IEEE80211 stack callback functions.
*/
-static int rt73usb_set_retry_limit(struct ieee80211_hw *hw,
- u32 short_retry, u32 long_retry)
-{
- struct rt2x00_dev *rt2x00dev = hw->priv;
- u32 reg;
-
- rt73usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
- rt2x00_set_field32(&reg, TXRX_CSR4_LONG_RETRY_LIMIT, long_retry);
- rt2x00_set_field32(&reg, TXRX_CSR4_SHORT_RETRY_LIMIT, short_retry);
- rt73usb_register_write(rt2x00dev, TXRX_CSR4, reg);
-
- return 0;
-}
-
static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
const struct ieee80211_tx_queue_params *params)
{
@@ -2251,33 +2139,33 @@ static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx,
field.bit_offset = queue_idx * 16;
field.bit_mask = 0xffff << field.bit_offset;
- rt73usb_register_read(rt2x00dev, AC_TXOP_CSR0, &reg);
+ rt2x00usb_register_read(rt2x00dev, AC_TXOP_CSR0, &reg);
rt2x00_set_field32(&reg, field, queue->txop);
- rt73usb_register_write(rt2x00dev, AC_TXOP_CSR0, reg);
+ rt2x00usb_register_write(rt2x00dev, AC_TXOP_CSR0, reg);
} else if (queue_idx < 4) {
field.bit_offset = (queue_idx - 2) * 16;
field.bit_mask = 0xffff << field.bit_offset;
- rt73usb_register_read(rt2x00dev, AC_TXOP_CSR1, &reg);
+ rt2x00usb_register_read(rt2x00dev, AC_TXOP_CSR1, &reg);
rt2x00_set_field32(&reg, field, queue->txop);
- rt73usb_register_write(rt2x00dev, AC_TXOP_CSR1, reg);
+ rt2x00usb_register_write(rt2x00dev, AC_TXOP_CSR1, reg);
}
/* Update WMM registers */
field.bit_offset = queue_idx * 4;
field.bit_mask = 0xf << field.bit_offset;
- rt73usb_register_read(rt2x00dev, AIFSN_CSR, &reg);
+ rt2x00usb_register_read(rt2x00dev, AIFSN_CSR, &reg);
rt2x00_set_field32(&reg, field, queue->aifs);
- rt73usb_register_write(rt2x00dev, AIFSN_CSR, reg);
+ rt2x00usb_register_write(rt2x00dev, AIFSN_CSR, reg);
- rt73usb_register_read(rt2x00dev, CWMIN_CSR, &reg);
+ rt2x00usb_register_read(rt2x00dev, CWMIN_CSR, &reg);
rt2x00_set_field32(&reg, field, queue->cw_min);
- rt73usb_register_write(rt2x00dev, CWMIN_CSR, reg);
+ rt2x00usb_register_write(rt2x00dev, CWMIN_CSR, reg);
- rt73usb_register_read(rt2x00dev, CWMAX_CSR, &reg);
+ rt2x00usb_register_read(rt2x00dev, CWMAX_CSR, &reg);
rt2x00_set_field32(&reg, field, queue->cw_max);
- rt73usb_register_write(rt2x00dev, CWMAX_CSR, reg);
+ rt2x00usb_register_write(rt2x00dev, CWMAX_CSR, reg);
return 0;
}
@@ -2295,9 +2183,9 @@ static u64 rt73usb_get_tsf(struct ieee80211_hw *hw)
u64 tsf;
u32 reg;
- rt73usb_register_read(rt2x00dev, TXRX_CSR13, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR13, &reg);
tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32;
- rt73usb_register_read(rt2x00dev, TXRX_CSR12, &reg);
+ rt2x00usb_register_read(rt2x00dev, TXRX_CSR12, &reg);
tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER);
return tsf;
@@ -2317,7 +2205,6 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
.configure_filter = rt2x00mac_configure_filter,
.set_key = rt2x00mac_set_key,
.get_stats = rt2x00mac_get_stats,
- .set_retry_limit = rt73usb_set_retry_limit,
.bss_info_changed = rt2x00mac_bss_info_changed,
.conf_tx = rt73usb_conf_tx,
.get_tx_stats = rt2x00mac_get_tx_stats,
@@ -2331,8 +2218,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
.load_firmware = rt73usb_load_firmware,
.initialize = rt2x00usb_initialize,
.uninitialize = rt2x00usb_uninitialize,
- .init_rxentry = rt2x00usb_init_rxentry,
- .init_txentry = rt2x00usb_init_txentry,
+ .clear_entry = rt2x00usb_clear_entry,
.set_device_state = rt73usb_set_device_state,
.link_stats = rt73usb_link_stats,
.reset_tuner = rt73usb_reset_tuner,
@@ -2348,6 +2234,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
.config_filter = rt73usb_config_filter,
.config_intf = rt73usb_config_intf,
.config_erp = rt73usb_config_erp,
+ .config_ant = rt73usb_config_ant,
.config = rt73usb_config,
};
diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h
index 868386c457f6..46e1405eb0e2 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.h
+++ b/drivers/net/wireless/rt2x00/rt73usb.h
@@ -48,7 +48,9 @@
#define CSR_REG_SIZE 0x04b0
#define EEPROM_BASE 0x0000
#define EEPROM_SIZE 0x0100
+#define BBP_BASE 0x0000
#define BBP_SIZE 0x0080
+#define RF_BASE 0x0000
#define RF_SIZE 0x0014
/*
diff --git a/drivers/net/wireless/rtl818x/Makefile b/drivers/net/wireless/rtl818x/Makefile
new file mode 100644
index 000000000000..c113b3e69046
--- /dev/null
+++ b/drivers/net/wireless/rtl818x/Makefile
@@ -0,0 +1,7 @@
+rtl8180-objs := rtl8180_dev.o rtl8180_rtl8225.o rtl8180_sa2400.o rtl8180_max2820.o rtl8180_grf5101.o
+rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o
+
+obj-$(CONFIG_RTL8180) += rtl8180.o
+obj-$(CONFIG_RTL8187) += rtl8187.o
+
+
diff --git a/drivers/net/wireless/rtl8180.h b/drivers/net/wireless/rtl818x/rtl8180.h
index 8721282a8185..8721282a8185 100644
--- a/drivers/net/wireless/rtl8180.h
+++ b/drivers/net/wireless/rtl818x/rtl8180.h
diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c
index df7e78ee8a88..5f887fb137a9 100644
--- a/drivers/net/wireless/rtl8180_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c
@@ -182,15 +182,13 @@ static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio)
skb->len, PCI_DMA_TODEVICE);
info = IEEE80211_SKB_CB(skb);
- memset(&info->status, 0, sizeof(info->status));
+ ieee80211_tx_info_clear_status(info);
- if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
- if (flags & RTL818X_TX_DESC_FLAG_TX_OK)
- info->flags |= IEEE80211_TX_STAT_ACK;
- else
- info->status.excessive_retries = 1;
- }
- info->status.retry_count = flags & 0xFF;
+ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
+ (flags & RTL818X_TX_DESC_FLAG_TX_OK))
+ info->flags |= IEEE80211_TX_STAT_ACK;
+
+ info->status.rates[0].count = (flags & 0xFF) + 1;
ieee80211_tx_status_irqsafe(dev, skb);
if (ring->entries - skb_queue_len(&ring->queue) == 2)
@@ -243,6 +241,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
unsigned int idx, prio;
dma_addr_t mapping;
u32 tx_flags;
+ u8 rc_flags;
u16 plcp_len = 0;
__le16 rts_duration = 0;
@@ -261,15 +260,16 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
tx_flags |= RTL818X_TX_DESC_FLAG_DMA |
RTL818X_TX_DESC_FLAG_NO_ENC;
- if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
+ rc_flags = info->control.rates[0].flags;
+ if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
tx_flags |= RTL818X_TX_DESC_FLAG_RTS;
tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
- } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
+ } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
tx_flags |= RTL818X_TX_DESC_FLAG_CTS;
tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
}
- if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS)
+ if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS)
rts_duration = ieee80211_rts_duration(dev, priv->vif, skb->len,
info);
@@ -292,9 +292,9 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
entry->plcp_len = cpu_to_le16(plcp_len);
entry->tx_buf = cpu_to_le32(mapping);
entry->frame_len = cpu_to_le32(skb->len);
- entry->flags2 = info->control.retries[0].rate_idx >= 0 ?
+ entry->flags2 = info->control.rates[1].idx >= 0 ?
ieee80211_get_alt_retry_rate(dev, info, 0)->bitrate << 4 : 0;
- entry->retry_limit = info->control.retry_limit;
+ entry->retry_limit = info->control.rates[0].count;
entry->flags = cpu_to_le32(tx_flags);
__skb_queue_tail(&ring->queue, skb);
if (ring->entries - skb_queue_len(&ring->queue) < 2)
@@ -692,9 +692,10 @@ static void rtl8180_remove_interface(struct ieee80211_hw *dev,
priv->vif = NULL;
}
-static int rtl8180_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+static int rtl8180_config(struct ieee80211_hw *dev, u32 changed)
{
struct rtl8180_priv *priv = dev->priv;
+ struct ieee80211_conf *conf = &dev->conf;
priv->rf->set_chan(dev, conf);
@@ -719,6 +720,17 @@ static int rtl8180_config_interface(struct ieee80211_hw *dev,
return 0;
}
+static void rtl8180_bss_info_changed(struct ieee80211_hw *dev,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info,
+ u32 changed)
+{
+ struct rtl8180_priv *priv = dev->priv;
+
+ if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp)
+ priv->rf->conf_erp(dev, info);
+}
+
static void rtl8180_configure_filter(struct ieee80211_hw *dev,
unsigned int changed_flags,
unsigned int *total_flags,
@@ -759,6 +771,7 @@ static const struct ieee80211_ops rtl8180_ops = {
.remove_interface = rtl8180_remove_interface,
.config = rtl8180_config,
.config_interface = rtl8180_config_interface,
+ .bss_info_changed = rtl8180_bss_info_changed,
.configure_filter = rtl8180_configure_filter,
};
@@ -806,7 +819,6 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
const char *chip_name, *rf_name = NULL;
u32 reg;
u16 eeprom_val;
- DECLARE_MAC_BUF(mac);
err = pci_enable_device(pdev);
if (err) {
@@ -855,7 +867,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
priv = dev->priv;
priv->pdev = pdev;
- dev->max_altrates = 1;
+ dev->max_rates = 2;
SET_IEEE80211_DEV(dev, &pdev->dev);
pci_set_drvdata(pdev, dev);
@@ -1002,8 +1014,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev,
goto err_iounmap;
}
- printk(KERN_INFO "%s: hwaddr %s, %s + %s\n",
- wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr),
+ printk(KERN_INFO "%s: hwaddr %pM, %s + %s\n",
+ wiphy_name(dev->wiphy), dev->wiphy->perm_addr,
chip_name, priv->rf->name);
return 0;
diff --git a/drivers/net/wireless/rtl8180_grf5101.c b/drivers/net/wireless/rtl818x/rtl8180_grf5101.c
index 947ee55f18b2..947ee55f18b2 100644
--- a/drivers/net/wireless/rtl8180_grf5101.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_grf5101.c
diff --git a/drivers/net/wireless/rtl8180_grf5101.h b/drivers/net/wireless/rtl818x/rtl8180_grf5101.h
index 76647111bcff..76647111bcff 100644
--- a/drivers/net/wireless/rtl8180_grf5101.h
+++ b/drivers/net/wireless/rtl818x/rtl8180_grf5101.h
diff --git a/drivers/net/wireless/rtl8180_max2820.c b/drivers/net/wireless/rtl818x/rtl8180_max2820.c
index 6c825fd7f3b6..6c825fd7f3b6 100644
--- a/drivers/net/wireless/rtl8180_max2820.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_max2820.c
diff --git a/drivers/net/wireless/rtl8180_max2820.h b/drivers/net/wireless/rtl818x/rtl8180_max2820.h
index 61cf6d1e7d57..61cf6d1e7d57 100644
--- a/drivers/net/wireless/rtl8180_max2820.h
+++ b/drivers/net/wireless/rtl818x/rtl8180_max2820.h
diff --git a/drivers/net/wireless/rtl8180_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8180_rtl8225.c
index cd22781728a9..4d2be0d9672b 100644
--- a/drivers/net/wireless/rtl8180_rtl8225.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_rtl8225.c
@@ -725,8 +725,14 @@ static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
msleep(10);
+}
+
+static void rtl8225_rf_conf_erp(struct ieee80211_hw *dev,
+ struct ieee80211_bss_conf *info)
+{
+ struct rtl8180_priv *priv = dev->priv;
- if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
+ if (info->use_short_slot) {
rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
@@ -745,14 +751,16 @@ static const struct rtl818x_rf_ops rtl8225_ops = {
.name = "rtl8225",
.init = rtl8225_rf_init,
.stop = rtl8225_rf_stop,
- .set_chan = rtl8225_rf_set_channel
+ .set_chan = rtl8225_rf_set_channel,
+ .conf_erp = rtl8225_rf_conf_erp,
};
static const struct rtl818x_rf_ops rtl8225z2_ops = {
.name = "rtl8225z2",
.init = rtl8225z2_rf_init,
.stop = rtl8225_rf_stop,
- .set_chan = rtl8225_rf_set_channel
+ .set_chan = rtl8225_rf_set_channel,
+ .conf_erp = rtl8225_rf_conf_erp,
};
const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *dev)
diff --git a/drivers/net/wireless/rtl8180_rtl8225.h b/drivers/net/wireless/rtl818x/rtl8180_rtl8225.h
index 310013a2d726..310013a2d726 100644
--- a/drivers/net/wireless/rtl8180_rtl8225.h
+++ b/drivers/net/wireless/rtl818x/rtl8180_rtl8225.h
diff --git a/drivers/net/wireless/rtl8180_sa2400.c b/drivers/net/wireless/rtl818x/rtl8180_sa2400.c
index cea4e0ccb92d..cea4e0ccb92d 100644
--- a/drivers/net/wireless/rtl8180_sa2400.c
+++ b/drivers/net/wireless/rtl818x/rtl8180_sa2400.c
diff --git a/drivers/net/wireless/rtl8180_sa2400.h b/drivers/net/wireless/rtl818x/rtl8180_sa2400.h
index a4aaa0d413f1..a4aaa0d413f1 100644
--- a/drivers/net/wireless/rtl8180_sa2400.h
+++ b/drivers/net/wireless/rtl818x/rtl8180_sa2400.h
diff --git a/drivers/net/wireless/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h
index e82bb4d289e8..3b1e1c2aad26 100644
--- a/drivers/net/wireless/rtl8187.h
+++ b/drivers/net/wireless/rtl818x/rtl8187.h
@@ -99,8 +99,8 @@ struct rtl8187_priv {
struct ieee80211_supported_band band;
struct usb_device *udev;
u32 rx_conf;
+ struct usb_anchor anchored;
u16 txpwr_base;
- u16 seqno;
u8 asic_rev;
u8 is_rtl8187b;
enum {
@@ -112,6 +112,12 @@ struct rtl8187_priv {
u8 signal;
u8 quality;
u8 noise;
+ u8 slot_time;
+ u8 aifsn[4];
+ struct {
+ __le64 buf;
+ struct sk_buff_head queue;
+ } b_tx_status;
};
void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data);
diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index 69eb0132593b..00ce3ef39abe 100644
--- a/drivers/net/wireless/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -7,6 +7,11 @@
* Based on the r8187 driver, which is:
* Copyright 2005 Andrea Merello <andreamrl@tiscali.it>, et al.
*
+ * The driver was extended to the RTL8187B in 2008 by:
+ * Herton Ronaldo Krzesinski <herton@mandriva.com.br>
+ * Hin-Tak Leung <htl10@users.sourceforge.net>
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
* Magic delays and register offsets below are taken from the original
* r8187 driver sources. Thanks to Realtek for their support!
*
@@ -27,6 +32,9 @@
MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
+MODULE_AUTHOR("Herton Ronaldo Krzesinski <herton@mandriva.com.br>");
+MODULE_AUTHOR("Hin-Tak Leung <htl10@users.sourceforge.net>");
+MODULE_AUTHOR("Larry Finger <Larry.Finger@lwfinger.net>");
MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver");
MODULE_LICENSE("GPL");
@@ -91,7 +99,6 @@ static const struct ieee80211_channel rtl818x_channels[] = {
static void rtl8187_iowrite_async_cb(struct urb *urb)
{
kfree(urb->context);
- usb_free_urb(urb);
}
static void rtl8187_iowrite_async(struct rtl8187_priv *priv, __le16 addr,
@@ -128,11 +135,13 @@ static void rtl8187_iowrite_async(struct rtl8187_priv *priv, __le16 addr,
usb_fill_control_urb(urb, priv->udev, usb_sndctrlpipe(priv->udev, 0),
(unsigned char *)dr, buf, len,
rtl8187_iowrite_async_cb, buf);
+ usb_anchor_urb(urb, &priv->anchored);
rc = usb_submit_urb(urb, GFP_ATOMIC);
if (rc < 0) {
kfree(buf);
- usb_free_urb(urb);
+ usb_unanchor_urb(urb);
}
+ usb_free_urb(urb);
}
static inline void rtl818x_iowrite32_async(struct rtl8187_priv *priv,
@@ -155,30 +164,45 @@ void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data)
rtl818x_iowrite8(priv, &priv->map->PHY[2], (data >> 16) & 0xFF);
rtl818x_iowrite8(priv, &priv->map->PHY[1], (data >> 8) & 0xFF);
rtl818x_iowrite8(priv, &priv->map->PHY[0], data & 0xFF);
-
- msleep(1);
}
static void rtl8187_tx_cb(struct urb *urb)
{
struct sk_buff *skb = (struct sk_buff *)urb->context;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_hw *hw = info->driver_data[0];
+ struct ieee80211_hw *hw = info->rate_driver_data[0];
struct rtl8187_priv *priv = hw->priv;
- usb_free_urb(info->driver_data[1]);
skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) :
sizeof(struct rtl8187_tx_hdr));
- memset(&info->status, 0, sizeof(info->status));
- info->flags |= IEEE80211_TX_STAT_ACK;
- ieee80211_tx_status_irqsafe(hw, skb);
+ ieee80211_tx_info_clear_status(info);
+
+ if (!urb->status &&
+ !(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
+ priv->is_rtl8187b) {
+ skb_queue_tail(&priv->b_tx_status.queue, skb);
+
+ /* queue is "full", discard last items */
+ while (skb_queue_len(&priv->b_tx_status.queue) > 5) {
+ struct sk_buff *old_skb;
+
+ dev_dbg(&priv->udev->dev,
+ "transmit status queue full\n");
+
+ old_skb = skb_dequeue(&priv->b_tx_status.queue);
+ ieee80211_tx_status_irqsafe(hw, old_skb);
+ }
+ } else {
+ if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && !urb->status)
+ info->flags |= IEEE80211_TX_STAT_ACK;
+ ieee80211_tx_status_irqsafe(hw, skb);
+ }
}
static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
{
struct rtl8187_priv *priv = dev->priv;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
unsigned int ep;
void *buf;
struct urb *urb;
@@ -189,7 +213,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb) {
kfree_skb(skb);
- return 0;
+ return -ENOMEM;
}
flags = skb->len;
@@ -198,12 +222,12 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
flags |= ieee80211_get_tx_rate(dev, info)->hw_value << 24;
if (ieee80211_has_morefrags(((struct ieee80211_hdr *)skb->data)->frame_control))
flags |= RTL818X_TX_DESC_FLAG_MOREFRAG;
- if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
flags |= RTL818X_TX_DESC_FLAG_RTS;
flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
rts_dur = ieee80211_rts_duration(dev, priv->vif,
skb->len, info);
- } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
+ } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
flags |= RTL818X_TX_DESC_FLAG_CTS;
flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
}
@@ -214,7 +238,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
hdr->flags = cpu_to_le32(flags);
hdr->len = 0;
hdr->rts_duration = rts_dur;
- hdr->retry = cpu_to_le32(info->control.retry_limit << 8);
+ hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8);
buf = hdr;
ep = 2;
@@ -232,7 +256,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
memset(hdr, 0, sizeof(*hdr));
hdr->flags = cpu_to_le32(flags);
hdr->rts_duration = rts_dur;
- hdr->retry = cpu_to_le32(info->control.retry_limit << 8);
+ hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8);
hdr->tx_duration =
ieee80211_generic_frame_duration(dev, priv->vif,
skb->len, txrate);
@@ -244,32 +268,20 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
ep = epmap[skb_get_queue_mapping(skb)];
}
- /* FIXME: The sequence that follows is needed for this driver to
- * work with mac80211 since "mac80211: fix TX sequence numbers".
- * As with the temporary code in rt2x00, changes will be needed
- * to get proper sequence numbers on beacons. In addition, this
- * patch places the sequence number in the hardware state, which
- * limits us to a single virtual state.
- */
- if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
- if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
- priv->seqno += 0x10;
- ieee80211hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
- ieee80211hdr->seq_ctrl |= cpu_to_le16(priv->seqno);
- }
-
- info->driver_data[0] = dev;
- info->driver_data[1] = urb;
+ info->rate_driver_data[0] = dev;
+ info->rate_driver_data[1] = urb;
usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep),
buf, skb->len, rtl8187_tx_cb, skb);
+ usb_anchor_urb(urb, &priv->anchored);
rc = usb_submit_urb(urb, GFP_ATOMIC);
if (rc < 0) {
- usb_free_urb(urb);
+ usb_unanchor_urb(urb);
kfree_skb(skb);
}
+ usb_free_urb(urb);
- return 0;
+ return rc;
}
static void rtl8187_rx_cb(struct urb *urb)
@@ -282,50 +294,35 @@ static void rtl8187_rx_cb(struct urb *urb)
int rate, signal;
u32 flags;
u32 quality;
+ unsigned long f;
- spin_lock(&priv->rx_queue.lock);
+ spin_lock_irqsave(&priv->rx_queue.lock, f);
if (skb->next)
__skb_unlink(skb, &priv->rx_queue);
else {
- spin_unlock(&priv->rx_queue.lock);
+ spin_unlock_irqrestore(&priv->rx_queue.lock, f);
return;
}
- spin_unlock(&priv->rx_queue.lock);
+ spin_unlock_irqrestore(&priv->rx_queue.lock, f);
+ skb_put(skb, urb->actual_length);
if (unlikely(urb->status)) {
- usb_free_urb(urb);
dev_kfree_skb_irq(skb);
return;
}
- skb_put(skb, urb->actual_length);
if (!priv->is_rtl8187b) {
struct rtl8187_rx_hdr *hdr =
(typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr));
flags = le32_to_cpu(hdr->flags);
- signal = hdr->signal & 0x7f;
+ /* As with the RTL8187B below, the AGC is used to calculate
+ * signal strength and quality. In this case, the scaling
+ * constants are derived from the output of p54usb.
+ */
+ quality = 130 - ((41 * hdr->agc) >> 6);
+ signal = -4 - ((27 * hdr->agc) >> 6);
rx_status.antenna = (hdr->signal >> 7) & 1;
- rx_status.noise = hdr->noise;
rx_status.mactime = le64_to_cpu(hdr->mac_time);
- priv->quality = signal;
- rx_status.qual = priv->quality;
- priv->noise = hdr->noise;
- rate = (flags >> 20) & 0xF;
- if (rate > 3) { /* OFDM rate */
- if (signal > 90)
- signal = 90;
- else if (signal < 25)
- signal = 25;
- signal = 90 - signal;
- } else { /* CCK rate */
- if (signal > 95)
- signal = 95;
- else if (signal < 30)
- signal = 30;
- signal = 95 - signal;
- }
- rx_status.signal = signal;
- priv->signal = signal;
} else {
struct rtl8187b_rx_hdr *hdr =
(typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr));
@@ -343,18 +340,18 @@ static void rtl8187_rx_cb(struct urb *urb)
*/
flags = le32_to_cpu(hdr->flags);
quality = 170 - hdr->agc;
- if (quality > 100)
- quality = 100;
signal = 14 - hdr->agc / 2;
- rx_status.qual = quality;
- priv->quality = quality;
- rx_status.signal = signal;
- priv->signal = signal;
rx_status.antenna = (hdr->rssi >> 7) & 1;
rx_status.mactime = le64_to_cpu(hdr->mac_time);
- rate = (flags >> 20) & 0xF;
}
+ if (quality > 100)
+ quality = 100;
+ rx_status.qual = quality;
+ priv->quality = quality;
+ rx_status.signal = signal;
+ priv->signal = signal;
+ rate = (flags >> 20) & 0xF;
skb_trim(skb, flags & 0x0FFF);
rx_status.rate_idx = rate;
rx_status.freq = dev->conf.channel->center_freq;
@@ -366,7 +363,6 @@ static void rtl8187_rx_cb(struct urb *urb)
skb = dev_alloc_skb(RTL8187_MAX_RX);
if (unlikely(!skb)) {
- usb_free_urb(urb);
/* TODO check rx queue length and refill *somewhere* */
return;
}
@@ -378,24 +374,32 @@ static void rtl8187_rx_cb(struct urb *urb)
urb->context = skb;
skb_queue_tail(&priv->rx_queue, skb);
- usb_submit_urb(urb, GFP_ATOMIC);
+ usb_anchor_urb(urb, &priv->anchored);
+ if (usb_submit_urb(urb, GFP_ATOMIC)) {
+ usb_unanchor_urb(urb);
+ skb_unlink(skb, &priv->rx_queue);
+ dev_kfree_skb_irq(skb);
+ }
}
static int rtl8187_init_urbs(struct ieee80211_hw *dev)
{
struct rtl8187_priv *priv = dev->priv;
- struct urb *entry;
+ struct urb *entry = NULL;
struct sk_buff *skb;
struct rtl8187_rx_info *info;
+ int ret = 0;
while (skb_queue_len(&priv->rx_queue) < 8) {
skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL);
- if (!skb)
- break;
+ if (!skb) {
+ ret = -ENOMEM;
+ goto err;
+ }
entry = usb_alloc_urb(0, GFP_KERNEL);
if (!entry) {
- kfree_skb(skb);
- break;
+ ret = -ENOMEM;
+ goto err;
}
usb_fill_bulk_urb(entry, priv->udev,
usb_rcvbulkpipe(priv->udev,
@@ -406,10 +410,129 @@ static int rtl8187_init_urbs(struct ieee80211_hw *dev)
info->urb = entry;
info->dev = dev;
skb_queue_tail(&priv->rx_queue, skb);
- usb_submit_urb(entry, GFP_KERNEL);
+ usb_anchor_urb(entry, &priv->anchored);
+ ret = usb_submit_urb(entry, GFP_KERNEL);
+ if (ret) {
+ skb_unlink(skb, &priv->rx_queue);
+ usb_unanchor_urb(entry);
+ goto err;
+ }
+ usb_free_urb(entry);
}
+ return ret;
- return 0;
+err:
+ usb_free_urb(entry);
+ kfree_skb(skb);
+ usb_kill_anchored_urbs(&priv->anchored);
+ return ret;
+}
+
+static void rtl8187b_status_cb(struct urb *urb)
+{
+ struct ieee80211_hw *hw = (struct ieee80211_hw *)urb->context;
+ struct rtl8187_priv *priv = hw->priv;
+ u64 val;
+ unsigned int cmd_type;
+
+ if (unlikely(urb->status))
+ return;
+
+ /*
+ * Read from status buffer:
+ *
+ * bits [30:31] = cmd type:
+ * - 0 indicates tx beacon interrupt
+ * - 1 indicates tx close descriptor
+ *
+ * In the case of tx beacon interrupt:
+ * [0:9] = Last Beacon CW
+ * [10:29] = reserved
+ * [30:31] = 00b
+ * [32:63] = Last Beacon TSF
+ *
+ * If it's tx close descriptor:
+ * [0:7] = Packet Retry Count
+ * [8:14] = RTS Retry Count
+ * [15] = TOK
+ * [16:27] = Sequence No
+ * [28] = LS
+ * [29] = FS
+ * [30:31] = 01b
+ * [32:47] = unused (reserved?)
+ * [48:63] = MAC Used Time
+ */
+ val = le64_to_cpu(priv->b_tx_status.buf);
+
+ cmd_type = (val >> 30) & 0x3;
+ if (cmd_type == 1) {
+ unsigned int pkt_rc, seq_no;
+ bool tok;
+ struct sk_buff *skb;
+ struct ieee80211_hdr *ieee80211hdr;
+ unsigned long flags;
+
+ pkt_rc = val & 0xFF;
+ tok = val & (1 << 15);
+ seq_no = (val >> 16) & 0xFFF;
+
+ spin_lock_irqsave(&priv->b_tx_status.queue.lock, flags);
+ skb_queue_reverse_walk(&priv->b_tx_status.queue, skb) {
+ ieee80211hdr = (struct ieee80211_hdr *)skb->data;
+
+ /*
+ * While testing, it was discovered that the seq_no
+ * doesn't actually contains the sequence number.
+ * Instead of returning just the 12 bits of sequence
+ * number, hardware is returning entire sequence control
+ * (fragment number plus sequence number) in a 12 bit
+ * only field overflowing after some time. As a
+ * workaround, just consider the lower bits, and expect
+ * it's unlikely we wrongly ack some sent data
+ */
+ if ((le16_to_cpu(ieee80211hdr->seq_ctrl)
+ & 0xFFF) == seq_no)
+ break;
+ }
+ if (skb != (struct sk_buff *) &priv->b_tx_status.queue) {
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+ __skb_unlink(skb, &priv->b_tx_status.queue);
+ if (tok)
+ info->flags |= IEEE80211_TX_STAT_ACK;
+ info->status.rates[0].count = pkt_rc + 1;
+
+ ieee80211_tx_status_irqsafe(hw, skb);
+ }
+ spin_unlock_irqrestore(&priv->b_tx_status.queue.lock, flags);
+ }
+
+ usb_anchor_urb(urb, &priv->anchored);
+ if (usb_submit_urb(urb, GFP_ATOMIC))
+ usb_unanchor_urb(urb);
+}
+
+static int rtl8187b_init_status_urb(struct ieee80211_hw *dev)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ struct urb *entry;
+ int ret = 0;
+
+ entry = usb_alloc_urb(0, GFP_KERNEL);
+ if (!entry)
+ return -ENOMEM;
+
+ usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, 9),
+ &priv->b_tx_status.buf, sizeof(priv->b_tx_status.buf),
+ rtl8187b_status_cb, dev);
+
+ usb_anchor_urb(entry, &priv->anchored);
+ ret = usb_submit_urb(entry, GFP_KERNEL);
+ if (ret)
+ usb_unanchor_urb(entry);
+ usb_free_urb(entry);
+
+ return ret;
}
static int rtl8187_cmd_reset(struct ieee80211_hw *dev)
@@ -687,7 +810,7 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev)
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480);
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x2488);
rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF);
- msleep(1100);
+ msleep(100);
priv->rf->init(dev);
@@ -721,6 +844,13 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev)
rtl818x_iowrite16_idx(priv, (__le16 *)0xFFEC, 0x0800, 1);
+ priv->slot_time = 0x9;
+ priv->aifsn[0] = 2; /* AIFSN[AC_VO] */
+ priv->aifsn[1] = 2; /* AIFSN[AC_VI] */
+ priv->aifsn[2] = 7; /* AIFSN[AC_BK] */
+ priv->aifsn[3] = 3; /* AIFSN[AC_BE] */
+ rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0);
+
return 0;
}
@@ -736,6 +866,9 @@ static int rtl8187_start(struct ieee80211_hw *dev)
return ret;
mutex_lock(&priv->conf_mutex);
+
+ init_usb_anchor(&priv->anchored);
+
if (priv->is_rtl8187b) {
reg = RTL818X_RX_CONF_MGMT |
RTL818X_RX_CONF_DATA |
@@ -757,6 +890,7 @@ static int rtl8187_start(struct ieee80211_hw *dev)
(7 << 0 /* long retry limit */) |
(7 << 21 /* MAX TX DMA */));
rtl8187_init_urbs(dev);
+ rtl8187b_init_status_urb(dev);
mutex_unlock(&priv->conf_mutex);
return 0;
}
@@ -809,7 +943,6 @@ static int rtl8187_start(struct ieee80211_hw *dev)
static void rtl8187_stop(struct ieee80211_hw *dev)
{
struct rtl8187_priv *priv = dev->priv;
- struct rtl8187_rx_info *info;
struct sk_buff *skb;
u32 reg;
@@ -828,11 +961,10 @@ static void rtl8187_stop(struct ieee80211_hw *dev)
rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
- while ((skb = skb_dequeue(&priv->rx_queue))) {
- info = (struct rtl8187_rx_info *)skb->cb;
- usb_kill_urb(info->urb);
- kfree_skb(skb);
- }
+ while ((skb = skb_dequeue(&priv->b_tx_status.queue)))
+ dev_kfree_skb_any(skb);
+
+ usb_kill_anchored_urbs(&priv->anchored);
mutex_unlock(&priv->conf_mutex);
}
@@ -876,9 +1008,10 @@ static void rtl8187_remove_interface(struct ieee80211_hw *dev,
mutex_unlock(&priv->conf_mutex);
}
-static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+static int rtl8187_config(struct ieee80211_hw *dev, u32 changed)
{
struct rtl8187_priv *priv = dev->priv;
+ struct ieee80211_conf *conf = &dev->conf;
u32 reg;
mutex_lock(&priv->conf_mutex);
@@ -889,27 +1022,10 @@ static int rtl8187_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
*/
rtl818x_iowrite32(priv, &priv->map->TX_CONF,
reg | RTL818X_TX_CONF_LOOPBACK_MAC);
- msleep(10);
priv->rf->set_chan(dev, conf);
msleep(10);
rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg);
- if (!priv->is_rtl8187b) {
- rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
-
- if (conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME) {
- rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
- rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
- rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14);
- rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73);
- } else {
- rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
- rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
- rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24);
- rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5);
- }
- }
-
rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2);
rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100);
rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100);
@@ -944,6 +1060,89 @@ static int rtl8187_config_interface(struct ieee80211_hw *dev,
return 0;
}
+/*
+ * With 8187B, AC_*_PARAM clashes with FEMR definition in struct rtl818x_csr for
+ * example. Thus we have to use raw values for AC_*_PARAM register addresses.
+ */
+static __le32 *rtl8187b_ac_addr[4] = {
+ (__le32 *) 0xFFF0, /* AC_VO */
+ (__le32 *) 0xFFF4, /* AC_VI */
+ (__le32 *) 0xFFFC, /* AC_BK */
+ (__le32 *) 0xFFF8, /* AC_BE */
+};
+
+#define SIFS_TIME 0xa
+
+static void rtl8187_conf_erp(struct rtl8187_priv *priv, bool use_short_slot,
+ bool use_short_preamble)
+{
+ if (priv->is_rtl8187b) {
+ u8 difs, eifs;
+ u16 ack_timeout;
+ int queue;
+
+ if (use_short_slot) {
+ priv->slot_time = 0x9;
+ difs = 0x1c;
+ eifs = 0x53;
+ } else {
+ priv->slot_time = 0x14;
+ difs = 0x32;
+ eifs = 0x5b;
+ }
+ rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
+ rtl818x_iowrite8(priv, &priv->map->SLOT, priv->slot_time);
+ rtl818x_iowrite8(priv, &priv->map->DIFS, difs);
+
+ /*
+ * BRSR+1 on 8187B is in fact EIFS register
+ * Value in units of 4 us
+ */
+ rtl818x_iowrite8(priv, (u8 *)&priv->map->BRSR + 1, eifs);
+
+ /*
+ * For 8187B, CARRIER_SENSE_COUNTER is in fact ack timeout
+ * register. In units of 4 us like eifs register
+ * ack_timeout = ack duration + plcp + difs + preamble
+ */
+ ack_timeout = 112 + 48 + difs;
+ if (use_short_preamble)
+ ack_timeout += 72;
+ else
+ ack_timeout += 144;
+ rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER,
+ DIV_ROUND_UP(ack_timeout, 4));
+
+ for (queue = 0; queue < 4; queue++)
+ rtl818x_iowrite8(priv, (u8 *) rtl8187b_ac_addr[queue],
+ priv->aifsn[queue] * priv->slot_time +
+ SIFS_TIME);
+ } else {
+ rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
+ if (use_short_slot) {
+ rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9);
+ rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14);
+ rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14);
+ } else {
+ rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14);
+ rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24);
+ rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24);
+ }
+ }
+}
+
+static void rtl8187_bss_info_changed(struct ieee80211_hw *dev,
+ struct ieee80211_vif *vif,
+ struct ieee80211_bss_conf *info,
+ u32 changed)
+{
+ struct rtl8187_priv *priv = dev->priv;
+
+ if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_ERP_PREAMBLE))
+ rtl8187_conf_erp(priv, info->use_short_slot,
+ info->use_short_preamble);
+}
+
static void rtl8187_configure_filter(struct ieee80211_hw *dev,
unsigned int changed_flags,
unsigned int *total_flags,
@@ -976,6 +1175,42 @@ static void rtl8187_configure_filter(struct ieee80211_hw *dev,
rtl818x_iowrite32_async(priv, &priv->map->RX_CONF, priv->rx_conf);
}
+static int rtl8187_conf_tx(struct ieee80211_hw *dev, u16 queue,
+ const struct ieee80211_tx_queue_params *params)
+{
+ struct rtl8187_priv *priv = dev->priv;
+ u8 cw_min, cw_max;
+
+ if (queue > 3)
+ return -EINVAL;
+
+ cw_min = fls(params->cw_min);
+ cw_max = fls(params->cw_max);
+
+ if (priv->is_rtl8187b) {
+ priv->aifsn[queue] = params->aifs;
+
+ /*
+ * This is the structure of AC_*_PARAM registers in 8187B:
+ * - TXOP limit field, bit offset = 16
+ * - ECWmax, bit offset = 12
+ * - ECWmin, bit offset = 8
+ * - AIFS, bit offset = 0
+ */
+ rtl818x_iowrite32(priv, rtl8187b_ac_addr[queue],
+ (params->txop << 16) | (cw_max << 12) |
+ (cw_min << 8) | (params->aifs *
+ priv->slot_time + SIFS_TIME));
+ } else {
+ if (queue != 0)
+ return -EINVAL;
+
+ rtl818x_iowrite8(priv, &priv->map->CW_VAL,
+ cw_min | (cw_max << 4));
+ }
+ return 0;
+}
+
static const struct ieee80211_ops rtl8187_ops = {
.tx = rtl8187_tx,
.start = rtl8187_start,
@@ -984,7 +1219,9 @@ static const struct ieee80211_ops rtl8187_ops = {
.remove_interface = rtl8187_remove_interface,
.config = rtl8187_config,
.config_interface = rtl8187_config_interface,
+ .bss_info_changed = rtl8187_bss_info_changed,
.configure_filter = rtl8187_configure_filter,
+ .conf_tx = rtl8187_conf_tx
};
static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom)
@@ -1029,7 +1266,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
const char *chip_name;
u16 txpwr, reg;
int err, i;
- DECLARE_MAC_BUF(mac);
dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops);
if (!dev) {
@@ -1065,6 +1301,7 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
priv->mode = NL80211_IFTYPE_MONITOR;
dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
+ IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_RX_INCLUDES_FCS;
eeprom.data = dev;
@@ -1180,16 +1417,13 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
(*channel++).hw_value = txpwr >> 8;
}
- if (priv->is_rtl8187b) {
- printk(KERN_WARNING "rtl8187: 8187B chip detected. Support "
- "is EXPERIMENTAL, and could damage your\n"
- " hardware, use at your own risk\n");
- dev->flags |= IEEE80211_HW_SIGNAL_DBM;
- } else {
- dev->flags |= IEEE80211_HW_SIGNAL_UNSPEC;
- dev->max_signal = 65;
- }
+ if (priv->is_rtl8187b)
+ printk(KERN_WARNING "rtl8187: 8187B chip detected.\n");
+ /*
+ * XXX: Once this driver supports anything that requires
+ * beacons it must implement IEEE80211_TX_CTL_ASSIGN_SEQ.
+ */
dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b)
@@ -1211,9 +1445,10 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
goto err_free_dev;
}
mutex_init(&priv->conf_mutex);
+ skb_queue_head_init(&priv->b_tx_status.queue);
- printk(KERN_INFO "%s: hwaddr %s, %s V%d + %s\n",
- wiphy_name(dev->wiphy), print_mac(mac, dev->wiphy->perm_addr),
+ printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s\n",
+ wiphy_name(dev->wiphy), dev->wiphy->perm_addr,
chip_name, priv->asic_rev, priv->rf->name);
return 0;
diff --git a/drivers/net/wireless/rtl8187_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
index 1bae89903410..4e75e8e7fa90 100644
--- a/drivers/net/wireless/rtl8187_rtl8225.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c
@@ -64,7 +64,6 @@ static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data)
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
- msleep(2);
}
static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data)
@@ -98,7 +97,6 @@ static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data)
rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
- msleep(2);
}
static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
@@ -333,21 +331,21 @@ static void rtl8225_rf_init(struct ieee80211_hw *dev)
struct rtl8187_priv *priv = dev->priv;
int i;
- rtl8225_write(dev, 0x0, 0x067); msleep(1);
- rtl8225_write(dev, 0x1, 0xFE0); msleep(1);
- rtl8225_write(dev, 0x2, 0x44D); msleep(1);
- rtl8225_write(dev, 0x3, 0x441); msleep(1);
- rtl8225_write(dev, 0x4, 0x486); msleep(1);
- rtl8225_write(dev, 0x5, 0xBC0); msleep(1);
- rtl8225_write(dev, 0x6, 0xAE6); msleep(1);
- rtl8225_write(dev, 0x7, 0x82A); msleep(1);
- rtl8225_write(dev, 0x8, 0x01F); msleep(1);
- rtl8225_write(dev, 0x9, 0x334); msleep(1);
- rtl8225_write(dev, 0xA, 0xFD4); msleep(1);
- rtl8225_write(dev, 0xB, 0x391); msleep(1);
- rtl8225_write(dev, 0xC, 0x050); msleep(1);
- rtl8225_write(dev, 0xD, 0x6DB); msleep(1);
- rtl8225_write(dev, 0xE, 0x029); msleep(1);
+ rtl8225_write(dev, 0x0, 0x067);
+ rtl8225_write(dev, 0x1, 0xFE0);
+ rtl8225_write(dev, 0x2, 0x44D);
+ rtl8225_write(dev, 0x3, 0x441);
+ rtl8225_write(dev, 0x4, 0x486);
+ rtl8225_write(dev, 0x5, 0xBC0);
+ rtl8225_write(dev, 0x6, 0xAE6);
+ rtl8225_write(dev, 0x7, 0x82A);
+ rtl8225_write(dev, 0x8, 0x01F);
+ rtl8225_write(dev, 0x9, 0x334);
+ rtl8225_write(dev, 0xA, 0xFD4);
+ rtl8225_write(dev, 0xB, 0x391);
+ rtl8225_write(dev, 0xC, 0x050);
+ rtl8225_write(dev, 0xD, 0x6DB);
+ rtl8225_write(dev, 0xE, 0x029);
rtl8225_write(dev, 0xF, 0x914); msleep(100);
rtl8225_write(dev, 0x2, 0xC4D); msleep(200);
@@ -375,91 +373,89 @@ static void rtl8225_rf_init(struct ieee80211_hw *dev)
for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
- msleep(1);
rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
- msleep(1);
}
msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x00, 0x01);
+ rtl8225_write_phy_ofdm(dev, 0x01, 0x02);
+ rtl8225_write_phy_ofdm(dev, 0x02, 0x42);
+ rtl8225_write_phy_ofdm(dev, 0x03, 0x00);
+ rtl8225_write_phy_ofdm(dev, 0x04, 0x00);
+ rtl8225_write_phy_ofdm(dev, 0x05, 0x00);
+ rtl8225_write_phy_ofdm(dev, 0x06, 0x40);
+ rtl8225_write_phy_ofdm(dev, 0x07, 0x00);
+ rtl8225_write_phy_ofdm(dev, 0x08, 0x40);
+ rtl8225_write_phy_ofdm(dev, 0x09, 0xfe);
+ rtl8225_write_phy_ofdm(dev, 0x0a, 0x09);
+ rtl8225_write_phy_ofdm(dev, 0x0b, 0x80);
+ rtl8225_write_phy_ofdm(dev, 0x0c, 0x01);
+ rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3);
+ rtl8225_write_phy_ofdm(dev, 0x0f, 0x38);
+ rtl8225_write_phy_ofdm(dev, 0x10, 0x84);
+ rtl8225_write_phy_ofdm(dev, 0x11, 0x06);
+ rtl8225_write_phy_ofdm(dev, 0x12, 0x20);
+ rtl8225_write_phy_ofdm(dev, 0x13, 0x20);
+ rtl8225_write_phy_ofdm(dev, 0x14, 0x00);
+ rtl8225_write_phy_ofdm(dev, 0x15, 0x40);
+ rtl8225_write_phy_ofdm(dev, 0x16, 0x00);
+ rtl8225_write_phy_ofdm(dev, 0x17, 0x40);
+ rtl8225_write_phy_ofdm(dev, 0x18, 0xef);
+ rtl8225_write_phy_ofdm(dev, 0x19, 0x19);
+ rtl8225_write_phy_ofdm(dev, 0x1a, 0x20);
+ rtl8225_write_phy_ofdm(dev, 0x1b, 0x76);
+ rtl8225_write_phy_ofdm(dev, 0x1c, 0x04);
+ rtl8225_write_phy_ofdm(dev, 0x1e, 0x95);
+ rtl8225_write_phy_ofdm(dev, 0x1f, 0x75);
+ rtl8225_write_phy_ofdm(dev, 0x20, 0x1f);
+ rtl8225_write_phy_ofdm(dev, 0x21, 0x27);
+ rtl8225_write_phy_ofdm(dev, 0x22, 0x16);
+ rtl8225_write_phy_ofdm(dev, 0x24, 0x46);
+ rtl8225_write_phy_ofdm(dev, 0x25, 0x20);
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90);
+ rtl8225_write_phy_ofdm(dev, 0x27, 0x88);
rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
- rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
- rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
- rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
- rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
- rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
- rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
- rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
- rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
- rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
- rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x00, 0x98);
+ rtl8225_write_phy_cck(dev, 0x03, 0x20);
+ rtl8225_write_phy_cck(dev, 0x04, 0x7e);
+ rtl8225_write_phy_cck(dev, 0x05, 0x12);
+ rtl8225_write_phy_cck(dev, 0x06, 0xfc);
+ rtl8225_write_phy_cck(dev, 0x07, 0x78);
+ rtl8225_write_phy_cck(dev, 0x08, 0x2e);
+ rtl8225_write_phy_cck(dev, 0x10, 0x9b);
+ rtl8225_write_phy_cck(dev, 0x11, 0x88);
+ rtl8225_write_phy_cck(dev, 0x12, 0x47);
rtl8225_write_phy_cck(dev, 0x13, 0xd0);
rtl8225_write_phy_cck(dev, 0x19, 0x00);
rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
rtl8225_write_phy_cck(dev, 0x1b, 0x08);
rtl8225_write_phy_cck(dev, 0x40, 0x86);
- rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
- rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
- rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
- rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1);
- rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1);
- rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1);
- rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1);
- rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1);
- rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1);
- rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1);
- rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1);
- rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x41, 0x8d);
+ rtl8225_write_phy_cck(dev, 0x42, 0x15);
+ rtl8225_write_phy_cck(dev, 0x43, 0x18);
+ rtl8225_write_phy_cck(dev, 0x44, 0x1f);
+ rtl8225_write_phy_cck(dev, 0x45, 0x1e);
+ rtl8225_write_phy_cck(dev, 0x46, 0x1a);
+ rtl8225_write_phy_cck(dev, 0x47, 0x15);
+ rtl8225_write_phy_cck(dev, 0x48, 0x10);
+ rtl8225_write_phy_cck(dev, 0x49, 0x0a);
+ rtl8225_write_phy_cck(dev, 0x4a, 0x05);
+ rtl8225_write_phy_cck(dev, 0x4b, 0x02);
+ rtl8225_write_phy_cck(dev, 0x4c, 0x05);
rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
rtl8225_rf_set_tx_power(dev, 1);
/* RX antenna default to A */
- rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */
- rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */
+ rtl8225_write_phy_cck(dev, 0x10, 0x9b); /* B: 0xDB */
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); /* B: 0x10 */
rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
msleep(1);
@@ -629,7 +625,7 @@ static void rtl8225z2_b_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
- rtl8225z2_tx_gain_cck_ofdm[cck_power]);
+ rtl8225z2_tx_gain_cck_ofdm[cck_power] << 1);
msleep(1);
rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
@@ -687,22 +683,23 @@ static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
struct rtl8187_priv *priv = dev->priv;
int i;
- rtl8225_write(dev, 0x0, 0x2BF); msleep(1);
- rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
- rtl8225_write(dev, 0x2, 0x44D); msleep(1);
- rtl8225_write(dev, 0x3, 0x441); msleep(1);
- rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
- rtl8225_write(dev, 0x5, 0xC72); msleep(1);
- rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
- rtl8225_write(dev, 0x7, 0x82A); msleep(1);
- rtl8225_write(dev, 0x8, 0x03F); msleep(1);
- rtl8225_write(dev, 0x9, 0x335); msleep(1);
- rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
- rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
- rtl8225_write(dev, 0xc, 0x850); msleep(1);
- rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
- rtl8225_write(dev, 0xe, 0x02B); msleep(1);
- rtl8225_write(dev, 0xf, 0x114); msleep(100);
+ rtl8225_write(dev, 0x0, 0x2BF);
+ rtl8225_write(dev, 0x1, 0xEE0);
+ rtl8225_write(dev, 0x2, 0x44D);
+ rtl8225_write(dev, 0x3, 0x441);
+ rtl8225_write(dev, 0x4, 0x8C3);
+ rtl8225_write(dev, 0x5, 0xC72);
+ rtl8225_write(dev, 0x6, 0x0E6);
+ rtl8225_write(dev, 0x7, 0x82A);
+ rtl8225_write(dev, 0x8, 0x03F);
+ rtl8225_write(dev, 0x9, 0x335);
+ rtl8225_write(dev, 0xa, 0x9D4);
+ rtl8225_write(dev, 0xb, 0x7BB);
+ rtl8225_write(dev, 0xc, 0x850);
+ rtl8225_write(dev, 0xd, 0xCDF);
+ rtl8225_write(dev, 0xe, 0x02B);
+ rtl8225_write(dev, 0xf, 0x114);
+ msleep(100);
rtl8225_write(dev, 0x0, 0x1B7);
@@ -736,94 +733,92 @@ static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
- msleep(1);
rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
- msleep(1);
}
msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x02, 0x42); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x0a, 0x08); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x00, 0x01);
+ rtl8225_write_phy_ofdm(dev, 0x01, 0x02);
+ rtl8225_write_phy_ofdm(dev, 0x02, 0x42);
+ rtl8225_write_phy_ofdm(dev, 0x03, 0x00);
+ rtl8225_write_phy_ofdm(dev, 0x04, 0x00);
+ rtl8225_write_phy_ofdm(dev, 0x05, 0x00);
+ rtl8225_write_phy_ofdm(dev, 0x06, 0x40);
+ rtl8225_write_phy_ofdm(dev, 0x07, 0x00);
+ rtl8225_write_phy_ofdm(dev, 0x08, 0x40);
+ rtl8225_write_phy_ofdm(dev, 0x09, 0xfe);
+ rtl8225_write_phy_ofdm(dev, 0x0a, 0x08);
+ rtl8225_write_phy_ofdm(dev, 0x0b, 0x80);
+ rtl8225_write_phy_ofdm(dev, 0x0c, 0x01);
rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
- rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x11, 0x07); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x1b, 0x15); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x21, 0x17); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); //FIXME: not needed?
- rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x25, 0x00); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3);
+ rtl8225_write_phy_ofdm(dev, 0x0f, 0x38);
+ rtl8225_write_phy_ofdm(dev, 0x10, 0x84);
+ rtl8225_write_phy_ofdm(dev, 0x11, 0x07);
+ rtl8225_write_phy_ofdm(dev, 0x12, 0x20);
+ rtl8225_write_phy_ofdm(dev, 0x13, 0x20);
+ rtl8225_write_phy_ofdm(dev, 0x14, 0x00);
+ rtl8225_write_phy_ofdm(dev, 0x15, 0x40);
+ rtl8225_write_phy_ofdm(dev, 0x16, 0x00);
+ rtl8225_write_phy_ofdm(dev, 0x17, 0x40);
+ rtl8225_write_phy_ofdm(dev, 0x18, 0xef);
+ rtl8225_write_phy_ofdm(dev, 0x19, 0x19);
+ rtl8225_write_phy_ofdm(dev, 0x1a, 0x20);
+ rtl8225_write_phy_ofdm(dev, 0x1b, 0x15);
+ rtl8225_write_phy_ofdm(dev, 0x1c, 0x04);
+ rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5);
+ rtl8225_write_phy_ofdm(dev, 0x1e, 0x95);
+ rtl8225_write_phy_ofdm(dev, 0x1f, 0x75);
+ rtl8225_write_phy_ofdm(dev, 0x20, 0x1f);
+ rtl8225_write_phy_ofdm(dev, 0x21, 0x17);
+ rtl8225_write_phy_ofdm(dev, 0x22, 0x16);
+ rtl8225_write_phy_ofdm(dev, 0x23, 0x80);
+ rtl8225_write_phy_ofdm(dev, 0x24, 0x46);
+ rtl8225_write_phy_ofdm(dev, 0x25, 0x00);
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90);
+ rtl8225_write_phy_ofdm(dev, 0x27, 0x88);
rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
- rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1);
- rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1);
- rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1);
- rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1);
- rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1);
- rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1);
- rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1);
- rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1);
- rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1);
- rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x00, 0x98);
+ rtl8225_write_phy_cck(dev, 0x03, 0x20);
+ rtl8225_write_phy_cck(dev, 0x04, 0x7e);
+ rtl8225_write_phy_cck(dev, 0x05, 0x12);
+ rtl8225_write_phy_cck(dev, 0x06, 0xfc);
+ rtl8225_write_phy_cck(dev, 0x07, 0x78);
+ rtl8225_write_phy_cck(dev, 0x08, 0x2e);
+ rtl8225_write_phy_cck(dev, 0x10, 0x9b);
+ rtl8225_write_phy_cck(dev, 0x11, 0x88);
+ rtl8225_write_phy_cck(dev, 0x12, 0x47);
rtl8225_write_phy_cck(dev, 0x13, 0xd0);
rtl8225_write_phy_cck(dev, 0x19, 0x00);
rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
rtl8225_write_phy_cck(dev, 0x1b, 0x08);
rtl8225_write_phy_cck(dev, 0x40, 0x86);
- rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1);
- rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1);
- rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1);
- rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1);
- rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1);
- rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1);
- rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1);
- rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1);
- rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1);
- rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1);
- rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1);
- rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1);
+ rtl8225_write_phy_cck(dev, 0x41, 0x8d);
+ rtl8225_write_phy_cck(dev, 0x42, 0x15);
+ rtl8225_write_phy_cck(dev, 0x43, 0x18);
+ rtl8225_write_phy_cck(dev, 0x44, 0x36);
+ rtl8225_write_phy_cck(dev, 0x45, 0x35);
+ rtl8225_write_phy_cck(dev, 0x46, 0x2e);
+ rtl8225_write_phy_cck(dev, 0x47, 0x25);
+ rtl8225_write_phy_cck(dev, 0x48, 0x1c);
+ rtl8225_write_phy_cck(dev, 0x49, 0x12);
+ rtl8225_write_phy_cck(dev, 0x4a, 0x09);
+ rtl8225_write_phy_cck(dev, 0x4b, 0x04);
+ rtl8225_write_phy_cck(dev, 0x4c, 0x05);
rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
rtl8225z2_rf_set_tx_power(dev, 1);
/* RX antenna default to A */
- rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */
- rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */
+ rtl8225_write_phy_cck(dev, 0x10, 0x9b); /* B: 0xDB */
+ rtl8225_write_phy_ofdm(dev, 0x26, 0x90); /* B: 0x10 */
rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
msleep(1);
@@ -835,40 +830,38 @@ static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev)
struct rtl8187_priv *priv = dev->priv;
int i;
- rtl8225_write(dev, 0x0, 0x0B7); msleep(1);
- rtl8225_write(dev, 0x1, 0xEE0); msleep(1);
- rtl8225_write(dev, 0x2, 0x44D); msleep(1);
- rtl8225_write(dev, 0x3, 0x441); msleep(1);
- rtl8225_write(dev, 0x4, 0x8C3); msleep(1);
- rtl8225_write(dev, 0x5, 0xC72); msleep(1);
- rtl8225_write(dev, 0x6, 0x0E6); msleep(1);
- rtl8225_write(dev, 0x7, 0x82A); msleep(1);
- rtl8225_write(dev, 0x8, 0x03F); msleep(1);
- rtl8225_write(dev, 0x9, 0x335); msleep(1);
- rtl8225_write(dev, 0xa, 0x9D4); msleep(1);
- rtl8225_write(dev, 0xb, 0x7BB); msleep(1);
- rtl8225_write(dev, 0xc, 0x850); msleep(1);
- rtl8225_write(dev, 0xd, 0xCDF); msleep(1);
- rtl8225_write(dev, 0xe, 0x02B); msleep(1);
- rtl8225_write(dev, 0xf, 0x114); msleep(1);
-
- rtl8225_write(dev, 0x0, 0x1B7); msleep(1);
+ rtl8225_write(dev, 0x0, 0x0B7);
+ rtl8225_write(dev, 0x1, 0xEE0);
+ rtl8225_write(dev, 0x2, 0x44D);
+ rtl8225_write(dev, 0x3, 0x441);
+ rtl8225_write(dev, 0x4, 0x8C3);
+ rtl8225_write(dev, 0x5, 0xC72);
+ rtl8225_write(dev, 0x6, 0x0E6);
+ rtl8225_write(dev, 0x7, 0x82A);
+ rtl8225_write(dev, 0x8, 0x03F);
+ rtl8225_write(dev, 0x9, 0x335);
+ rtl8225_write(dev, 0xa, 0x9D4);
+ rtl8225_write(dev, 0xb, 0x7BB);
+ rtl8225_write(dev, 0xc, 0x850);
+ rtl8225_write(dev, 0xd, 0xCDF);
+ rtl8225_write(dev, 0xe, 0x02B);
+ rtl8225_write(dev, 0xf, 0x114);
+
+ rtl8225_write(dev, 0x0, 0x1B7);
for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
- rtl8225_write(dev, 0x1, i + 1); msleep(1);
- rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]); msleep(1);
+ rtl8225_write(dev, 0x1, i + 1);
+ rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
}
- rtl8225_write(dev, 0x3, 0x080); msleep(1);
- rtl8225_write(dev, 0x5, 0x004); msleep(1);
- rtl8225_write(dev, 0x0, 0x0B7); msleep(1);
- msleep(3000);
+ rtl8225_write(dev, 0x3, 0x080);
+ rtl8225_write(dev, 0x5, 0x004);
+ rtl8225_write(dev, 0x0, 0x0B7);
- rtl8225_write(dev, 0x2, 0xC4D); msleep(1);
- msleep(2000);
+ rtl8225_write(dev, 0x2, 0xC4D);
- rtl8225_write(dev, 0x2, 0x44D); msleep(1);
- rtl8225_write(dev, 0x0, 0x2BF); msleep(1);
+ rtl8225_write(dev, 0x2, 0x44D);
+ rtl8225_write(dev, 0x0, 0x2BF);
rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x03);
rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x07);
@@ -885,24 +878,10 @@ static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev)
for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++)
rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]);
- rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22);
- rtl818x_iowrite8(priv, &priv->map->SLOT, 9);
- rtl818x_iowrite8(priv, (u8 *)0xFFF0, 28);
- rtl818x_iowrite8(priv, (u8 *)0xFFF4, 28);
- rtl818x_iowrite8(priv, (u8 *)0xFFF8, 28);
- rtl818x_iowrite8(priv, (u8 *)0xFFFC, 28);
- rtl818x_iowrite8(priv, (u8 *)0xFF2D, 0x5B);
- rtl818x_iowrite8(priv, (u8 *)0xFF79, 0x5B);
- rtl818x_iowrite32(priv, (__le32 *)0xFFF0, (7 << 12) | (3 << 8) | 28);
- rtl818x_iowrite32(priv, (__le32 *)0xFFF4, (7 << 12) | (3 << 8) | 28);
- rtl818x_iowrite32(priv, (__le32 *)0xFFF8, (7 << 12) | (3 << 8) | 28);
- rtl818x_iowrite32(priv, (__le32 *)0xFFFC, (7 << 12) | (3 << 8) | 28);
- rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0);
-
- rtl8225_write_phy_ofdm(dev, 0x97, 0x46); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6); msleep(1);
- rtl8225_write_phy_ofdm(dev, 0x85, 0xfc); msleep(1);
- rtl8225_write_phy_cck(dev, 0xc1, 0x88); msleep(1);
+ rtl8225_write_phy_ofdm(dev, 0x97, 0x46);
+ rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6);
+ rtl8225_write_phy_ofdm(dev, 0x85, 0xfc);
+ rtl8225_write_phy_cck(dev, 0xc1, 0x88);
}
static void rtl8225_rf_stop(struct ieee80211_hw *dev)
@@ -910,7 +889,7 @@ static void rtl8225_rf_stop(struct ieee80211_hw *dev)
u8 reg;
struct rtl8187_priv *priv = dev->priv;
- rtl8225_write(dev, 0x4, 0x1f); msleep(1);
+ rtl8225_write(dev, 0x4, 0x1f);
rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
diff --git a/drivers/net/wireless/rtl8187_rtl8225.h b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.h
index 20c5b6ead0f6..20c5b6ead0f6 100644
--- a/drivers/net/wireless/rtl8187_rtl8225.h
+++ b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.h
diff --git a/drivers/net/wireless/rtl818x.h b/drivers/net/wireless/rtl818x/rtl818x.h
index 3538b15211b1..34a5555cc19c 100644
--- a/drivers/net/wireless/rtl818x.h
+++ b/drivers/net/wireless/rtl818x/rtl818x.h
@@ -191,6 +191,7 @@ struct rtl818x_rf_ops {
void (*init)(struct ieee80211_hw *);
void (*stop)(struct ieee80211_hw *);
void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *);
+ void (*conf_erp)(struct ieee80211_hw *, struct ieee80211_bss_conf *);
};
/* Tx/Rx flags are common between RTL818X chips */
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index 417e9e675fac..dd0de3a9ed4e 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -1234,7 +1234,7 @@ static void ResetRadio(struct strip *strip_info)
static void strip_write_some_more(struct tty_struct *tty)
{
- struct strip *strip_info = (struct strip *) tty->disc_data;
+ struct strip *strip_info = tty->disc_data;
/* First make sure we're connected. */
if (!strip_info || strip_info->magic != STRIP_MAGIC ||
@@ -1252,7 +1252,7 @@ static void strip_write_some_more(struct tty_struct *tty)
#endif
} else { /* Else start transmission of another packet */
- tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+ clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
strip_unlock(strip_info);
}
}
@@ -1455,8 +1455,7 @@ static void strip_send(struct strip *strip_info, struct sk_buff *skb)
*/
strip_info->tx_head = strip_info->tx_buff;
strip_info->tx_left = ptr - strip_info->tx_buff;
- strip_info->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
-
+ set_bit(TTY_DO_WRITE_WAKEUP, &strip_info->tty->flags);
/*
* 4. Debugging check to make sure we're not overflowing the buffer.
*/
@@ -1997,7 +1996,6 @@ static void deliver_packet(struct strip *strip_info, STRIP_Header * header,
#ifdef EXT_COUNTERS
strip_info->rx_bytes += packetlen;
#endif
- skb->dev->last_rx = jiffies;
netif_rx(skb);
}
}
@@ -2261,7 +2259,7 @@ static void process_message(struct strip *strip_info)
static void strip_receive_buf(struct tty_struct *tty, const unsigned char *cp,
char *fp, int count)
{
- struct strip *strip_info = (struct strip *) tty->disc_data;
+ struct strip *strip_info = tty->disc_data;
const unsigned char *end = cp + count;
if (!strip_info || strip_info->magic != STRIP_MAGIC
@@ -2455,8 +2453,7 @@ static int strip_close_low(struct net_device *dev)
if (strip_info->tty == NULL)
return -EBUSY;
- strip_info->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
-
+ clear_bit(TTY_DO_WRITE_WAKEUP, &strip_info->tty->flags);
netif_stop_queue(dev);
/*
@@ -2490,7 +2487,6 @@ static void strip_dev_setup(struct net_device *dev)
*/
dev->trans_start = 0;
- dev->last_rx = 0;
dev->tx_queue_len = 30; /* Drop after 30 frames queued */
dev->flags = 0;
@@ -2498,7 +2494,7 @@ static void strip_dev_setup(struct net_device *dev)
dev->type = ARPHRD_METRICOM; /* dtang */
dev->hard_header_len = sizeof(STRIP_Header);
/*
- * dev->priv Already holds a pointer to our struct strip
+ * netdev_priv(dev) Already holds a pointer to our struct strip
*/
*(MetricomAddress *) & dev->broadcast = broadcast_address;
@@ -2598,7 +2594,7 @@ static struct strip *strip_alloc(void)
static int strip_open(struct tty_struct *tty)
{
- struct strip *strip_info = (struct strip *) tty->disc_data;
+ struct strip *strip_info = tty->disc_data;
/*
* First make sure we're not already connected.
@@ -2669,7 +2665,7 @@ static int strip_open(struct tty_struct *tty)
static void strip_close(struct tty_struct *tty)
{
- struct strip *strip_info = (struct strip *) tty->disc_data;
+ struct strip *strip_info = tty->disc_data;
/*
* First make sure we're connected.
@@ -2695,7 +2691,7 @@ static void strip_close(struct tty_struct *tty)
static int strip_ioctl(struct tty_struct *tty, struct file *file,
unsigned int cmd, unsigned long arg)
{
- struct strip *strip_info = (struct strip *) tty->disc_data;
+ struct strip *strip_info = tty->disc_data;
/*
* First make sure we're connected.
diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
index e939a73ff794..832679396b6c 100644
--- a/drivers/net/wireless/wavelan.c
+++ b/drivers/net/wireless/wavelan.c
@@ -134,7 +134,7 @@ static inline void wv_16_on(unsigned long ioaddr, u16 hacr)
*/
static inline void wv_ints_off(struct net_device * dev)
{
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
unsigned long ioaddr = dev->base_addr;
lp->hacr &= ~HACR_INTRON;
@@ -148,7 +148,7 @@ static inline void wv_ints_off(struct net_device * dev)
*/
static inline void wv_ints_on(struct net_device * dev)
{
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
unsigned long ioaddr = dev->base_addr;
lp->hacr |= HACR_INTRON;
@@ -526,7 +526,7 @@ static inline void obram_write(unsigned long ioaddr, u16 o, u8 * b, int n)
*/
static void wv_ack(struct net_device * dev)
{
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
unsigned long ioaddr = dev->base_addr;
u16 scb_cs;
int i;
@@ -568,7 +568,7 @@ static void wv_ack(struct net_device * dev)
*/
static int wv_synchronous_cmd(struct net_device * dev, const char *str)
{
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
unsigned long ioaddr = dev->base_addr;
u16 scb_cmd;
ach_t cb;
@@ -824,7 +824,7 @@ if (lp->tx_n_in_use > 0)
*/
static void wv_82586_reconfig(struct net_device * dev)
{
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
unsigned long flags;
/* Arm the flag, will be cleard in wv_82586_config() */
@@ -859,8 +859,6 @@ static void wv_82586_reconfig(struct net_device * dev)
*/
static void wv_psa_show(psa_t * p)
{
- DECLARE_MAC_BUF(mac);
-
printk(KERN_DEBUG "##### WaveLAN PSA contents: #####\n");
printk(KERN_DEBUG "psa_io_base_addr_1: 0x%02X %02X %02X %02X\n",
p->psa_io_base_addr_1,
@@ -872,13 +870,10 @@ static void wv_psa_show(psa_t * p)
printk(KERN_DEBUG "psa_holi_params: 0x%02x, ", p->psa_holi_params);
printk("psa_int_req_no: %d\n", p->psa_int_req_no);
#ifdef DEBUG_SHOW_UNUSED
- printk(KERN_DEBUG "psa_unused0[]: %s\n",
- print_mac(mac, p->psa_unused0));
+ printk(KERN_DEBUG "psa_unused0[]: %pM\n", p->psa_unused0);
#endif /* DEBUG_SHOW_UNUSED */
- printk(KERN_DEBUG "psa_univ_mac_addr[]: %s\n",
- print_mac(mac, p->psa_univ_mac_addr));
- printk(KERN_DEBUG "psa_local_mac_addr[]: %s\n",
- print_mac(mac, p->psa_local_mac_addr));
+ printk(KERN_DEBUG "psa_univ_mac_addr[]: %pM\n", p->psa_univ_mac_addr);
+ printk(KERN_DEBUG "psa_local_mac_addr[]: %pM\n", p->psa_local_mac_addr);
printk(KERN_DEBUG "psa_univ_local_sel: %d, ",
p->psa_univ_local_sel);
printk("psa_comp_number: %d, ", p->psa_comp_number);
@@ -927,7 +922,7 @@ static void wv_psa_show(psa_t * p)
static void wv_mmc_show(struct net_device * dev)
{
unsigned long ioaddr = dev->base_addr;
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
mmr_t m;
/* Basic check */
@@ -1107,8 +1102,6 @@ static void wv_scb_show(unsigned long ioaddr)
*/
static void wv_ru_show(struct net_device * dev)
{
- /* net_local *lp = (net_local *) dev->priv; */
-
printk(KERN_DEBUG
"##### WaveLAN i82586 receiver unit status: #####\n");
printk(KERN_DEBUG "ru:");
@@ -1153,7 +1146,7 @@ static void wv_cu_show_one(struct net_device * dev, net_local * lp, int i, u16 p
*/
static void wv_cu_show(struct net_device * dev)
{
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
unsigned int i;
u16 p;
@@ -1195,7 +1188,7 @@ static void wv_local_show(struct net_device * dev)
{
net_local *lp;
- lp = (net_local *) dev->priv;
+ lp = netdev_priv(dev);
printk(KERN_DEBUG "local:");
printk(" tx_n_in_use=%d,", lp->tx_n_in_use);
@@ -1220,14 +1213,13 @@ static inline void wv_packet_info(u8 * p, /* Packet to dump */
{ /* Name of the function */
int i;
int maxi;
- DECLARE_MAC_BUF(mac);
printk(KERN_DEBUG
- "%s: %s(): dest %s, length %d\n",
- msg1, msg2, print_mac(mac, p), length);
+ "%s: %s(): dest %pM, length %d\n",
+ msg1, msg2, p, length);
printk(KERN_DEBUG
- "%s: %s(): src %s, type 0x%02X%02X\n",
- msg1, msg2, print_mac(mac, &p[6]), p[12], p[13]);
+ "%s: %s(): src %pM, type 0x%02X%02X\n",
+ msg1, msg2, &p[6], p[12], p[13]);
#ifdef DEBUG_PACKET_DUMP
@@ -1256,11 +1248,8 @@ static inline void wv_packet_info(u8 * p, /* Packet to dump */
static void wv_init_info(struct net_device * dev)
{
short ioaddr = dev->base_addr;
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
psa_t psa;
-#ifdef DEBUG_BASIC_SHOW
- DECLARE_MAC_BUF(mac);
-#endif
/* Read the parameter storage area */
psa_read(ioaddr, lp->hacr, 0, (unsigned char *) &psa, sizeof(psa));
@@ -1277,8 +1266,8 @@ static void wv_init_info(struct net_device * dev)
#ifdef DEBUG_BASIC_SHOW
/* Now, let's go for the basic stuff. */
- printk(KERN_NOTICE "%s: WaveLAN at %#x, %s, IRQ %d",
- dev->name, ioaddr, print_mac(mac, dev->dev_addr), dev->irq);
+ printk(KERN_NOTICE "%s: WaveLAN at %#x, %pM, IRQ %d",
+ dev->name, ioaddr, dev->dev_addr, dev->irq);
/* Print current network ID. */
if (psa.psa_nwid_select)
@@ -1369,7 +1358,7 @@ static en_stats *wavelan_get_stats(struct net_device * dev)
printk(KERN_DEBUG "%s: <>wavelan_get_stats()\n", dev->name);
#endif
- return (&((net_local *) dev->priv)->stats);
+ return &((net_local *)netdev_priv(dev))->stats;
}
/*------------------------------------------------------------------*/
@@ -1382,7 +1371,7 @@ static en_stats *wavelan_get_stats(struct net_device * dev)
*/
static void wavelan_set_multicast_list(struct net_device * dev)
{
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
#ifdef DEBUG_IOCTL_TRACE
printk(KERN_DEBUG "%s: ->wavelan_set_multicast_list()\n",
@@ -1716,7 +1705,7 @@ static inline void wl_spy_gather(struct net_device * dev,
*/
static inline void wl_his_gather(struct net_device * dev, u8 * stats)
{ /* Statistics to gather */
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
u8 level = stats[0] & MMR_SIGNAL_LVL;
int i;
@@ -1753,7 +1742,7 @@ static int wavelan_set_nwid(struct net_device *dev,
char *extra)
{
unsigned long ioaddr = dev->base_addr;
- net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ net_local *lp = netdev_priv(dev); /* lp is not unused */
psa_t psa;
mm_t m;
unsigned long flags;
@@ -1812,7 +1801,7 @@ static int wavelan_get_nwid(struct net_device *dev,
char *extra)
{
unsigned long ioaddr = dev->base_addr;
- net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ net_local *lp = netdev_priv(dev); /* lp is not unused */
psa_t psa;
unsigned long flags;
int ret = 0;
@@ -1844,7 +1833,7 @@ static int wavelan_set_freq(struct net_device *dev,
char *extra)
{
unsigned long ioaddr = dev->base_addr;
- net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ net_local *lp = netdev_priv(dev); /* lp is not unused */
unsigned long flags;
int ret;
@@ -1874,7 +1863,7 @@ static int wavelan_get_freq(struct net_device *dev,
char *extra)
{
unsigned long ioaddr = dev->base_addr;
- net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ net_local *lp = netdev_priv(dev); /* lp is not unused */
psa_t psa;
unsigned long flags;
int ret = 0;
@@ -1920,7 +1909,7 @@ static int wavelan_set_sens(struct net_device *dev,
char *extra)
{
unsigned long ioaddr = dev->base_addr;
- net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ net_local *lp = netdev_priv(dev); /* lp is not unused */
psa_t psa;
unsigned long flags;
int ret = 0;
@@ -1956,7 +1945,7 @@ static int wavelan_get_sens(struct net_device *dev,
char *extra)
{
unsigned long ioaddr = dev->base_addr;
- net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ net_local *lp = netdev_priv(dev); /* lp is not unused */
psa_t psa;
unsigned long flags;
int ret = 0;
@@ -1987,7 +1976,7 @@ static int wavelan_set_encode(struct net_device *dev,
char *extra)
{
unsigned long ioaddr = dev->base_addr;
- net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ net_local *lp = netdev_priv(dev); /* lp is not unused */
unsigned long flags;
psa_t psa;
int ret = 0;
@@ -2057,7 +2046,7 @@ static int wavelan_get_encode(struct net_device *dev,
char *extra)
{
unsigned long ioaddr = dev->base_addr;
- net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ net_local *lp = netdev_priv(dev); /* lp is not unused */
psa_t psa;
unsigned long flags;
int ret = 0;
@@ -2104,7 +2093,7 @@ static int wavelan_get_range(struct net_device *dev,
char *extra)
{
unsigned long ioaddr = dev->base_addr;
- net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ net_local *lp = netdev_priv(dev); /* lp is not unused */
struct iw_range *range = (struct iw_range *) extra;
unsigned long flags;
int ret = 0;
@@ -2179,7 +2168,7 @@ static int wavelan_set_qthr(struct net_device *dev,
char *extra)
{
unsigned long ioaddr = dev->base_addr;
- net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ net_local *lp = netdev_priv(dev); /* lp is not unused */
psa_t psa;
unsigned long flags;
@@ -2211,7 +2200,7 @@ static int wavelan_get_qthr(struct net_device *dev,
char *extra)
{
unsigned long ioaddr = dev->base_addr;
- net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ net_local *lp = netdev_priv(dev); /* lp is not unused */
psa_t psa;
unsigned long flags;
@@ -2239,7 +2228,7 @@ static int wavelan_set_histo(struct net_device *dev,
union iwreq_data *wrqu,
char *extra)
{
- net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ net_local *lp = netdev_priv(dev); /* lp is not unused */
/* Check the number of intervals. */
if (wrqu->data.length > 16) {
@@ -2282,7 +2271,7 @@ static int wavelan_get_histo(struct net_device *dev,
union iwreq_data *wrqu,
char *extra)
{
- net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ net_local *lp = netdev_priv(dev); /* lp is not unused */
/* Set the number of intervals. */
wrqu->data.length = lp->his_number;
@@ -2386,7 +2375,7 @@ static const struct iw_handler_def wavelan_handler_def =
static iw_stats *wavelan_get_wireless_stats(struct net_device * dev)
{
unsigned long ioaddr = dev->base_addr;
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
mmr_t m;
iw_stats *wstats;
unsigned long flags;
@@ -2461,7 +2450,7 @@ static iw_stats *wavelan_get_wireless_stats(struct net_device * dev)
static void
wv_packet_read(struct net_device * dev, u16 buf_off, int sksize)
{
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
unsigned long ioaddr = dev->base_addr;
struct sk_buff *skb;
@@ -2537,7 +2526,6 @@ wv_packet_read(struct net_device * dev, u16 buf_off, int sksize)
netif_rx(skb);
/* Keep statistics up to date */
- dev->last_rx = jiffies;
lp->stats.rx_packets++;
lp->stats.rx_bytes += sksize;
@@ -2556,7 +2544,7 @@ wv_packet_read(struct net_device * dev, u16 buf_off, int sksize)
static void wv_receive(struct net_device * dev)
{
unsigned long ioaddr = dev->base_addr;
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
fd_t fd;
rbd_t rbd;
int nreaped = 0;
@@ -2738,7 +2726,7 @@ static void wv_receive(struct net_device * dev)
*/
static int wv_packet_write(struct net_device * dev, void *buf, short length)
{
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
unsigned long ioaddr = dev->base_addr;
unsigned short txblock;
unsigned short txpred;
@@ -2869,7 +2857,7 @@ static int wv_packet_write(struct net_device * dev, void *buf, short length)
*/
static int wavelan_packet_xmit(struct sk_buff *skb, struct net_device * dev)
{
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
unsigned long flags;
char data[ETH_ZLEN];
@@ -2937,7 +2925,7 @@ static int wavelan_packet_xmit(struct sk_buff *skb, struct net_device * dev)
static int wv_mmc_init(struct net_device * dev)
{
unsigned long ioaddr = dev->base_addr;
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
psa_t psa;
mmw_t m;
int configured;
@@ -3108,7 +3096,7 @@ static int wv_mmc_init(struct net_device * dev)
*/
static int wv_ru_start(struct net_device * dev)
{
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
unsigned long ioaddr = dev->base_addr;
u16 scb_cs;
fd_t fd;
@@ -3200,7 +3188,7 @@ static int wv_ru_start(struct net_device * dev)
*/
static int wv_cu_start(struct net_device * dev)
{
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
unsigned long ioaddr = dev->base_addr;
int i;
u16 txblock;
@@ -3301,7 +3289,7 @@ static int wv_cu_start(struct net_device * dev)
*/
static int wv_82586_start(struct net_device * dev)
{
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
unsigned long ioaddr = dev->base_addr;
scp_t scp; /* system configuration pointer */
iscp_t iscp; /* intermediate scp */
@@ -3433,7 +3421,7 @@ static int wv_82586_start(struct net_device * dev)
*/
static void wv_82586_config(struct net_device * dev)
{
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
unsigned long ioaddr = dev->base_addr;
unsigned short txblock;
unsigned short txpred;
@@ -3565,15 +3553,11 @@ static void wv_82586_config(struct net_device * dev)
WAVELAN_ADDR_SIZE >> 1);
#ifdef DEBUG_CONFIG_INFO
- {
- DECLARE_MAC_BUF(mac);
printk(KERN_DEBUG
"%s: wv_82586_config(): set %d multicast addresses:\n",
dev->name, lp->mc_count);
for (dmi = dev->mc_list; dmi; dmi = dmi->next)
- printk(KERN_DEBUG " %s\n",
- print_mac(mac, dmi->dmi_addr));
- }
+ printk(KERN_DEBUG " %pM\n", dmi->dmi_addr);
#endif
}
@@ -3613,7 +3597,7 @@ static void wv_82586_config(struct net_device * dev)
*/
static void wv_82586_stop(struct net_device * dev)
{
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
unsigned long ioaddr = dev->base_addr;
u16 scb_cmd;
@@ -3650,7 +3634,7 @@ static void wv_82586_stop(struct net_device * dev)
*/
static int wv_hw_reset(struct net_device * dev)
{
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
unsigned long ioaddr = dev->base_addr;
#ifdef DEBUG_CONFIG_TRACE
@@ -3751,7 +3735,7 @@ static irqreturn_t wavelan_interrupt(int irq, void *dev_id)
printk(KERN_DEBUG "%s: ->wavelan_interrupt()\n", dev->name);
#endif
- lp = (net_local *) dev->priv;
+ lp = netdev_priv(dev);
ioaddr = dev->base_addr;
#ifdef DEBUG_INTERRUPT_INFO
@@ -3894,7 +3878,7 @@ static irqreturn_t wavelan_interrupt(int irq, void *dev_id)
*/
static void wavelan_watchdog(struct net_device * dev)
{
- net_local * lp = (net_local *)dev->priv;
+ net_local *lp = netdev_priv(dev);
u_long ioaddr = dev->base_addr;
unsigned long flags;
unsigned int nreaped;
@@ -3974,7 +3958,7 @@ static void wavelan_watchdog(struct net_device * dev)
*/
static int wavelan_open(struct net_device * dev)
{
- net_local * lp = (net_local *)dev->priv;
+ net_local *lp = netdev_priv(dev);
unsigned long flags;
#ifdef DEBUG_CALLBACK_TRACE
@@ -4029,7 +4013,7 @@ static int wavelan_open(struct net_device * dev)
*/
static int wavelan_close(struct net_device * dev)
{
- net_local *lp = (net_local *) dev->priv;
+ net_local *lp = netdev_priv(dev);
unsigned long flags;
#ifdef DEBUG_CALLBACK_TRACE
@@ -4128,8 +4112,8 @@ static int __init wavelan_config(struct net_device *dev, unsigned short ioaddr)
dev->if_port = 0;
/* Initialize device structures */
- memset(dev->priv, 0, sizeof(net_local));
- lp = (net_local *) dev->priv;
+ memset(netdev_priv(dev), 0, sizeof(net_local));
+ lp = netdev_priv(dev);
/* Back link to the device structure. */
lp->dev = dev;
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index e124b1d6267a..de717f8ffd61 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -1020,7 +1020,6 @@ wv_82593_reconfig(struct net_device * dev)
static void
wv_psa_show(psa_t * p)
{
- DECLARE_MAC_BUF(mac);
printk(KERN_DEBUG "##### wavelan psa contents: #####\n");
printk(KERN_DEBUG "psa_io_base_addr_1: 0x%02X %02X %02X %02X\n",
p->psa_io_base_addr_1,
@@ -1034,13 +1033,10 @@ wv_psa_show(psa_t * p)
printk(KERN_DEBUG "psa_holi_params: 0x%02x, ", p->psa_holi_params);
printk("psa_int_req_no: %d\n", p->psa_int_req_no);
#ifdef DEBUG_SHOW_UNUSED
- printk(KERN_DEBUG "psa_unused0[]: %s\n",
- print_mac(mac, p->psa_unused0));
+ printk(KERN_DEBUG "psa_unused0[]: %pM\n", p->psa_unused0);
#endif /* DEBUG_SHOW_UNUSED */
- printk(KERN_DEBUG "psa_univ_mac_addr[]: %s\n",
- print_mac(mac, p->psa_univ_mac_addr));
- printk(KERN_DEBUG "psa_local_mac_addr[]: %s\n",
- print_mac(mac, p->psa_local_mac_addr));
+ printk(KERN_DEBUG "psa_univ_mac_addr[]: %pM\n", p->psa_univ_mac_addr);
+ printk(KERN_DEBUG "psa_local_mac_addr[]: %pM\n", p->psa_local_mac_addr);
printk(KERN_DEBUG "psa_univ_local_sel: %d, ", p->psa_univ_local_sel);
printk("psa_comp_number: %d, ", p->psa_comp_number);
printk("psa_thr_pre_set: 0x%02x\n", p->psa_thr_pre_set);
@@ -1238,12 +1234,11 @@ wv_packet_info(u_char * p, /* Packet to dump */
{
int i;
int maxi;
- DECLARE_MAC_BUF(mac);
- printk(KERN_DEBUG "%s: %s(): dest %s, length %d\n",
- msg1, msg2, print_mac(mac, p), length);
- printk(KERN_DEBUG "%s: %s(): src %s, type 0x%02X%02X\n",
- msg1, msg2, print_mac(mac, &p[6]), p[12], p[13]);
+ printk(KERN_DEBUG "%s: %s(): dest %pM, length %d\n",
+ msg1, msg2, p, length);
+ printk(KERN_DEBUG "%s: %s(): src %pM, type 0x%02X%02X\n",
+ msg1, msg2, &p[6], p[12], p[13]);
#ifdef DEBUG_PACKET_DUMP
@@ -1274,7 +1269,6 @@ wv_init_info(struct net_device * dev)
{
unsigned int base = dev->base_addr;
psa_t psa;
- DECLARE_MAC_BUF(mac);
/* Read the parameter storage area */
psa_read(dev, 0, (unsigned char *) &psa, sizeof(psa));
@@ -1291,10 +1285,8 @@ wv_init_info(struct net_device * dev)
#ifdef DEBUG_BASIC_SHOW
/* Now, let's go for the basic stuff */
- printk(KERN_NOTICE "%s: WaveLAN: port %#x, irq %d, "
- "hw_addr %s",
- dev->name, base, dev->irq,
- print_mac(mac, dev->dev_addr));
+ printk(KERN_NOTICE "%s: WaveLAN: port %#x, irq %d, hw_addr %pM",
+ dev->name, base, dev->irq, dev->dev_addr);
/* Print current network id */
if(psa.psa_nwid_select)
@@ -2243,13 +2235,7 @@ static int wavelan_set_wap(struct net_device *dev,
char *extra)
{
#ifdef DEBUG_IOCTL_INFO
- printk(KERN_DEBUG "Set AP to : %02X:%02X:%02X:%02X:%02X:%02X\n",
- wrqu->ap_addr.sa_data[0],
- wrqu->ap_addr.sa_data[1],
- wrqu->ap_addr.sa_data[2],
- wrqu->ap_addr.sa_data[3],
- wrqu->ap_addr.sa_data[4],
- wrqu->ap_addr.sa_data[5]);
+ printk(KERN_DEBUG "Set AP to : %pM\n", wrqu->ap_addr.sa_data);
#endif /* DEBUG_IOCTL_INFO */
return -EOPNOTSUPP;
@@ -2892,7 +2878,6 @@ wv_packet_read(struct net_device * dev,
netif_rx(skb);
/* Keep stats up to date */
- dev->last_rx = jiffies;
lp->stats.rx_packets++;
lp->stats.rx_bytes += sksize;
@@ -3647,12 +3632,10 @@ wv_82593_config(struct net_device * dev)
int addrs_len = WAVELAN_ADDR_SIZE * lp->mc_count;
#ifdef DEBUG_CONFIG_INFO
- DECLARE_MAC_BUF(mac);
printk(KERN_DEBUG "%s: wv_hw_config(): set %d multicast addresses:\n",
dev->name, lp->mc_count);
for(dmi=dev->mc_list; dmi; dmi=dmi->next)
- printk(KERN_DEBUG " %s\n",
- print_mac(mac, dmi->dmi_addr));
+ printk(KERN_DEBUG " %pM\n", dmi->dmi_addr);
#endif
/* Initialize adapter's ethernet multicast addresses */
diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h
index 65ceb088f700..59bb3a55ab48 100644
--- a/drivers/net/wireless/wl3501.h
+++ b/drivers/net/wireless/wl3501.h
@@ -2,7 +2,7 @@
#define __WL3501_H__
#include <linux/spinlock.h>
-#include <net/ieee80211.h>
+#include <linux/ieee80211.h>
/* define for WLA 2.0 */
#define WL3501_BLKSZ 256
@@ -548,7 +548,7 @@ struct wl3501_80211_tx_plcp_hdr {
struct wl3501_80211_tx_hdr {
struct wl3501_80211_tx_plcp_hdr pclp_hdr;
- struct ieee80211_hdr_4addr mac_hdr;
+ struct ieee80211_hdr mac_hdr;
} __attribute__ ((packed));
/*
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 68789c6e1ce9..c99a1b6b948f 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -860,10 +860,9 @@ static int wl3501_esbq_confirm(struct wl3501_card *this)
static void wl3501_online(struct net_device *dev)
{
struct wl3501_card *this = netdev_priv(dev);
- DECLARE_MAC_BUF(mac);
- printk(KERN_INFO "%s: Wireless LAN online. BSSID: %s\n",
- dev->name, print_mac(mac, this->bssid));
+ printk(KERN_INFO "%s: Wireless LAN online. BSSID: %pM\n",
+ dev->name, this->bssid);
netif_wake_queue(dev);
}
@@ -1014,7 +1013,6 @@ static inline void wl3501_md_ind_interrupt(struct net_device *dev,
wl3501_receive(this, skb->data, pkt_len);
skb_put(skb, pkt_len);
skb->protocol = eth_type_trans(skb, dev);
- dev->last_rx = jiffies;
this->stats.rx_packets++;
this->stats.rx_bytes += skb->len;
netif_rx(skb);
@@ -1965,7 +1963,6 @@ static int wl3501_config(struct pcmcia_device *link)
struct net_device *dev = link->priv;
int i = 0, j, last_fn, last_ret;
struct wl3501_card *this;
- DECLARE_MAC_BUF(mac);
/* Try allocating IO ports. This tries a few fixed addresses. If you
* want, you can also read the card's config table to pick addresses --
@@ -2024,9 +2021,9 @@ static int wl3501_config(struct pcmcia_device *link)
/* print probe information */
printk(KERN_INFO "%s: wl3501 @ 0x%3.3x, IRQ %d, "
- "MAC addr in flash ROM:%s\n",
+ "MAC addr in flash ROM:%pM\n",
dev->name, this->base_addr, (int)dev->irq,
- print_mac(mac, dev->dev_addr));
+ dev->dev_addr);
/*
* Initialize card parameters - added by jss
*/
diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c
index b16ec6e5f0e3..b45c27d42fd8 100644
--- a/drivers/net/wireless/zd1201.c
+++ b/drivers/net/wireless/zd1201.c
@@ -17,11 +17,11 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/wireless.h>
+#include <linux/ieee80211.h>
#include <net/iw_handler.h>
#include <linux/string.h>
#include <linux/if_arp.h>
#include <linux/firmware.h>
-#include <net/ieee80211.h>
#include "zd1201.h"
static struct usb_device_id zd1201_table[] = {
@@ -328,7 +328,6 @@ static void zd1201_usbrx(struct urb *urb)
memcpy(skb_put(skb, 2), &data[datalen-24], 2);
memcpy(skb_put(skb, len), data, len);
skb->protocol = eth_type_trans(skb, zd->dev);
- skb->dev->last_rx = jiffies;
zd->stats.rx_packets++;
zd->stats.rx_bytes += skb->len;
netif_rx(skb);
@@ -346,7 +345,7 @@ static void zd1201_usbrx(struct urb *urb)
frag = kmalloc(sizeof(*frag), GFP_ATOMIC);
if (!frag)
goto resubmit;
- skb = dev_alloc_skb(IEEE80211_DATA_LEN +14+2);
+ skb = dev_alloc_skb(IEEE80211_MAX_DATA_LEN +14+2);
if (!skb) {
kfree(frag);
goto resubmit;
@@ -385,7 +384,6 @@ static void zd1201_usbrx(struct urb *urb)
memcpy(skb_put(skb, len), data+8, len);
}
skb->protocol = eth_type_trans(skb, zd->dev);
- skb->dev->last_rx = jiffies;
zd->stats.rx_packets++;
zd->stats.rx_bytes += skb->len;
netif_rx(skb);
@@ -745,7 +743,7 @@ static int zd1201_join(struct zd1201 *zd, char *essid, int essidlen)
static int zd1201_net_open(struct net_device *dev)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
/* Start MAC with wildcard if no essid set */
if (!zd->mac_enabled)
@@ -783,7 +781,7 @@ static int zd1201_net_stop(struct net_device *dev)
*/
static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
unsigned char *txbuf = zd->txdata;
int txbuflen, pad = 0, err;
struct urb *urb = zd->tx_urb;
@@ -833,7 +831,7 @@ static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
static void zd1201_tx_timeout(struct net_device *dev)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
if (!zd)
return;
@@ -848,7 +846,7 @@ static void zd1201_tx_timeout(struct net_device *dev)
static int zd1201_set_mac_address(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
int err;
if (!zd)
@@ -865,21 +863,21 @@ static int zd1201_set_mac_address(struct net_device *dev, void *p)
static struct net_device_stats *zd1201_get_stats(struct net_device *dev)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
return &zd->stats;
}
static struct iw_statistics *zd1201_get_wireless_stats(struct net_device *dev)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
return &zd->iwstats;
}
static void zd1201_set_multicast(struct net_device *dev)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
struct dev_mc_list *mc = dev->mc_list;
unsigned char reqbuf[ETH_ALEN*ZD1201_MAXMULTI];
int i;
@@ -899,7 +897,7 @@ static void zd1201_set_multicast(struct net_device *dev)
static int zd1201_config_commit(struct net_device *dev,
struct iw_request_info *info, struct iw_point *data, char *essid)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
return zd1201_mac_reset(zd);
}
@@ -914,7 +912,7 @@ static int zd1201_get_name(struct net_device *dev,
static int zd1201_set_freq(struct net_device *dev,
struct iw_request_info *info, struct iw_freq *freq, char *extra)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
short channel = 0;
int err;
@@ -939,7 +937,7 @@ static int zd1201_set_freq(struct net_device *dev,
static int zd1201_get_freq(struct net_device *dev,
struct iw_request_info *info, struct iw_freq *freq, char *extra)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
short channel;
int err;
@@ -955,7 +953,7 @@ static int zd1201_get_freq(struct net_device *dev,
static int zd1201_set_mode(struct net_device *dev,
struct iw_request_info *info, __u32 *mode, char *extra)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
short porttype, monitor = 0;
unsigned char buffer[IW_ESSID_MAX_SIZE+2];
int err;
@@ -1017,7 +1015,7 @@ static int zd1201_set_mode(struct net_device *dev,
static int zd1201_get_mode(struct net_device *dev,
struct iw_request_info *info, __u32 *mode, char *extra)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
short porttype;
int err;
@@ -1093,7 +1091,7 @@ static int zd1201_get_range(struct net_device *dev,
static int zd1201_get_wap(struct net_device *dev,
struct iw_request_info *info, struct sockaddr *ap_addr, char *extra)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
unsigned char buffer[6];
if (!zd1201_getconfig(zd, ZD1201_RID_COMMSQUALITY, buffer, 6)) {
@@ -1121,7 +1119,7 @@ static int zd1201_set_scan(struct net_device *dev,
static int zd1201_get_scan(struct net_device *dev,
struct iw_request_info *info, struct iw_point *srq, char *extra)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
int err, i, j, enabled_save;
struct iw_event iwe;
char *cev = extra;
@@ -1213,7 +1211,7 @@ static int zd1201_get_scan(struct net_device *dev,
static int zd1201_set_essid(struct net_device *dev,
struct iw_request_info *info, struct iw_point *data, char *essid)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
if (data->length > IW_ESSID_MAX_SIZE)
return -EINVAL;
@@ -1228,7 +1226,7 @@ static int zd1201_set_essid(struct net_device *dev,
static int zd1201_get_essid(struct net_device *dev,
struct iw_request_info *info, struct iw_point *data, char *essid)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
memcpy(essid, zd->essid, zd->essidlen);
data->flags = 1;
@@ -1249,7 +1247,7 @@ static int zd1201_get_nick(struct net_device *dev, struct iw_request_info *info,
static int zd1201_set_rate(struct net_device *dev,
struct iw_request_info *info, struct iw_param *rrq, char *extra)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
short rate;
int err;
@@ -1282,7 +1280,7 @@ static int zd1201_set_rate(struct net_device *dev,
static int zd1201_get_rate(struct net_device *dev,
struct iw_request_info *info, struct iw_param *rrq, char *extra)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
short rate;
int err;
@@ -1315,7 +1313,7 @@ static int zd1201_get_rate(struct net_device *dev,
static int zd1201_set_rts(struct net_device *dev, struct iw_request_info *info,
struct iw_param *rts, char *extra)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
int err;
short val = rts->value;
@@ -1335,7 +1333,7 @@ static int zd1201_set_rts(struct net_device *dev, struct iw_request_info *info,
static int zd1201_get_rts(struct net_device *dev, struct iw_request_info *info,
struct iw_param *rts, char *extra)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
short rtst;
int err;
@@ -1352,7 +1350,7 @@ static int zd1201_get_rts(struct net_device *dev, struct iw_request_info *info,
static int zd1201_set_frag(struct net_device *dev, struct iw_request_info *info,
struct iw_param *frag, char *extra)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
int err;
short val = frag->value;
@@ -1373,7 +1371,7 @@ static int zd1201_set_frag(struct net_device *dev, struct iw_request_info *info,
static int zd1201_get_frag(struct net_device *dev, struct iw_request_info *info,
struct iw_param *frag, char *extra)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
short fragt;
int err;
@@ -1402,7 +1400,7 @@ static int zd1201_get_retry(struct net_device *dev,
static int zd1201_set_encode(struct net_device *dev,
struct iw_request_info *info, struct iw_point *erq, char *key)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
short i;
int err, rid;
@@ -1459,7 +1457,7 @@ static int zd1201_set_encode(struct net_device *dev,
static int zd1201_get_encode(struct net_device *dev,
struct iw_request_info *info, struct iw_point *erq, char *key)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
short i;
int err;
@@ -1492,7 +1490,7 @@ static int zd1201_get_encode(struct net_device *dev,
static int zd1201_set_power(struct net_device *dev,
struct iw_request_info *info, struct iw_param *vwrq, char *extra)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
short enabled, duration, level;
int err;
@@ -1531,7 +1529,7 @@ out:
static int zd1201_get_power(struct net_device *dev,
struct iw_request_info *info, struct iw_param *vwrq, char *extra)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
short enabled, level, duration;
int err;
@@ -1618,7 +1616,7 @@ static const iw_handler zd1201_iw_handler[] =
static int zd1201_set_hostauth(struct net_device *dev,
struct iw_request_info *info, struct iw_param *rrq, char *extra)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
if (!zd->ap)
return -EOPNOTSUPP;
@@ -1629,7 +1627,7 @@ static int zd1201_set_hostauth(struct net_device *dev,
static int zd1201_get_hostauth(struct net_device *dev,
struct iw_request_info *info, struct iw_param *rrq, char *extra)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
short hostauth;
int err;
@@ -1648,7 +1646,7 @@ static int zd1201_get_hostauth(struct net_device *dev,
static int zd1201_auth_sta(struct net_device *dev,
struct iw_request_info *info, struct sockaddr *sta, char *extra)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
unsigned char buffer[10];
if (!zd->ap)
@@ -1664,7 +1662,7 @@ static int zd1201_auth_sta(struct net_device *dev,
static int zd1201_set_maxassoc(struct net_device *dev,
struct iw_request_info *info, struct iw_param *rrq, char *extra)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
int err;
if (!zd->ap)
@@ -1679,7 +1677,7 @@ static int zd1201_set_maxassoc(struct net_device *dev,
static int zd1201_get_maxassoc(struct net_device *dev,
struct iw_request_info *info, struct iw_param *rrq, char *extra)
{
- struct zd1201 *zd = (struct zd1201 *)dev->priv;
+ struct zd1201 *zd = netdev_priv(dev);
short maxassoc;
int err;
@@ -1731,6 +1729,7 @@ static int zd1201_probe(struct usb_interface *interface,
const struct usb_device_id *id)
{
struct zd1201 *zd;
+ struct net_device *dev;
struct usb_device *usb;
int err;
short porttype;
@@ -1738,9 +1737,12 @@ static int zd1201_probe(struct usb_interface *interface,
usb = interface_to_usbdev(interface);
- zd = kzalloc(sizeof(struct zd1201), GFP_KERNEL);
- if (!zd)
+ dev = alloc_etherdev(sizeof(*zd));
+ if (!dev)
return -ENOMEM;
+ zd = netdev_priv(dev);
+ zd->dev = dev;
+
zd->ap = ap;
zd->usb = usb;
zd->removed = 0;
@@ -1775,34 +1777,29 @@ static int zd1201_probe(struct usb_interface *interface,
if (err)
goto err_start;
- zd->dev = alloc_etherdev(0);
- if (!zd->dev)
- goto err_start;
-
- zd->dev->priv = zd;
- zd->dev->open = zd1201_net_open;
- zd->dev->stop = zd1201_net_stop;
- zd->dev->get_stats = zd1201_get_stats;
- zd->dev->wireless_handlers =
+ dev->open = zd1201_net_open;
+ dev->stop = zd1201_net_stop;
+ dev->get_stats = zd1201_get_stats;
+ dev->wireless_handlers =
(struct iw_handler_def *)&zd1201_iw_handlers;
- zd->dev->hard_start_xmit = zd1201_hard_start_xmit;
- zd->dev->watchdog_timeo = ZD1201_TX_TIMEOUT;
- zd->dev->tx_timeout = zd1201_tx_timeout;
- zd->dev->set_multicast_list = zd1201_set_multicast;
- zd->dev->set_mac_address = zd1201_set_mac_address;
- strcpy(zd->dev->name, "wlan%d");
+ dev->hard_start_xmit = zd1201_hard_start_xmit;
+ dev->watchdog_timeo = ZD1201_TX_TIMEOUT;
+ dev->tx_timeout = zd1201_tx_timeout;
+ dev->set_multicast_list = zd1201_set_multicast;
+ dev->set_mac_address = zd1201_set_mac_address;
+ strcpy(dev->name, "wlan%d");
err = zd1201_getconfig(zd, ZD1201_RID_CNFOWNMACADDR,
- zd->dev->dev_addr, zd->dev->addr_len);
+ dev->dev_addr, dev->addr_len);
if (err)
- goto err_net;
+ goto err_start;
/* Set wildcard essid to match zd->essid */
*(__le16 *)buf = cpu_to_le16(0);
err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf,
IW_ESSID_MAX_SIZE+2, 1);
if (err)
- goto err_net;
+ goto err_start;
if (zd->ap)
porttype = ZD1201_PORTTYPE_AP;
@@ -1810,30 +1807,28 @@ static int zd1201_probe(struct usb_interface *interface,
porttype = ZD1201_PORTTYPE_BSS;
err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype);
if (err)
- goto err_net;
+ goto err_start;
- SET_NETDEV_DEV(zd->dev, &usb->dev);
+ SET_NETDEV_DEV(dev, &usb->dev);
- err = register_netdev(zd->dev);
+ err = register_netdev(dev);
if (err)
- goto err_net;
+ goto err_start;
dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n",
- zd->dev->name);
+ dev->name);
usb_set_intfdata(interface, zd);
zd1201_enable(zd); /* zd1201 likes to startup enabled, */
zd1201_disable(zd); /* interfering with all the wifis in range */
return 0;
-err_net:
- free_netdev(zd->dev);
err_start:
/* Leave the device in reset state */
zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0);
err_zd:
usb_free_urb(zd->tx_urb);
usb_free_urb(zd->rx_urb);
- kfree(zd);
+ free_netdev(dev);
return err;
}
@@ -1846,10 +1841,6 @@ static void zd1201_disconnect(struct usb_interface *interface)
if (!zd)
return;
usb_set_intfdata(interface, NULL);
- if (zd->dev) {
- unregister_netdev(zd->dev);
- free_netdev(zd->dev);
- }
hlist_for_each_entry_safe(frag, node, node2, &zd->fraglist, fnode) {
hlist_del_init(&frag->fnode);
@@ -1865,7 +1856,11 @@ static void zd1201_disconnect(struct usb_interface *interface)
usb_kill_urb(zd->rx_urb);
usb_free_urb(zd->rx_urb);
}
- kfree(zd);
+
+ if (zd->dev) {
+ unregister_netdev(zd->dev);
+ free_netdev(zd->dev);
+ }
}
#ifdef CONFIG_PM
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index e0ac58b8ff1f..f1519143f8a6 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -378,7 +378,6 @@ int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
[0] = { .addr = CR_MAC_ADDR_P1 },
[1] = { .addr = CR_MAC_ADDR_P2 },
};
- DECLARE_MAC_BUF(mac);
if (mac_addr) {
reqs[0].value = (mac_addr[3] << 24)
@@ -387,8 +386,7 @@ int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
| mac_addr[0];
reqs[1].value = (mac_addr[5] << 8)
| mac_addr[4];
- dev_dbg_f(zd_chip_dev(chip),
- "mac addr %s\n", print_mac(mac, mac_addr));
+ dev_dbg_f(zd_chip_dev(chip), "mac addr %pM\n", mac_addr);
} else {
dev_dbg_f(zd_chip_dev(chip), "set NULL mac\n");
}
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index cac732f4047f..9caa96a13586 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -171,7 +171,7 @@ int zd_mac_init_hw(struct ieee80211_hw *hw)
r = zd_reg2alpha2(mac->regdomain, alpha2);
if (!r)
- regulatory_hint(hw->wiphy, alpha2, NULL);
+ regulatory_hint(hw->wiphy, alpha2);
r = 0;
disable_int:
@@ -296,15 +296,14 @@ static void zd_op_stop(struct ieee80211_hw *hw)
* If no status information has been requested, the skb is freed.
*/
static void tx_status(struct ieee80211_hw *hw, struct sk_buff *skb,
- u32 flags, int ackssi, bool success)
+ int ackssi, bool success)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- memset(&info->status, 0, sizeof(info->status));
+ ieee80211_tx_info_clear_status(info);
- if (!success)
- info->status.excessive_retries = 1;
- info->flags |= flags;
+ if (success)
+ info->flags |= IEEE80211_TX_STAT_ACK;
info->status.ack_signal = ackssi;
ieee80211_tx_status_irqsafe(hw, skb);
}
@@ -326,7 +325,7 @@ void zd_mac_tx_failed(struct ieee80211_hw *hw)
if (skb == NULL)
return;
- tx_status(hw, skb, 0, 0, 0);
+ tx_status(hw, skb, 0, 0);
}
/**
@@ -342,12 +341,12 @@ void zd_mac_tx_failed(struct ieee80211_hw *hw)
void zd_mac_tx_to_dev(struct sk_buff *skb, int error)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_hw *hw = info->driver_data[0];
+ struct ieee80211_hw *hw = info->rate_driver_data[0];
skb_pull(skb, sizeof(struct zd_ctrlset));
if (unlikely(error ||
(info->flags & IEEE80211_TX_CTL_NO_ACK))) {
- tx_status(hw, skb, 0, 0, !error);
+ tx_status(hw, skb, 0, !error);
} else {
struct sk_buff_head *q =
&zd_hw_mac(hw)->ack_wait_queue;
@@ -406,7 +405,8 @@ static int zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length)
}
static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
- struct ieee80211_hdr *header, u32 flags)
+ struct ieee80211_hdr *header,
+ struct ieee80211_tx_info *info)
{
/*
* CONTROL TODO:
@@ -417,7 +417,7 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
cs->control = 0;
/* First fragment */
- if (flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+ if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
cs->control |= ZD_CS_NEED_RANDOM_BACKOFF;
/* Multicast */
@@ -428,10 +428,10 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
if (ieee80211_is_pspoll(header->frame_control))
cs->control |= ZD_CS_PS_POLL_FRAME;
- if (flags & IEEE80211_TX_CTL_USE_RTS_CTS)
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS)
cs->control |= ZD_CS_RTS;
- if (flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
cs->control |= ZD_CS_SELF_CTS;
/* FIXME: Management frame? */
@@ -517,12 +517,12 @@ static int fill_ctrlset(struct zd_mac *mac,
txrate = ieee80211_get_tx_rate(mac->hw, info);
cs->modulation = txrate->hw_value;
- if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE)
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
cs->modulation = txrate->hw_value_short;
cs->tx_length = cpu_to_le16(frag_len);
- cs_set_control(mac, cs, hdr, info->flags);
+ cs_set_control(mac, cs, hdr, info);
packet_length = frag_len + sizeof(struct zd_ctrlset) + 10;
ZD_ASSERT(packet_length <= 0xffff);
@@ -577,7 +577,7 @@ static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
if (r)
return r;
- info->driver_data[0] = hw;
+ info->rate_driver_data[0] = hw;
r = zd_usb_tx(&mac->chip.usb, skb);
if (r)
@@ -618,7 +618,7 @@ static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr,
if (likely(!memcmp(tx_hdr->addr2, rx_hdr->addr1, ETH_ALEN)))
{
__skb_unlink(skb, q);
- tx_status(hw, skb, IEEE80211_TX_STAT_ACK, stats->signal, 1);
+ tx_status(hw, skb, stats->signal, 1);
goto out;
}
}
@@ -743,9 +743,11 @@ static void zd_op_remove_interface(struct ieee80211_hw *hw,
zd_write_mac_addr(&mac->chip, NULL);
}
-static int zd_op_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
+static int zd_op_config(struct ieee80211_hw *hw, u32 changed)
{
struct zd_mac *mac = zd_hw_mac(hw);
+ struct ieee80211_conf *conf = &hw->conf;
+
return zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
}
@@ -852,14 +854,12 @@ static void zd_op_configure_filter(struct ieee80211_hw *hw,
if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) {
zd_mc_add_all(&hash);
} else {
- DECLARE_MAC_BUF(macbuf);
-
zd_mc_clear(&hash);
for (i = 0; i < mc_count; i++) {
if (!mclist)
break;
- dev_dbg_f(zd_mac_dev(mac), "mc addr %s\n",
- print_mac(macbuf, mclist->dmi_addr));
+ dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n",
+ mclist->dmi_addr);
zd_mc_add_addr(&hash, mclist->dmi_addr);
mclist = mclist->next;
}
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index a3ccd8c1c716..04c139666965 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -909,7 +909,7 @@ free_urb:
* it might be freed by zd_mac_tx_to_dev or mac80211)
*/
info = IEEE80211_SKB_CB(skb);
- usb = &zd_hw_mac(info->driver_data[0])->chip.usb;
+ usb = &zd_hw_mac(info->rate_driver_data[0])->chip.usb;
zd_mac_tx_to_dev(skb, urb->status);
free_tx_urb(usb, urb);
tx_dec_submitted_urbs(usb);
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 6d017adc914a..761635be9104 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -196,7 +196,7 @@ static void rx_refill_timeout(unsigned long data)
{
struct net_device *dev = (struct net_device *)data;
struct netfront_info *np = netdev_priv(dev);
- netif_rx_schedule(dev, &np->napi);
+ netif_rx_schedule(&np->napi);
}
static int netfront_tx_slot_available(struct netfront_info *np)
@@ -328,7 +328,7 @@ static int xennet_open(struct net_device *dev)
xennet_alloc_rx_buffers(dev);
np->rx.sring->rsp_event = np->rx.rsp_cons + 1;
if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx))
- netif_rx_schedule(dev, &np->napi);
+ netif_rx_schedule(&np->napi);
}
spin_unlock_bh(&np->rx_lock);
@@ -841,7 +841,6 @@ static int handle_incoming_queue(struct net_device *dev,
/* Pass it up. */
netif_receive_skb(skb);
- dev->last_rx = jiffies;
}
return packets_dropped;
@@ -980,7 +979,7 @@ err:
RING_FINAL_CHECK_FOR_RESPONSES(&np->rx, more_to_do);
if (!more_to_do)
- __netif_rx_complete(dev, napi);
+ __netif_rx_complete(napi);
local_irq_restore(flags);
}
@@ -1311,7 +1310,7 @@ static irqreturn_t xennet_interrupt(int irq, void *dev_id)
xennet_tx_buf_gc(dev);
/* Under tx_lock: protects access to rx shared-ring indexes. */
if (RING_HAS_UNCONSUMED_RESPONSES(&np->rx))
- netif_rx_schedule(dev, &np->napi);
+ netif_rx_schedule(&np->napi);
}
spin_unlock_irqrestore(&np->tx_lock, flags);
diff --git a/drivers/net/xtsonic.c b/drivers/net/xtsonic.c
index da42aa06a3ba..03a3f34e9039 100644
--- a/drivers/net/xtsonic.c
+++ b/drivers/net/xtsonic.c
@@ -239,8 +239,6 @@ int __init xtsonic_probe(struct platform_device *pdev)
struct resource *resmem, *resirq;
int err = 0;
- DECLARE_MAC_BUF(mac);
-
if ((resmem = platform_get_resource(pdev, IORESOURCE_MEM, 0)) == NULL)
return -ENODEV;
@@ -263,8 +261,8 @@ int __init xtsonic_probe(struct platform_device *pdev)
if ((err = register_netdev(dev)))
goto out1;
- printk("%s: SONIC ethernet @%08lx, MAC %s, IRQ %d\n", dev->name,
- dev->base_addr, print_mac(mac, dev->dev_addr), dev->irq);
+ printk("%s: SONIC ethernet @%08lx, MAC %pM, IRQ %d\n", dev->name,
+ dev->base_addr, dev->dev_addr, dev->irq);
return 0;
diff --git a/drivers/net/yellowfin.c b/drivers/net/yellowfin.c
index 57e1f495b9fc..cf9712922778 100644
--- a/drivers/net/yellowfin.c
+++ b/drivers/net/yellowfin.c
@@ -355,6 +355,16 @@ static int yellowfin_close(struct net_device *dev);
static void set_rx_mode(struct net_device *dev);
static const struct ethtool_ops ethtool_ops;
+static const struct net_device_ops netdev_ops = {
+ .ndo_open = yellowfin_open,
+ .ndo_stop = yellowfin_close,
+ .ndo_start_xmit = yellowfin_start_xmit,
+ .ndo_set_multicast_list = set_rx_mode,
+ .ndo_change_mtu = eth_change_mtu,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_do_ioctl = netdev_ioctl,
+ .ndo_tx_timeout = yellowfin_tx_timeout,
+};
static int __devinit yellowfin_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
@@ -374,7 +384,6 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev,
#else
int bar = 1;
#endif
- DECLARE_MAC_BUF(mac);
/* when built into the kernel, we only print version if device is found */
#ifndef MODULE
@@ -465,13 +474,8 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev,
np->duplex_lock = 1;
/* The Yellowfin-specific entries in the device structure. */
- dev->open = &yellowfin_open;
- dev->hard_start_xmit = &yellowfin_start_xmit;
- dev->stop = &yellowfin_close;
- dev->set_multicast_list = &set_rx_mode;
- dev->do_ioctl = &netdev_ioctl;
+ dev->netdev_ops = &netdev_ops;
SET_ETHTOOL_OPS(dev, &ethtool_ops);
- dev->tx_timeout = yellowfin_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
if (mtu)
@@ -481,10 +485,10 @@ static int __devinit yellowfin_init_one(struct pci_dev *pdev,
if (i)
goto err_out_unmap_status;
- printk(KERN_INFO "%s: %s type %8x at %p, %s, IRQ %d.\n",
+ printk(KERN_INFO "%s: %s type %8x at %p, %pM, IRQ %d.\n",
dev->name, pci_id_tbl[chip_idx].name,
ioread32(ioaddr + ChipRev), ioaddr,
- print_mac(mac, dev->dev_addr), irq);
+ dev->dev_addr, irq);
if (np->drv_flags & HasMII) {
int phy, phy_idx = 0;
@@ -1100,11 +1104,9 @@ static int yellowfin_rx(struct net_device *dev)
memcmp(le32_to_cpu(yp->rx_ring_dma +
entry*sizeof(struct yellowfin_desc)),
"\377\377\377\377\377\377", 6) != 0) {
- if (bogus_rx++ == 0) {
- DECLARE_MAC_BUF(mac);
- printk(KERN_WARNING "%s: Bad frame to %s\n",
- dev->name, print_mac(mac, buf_addr));
- }
+ if (bogus_rx++ == 0)
+ printk(KERN_WARNING "%s: Bad frame to %pM\n",
+ dev->name, buf_addr);
#endif
} else {
struct sk_buff *skb;
@@ -1141,7 +1143,6 @@ static int yellowfin_rx(struct net_device *dev)
}
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
}
@@ -1423,14 +1424,3 @@ static void __exit yellowfin_cleanup (void)
module_init(yellowfin_init);
module_exit(yellowfin_cleanup);
-
-/*
- * Local variables:
- * compile-command: "gcc -DMODULE -Wall -Wstrict-prototypes -O6 -c yellowfin.c"
- * compile-command-alphaLX: "gcc -DMODULE -Wall -Wstrict-prototypes -O2 -c yellowfin.c -fomit-frame-pointer -fno-strength-reduce -mno-fp-regs -Wa,-m21164a -DBWX_USABLE -DBWIO_ENABLED"
- * simple-compile-command: "gcc -DMODULE -O6 -c yellowfin.c"
- * c-indent-level: 4
- * c-basic-offset: 4
- * tab-width: 4
- * End:
- */
diff --git a/drivers/net/znet.c b/drivers/net/znet.c
index a86c022d6a94..f0b15c9347d0 100644
--- a/drivers/net/znet.c
+++ b/drivers/net/znet.c
@@ -167,7 +167,7 @@ static void znet_tx_timeout (struct net_device *dev);
/* Request needed resources */
static int znet_request_resources (struct net_device *dev)
{
- struct znet_private *znet = dev->priv;
+ struct znet_private *znet = netdev_priv(dev);
unsigned long flags;
if (request_irq (dev->irq, &znet_interrupt, 0, "ZNet", dev))
@@ -201,7 +201,7 @@ static int znet_request_resources (struct net_device *dev)
static void znet_release_resources (struct net_device *dev)
{
- struct znet_private *znet = dev->priv;
+ struct znet_private *znet = netdev_priv(dev);
unsigned long flags;
release_region (znet->sia_base, znet->sia_size);
@@ -216,7 +216,7 @@ static void znet_release_resources (struct net_device *dev)
/* Keep the magical SIA stuff in a single function... */
static void znet_transceiver_power (struct net_device *dev, int on)
{
- struct znet_private *znet = dev->priv;
+ struct znet_private *znet = netdev_priv(dev);
unsigned char v;
/* Turn on/off the 82501 SIA, using zenith-specific magic. */
@@ -235,7 +235,7 @@ static void znet_transceiver_power (struct net_device *dev, int on)
Also used from hardware_init. */
static void znet_set_multicast_list (struct net_device *dev)
{
- struct znet_private *znet = dev->priv;
+ struct znet_private *znet = netdev_priv(dev);
short ioaddr = dev->base_addr;
struct i82593_conf_block *cfblk = &znet->i593_init;
@@ -370,7 +370,6 @@ static int __init znet_probe (void)
struct net_device *dev;
char *p;
int err = -ENOMEM;
- DECLARE_MAC_BUF(mac);
/* This code scans the region 0xf0000 to 0xfffff for a "NETIDBLK". */
for(p = (char *)phys_to_virt(0xf0000); p < (char *)phys_to_virt(0x100000); p++)
@@ -387,7 +386,7 @@ static int __init znet_probe (void)
if (!dev)
return -ENOMEM;
- znet = dev->priv;
+ znet = netdev_priv(dev);
netinfo = (struct netidblk *)p;
dev->base_addr = netinfo->iobase1;
@@ -397,9 +396,9 @@ static int __init znet_probe (void)
for (i = 0; i < 6; i++)
dev->dev_addr[i] = netinfo->netid[i];
- printk(KERN_INFO "%s: ZNET at %#3lx, %s"
+ printk(KERN_INFO "%s: ZNET at %#3lx, %pM"
", using IRQ %d DMA %d and %d.\n",
- dev->name, dev->base_addr, print_mac(mac, dev->dev_addr),
+ dev->name, dev->base_addr, dev->dev_addr,
dev->irq, netinfo->dma1, netinfo->dma2);
if (znet_debug > 1) {
@@ -531,7 +530,7 @@ static void znet_tx_timeout (struct net_device *dev)
static int znet_send_packet(struct sk_buff *skb, struct net_device *dev)
{
int ioaddr = dev->base_addr;
- struct znet_private *znet = dev->priv;
+ struct znet_private *znet = netdev_priv(dev);
unsigned long flags;
short length = skb->len;
@@ -601,7 +600,7 @@ static int znet_send_packet(struct sk_buff *skb, struct net_device *dev)
static irqreturn_t znet_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
- struct znet_private *znet = dev->priv;
+ struct znet_private *znet = netdev_priv(dev);
int ioaddr;
int boguscnt = 20;
int handled = 0;
@@ -679,7 +678,7 @@ static irqreturn_t znet_interrupt(int irq, void *dev_id)
static void znet_rx(struct net_device *dev)
{
- struct znet_private *znet = dev->priv;
+ struct znet_private *znet = netdev_priv(dev);
int ioaddr = dev->base_addr;
int boguscount = 1;
short next_frame_end_offset = 0; /* Offset of next frame start. */
@@ -786,7 +785,6 @@ static void znet_rx(struct net_device *dev)
}
skb->protocol=eth_type_trans(skb,dev);
netif_rx(skb);
- dev->last_rx = jiffies;
dev->stats.rx_packets++;
dev->stats.rx_bytes += pkt_len;
}
@@ -829,7 +827,7 @@ static void show_dma(struct net_device *dev)
{
short ioaddr = dev->base_addr;
unsigned char stat = inb (ioaddr);
- struct znet_private *znet = dev->priv;
+ struct znet_private *znet = netdev_priv(dev);
unsigned long flags;
short dma_port = ((znet->tx_dma&3)<<2) + IO_DMA2_BASE;
unsigned addr = inb(dma_port);
@@ -852,7 +850,7 @@ static void hardware_init(struct net_device *dev)
{
unsigned long flags;
short ioaddr = dev->base_addr;
- struct znet_private *znet = dev->priv;
+ struct znet_private *znet = netdev_priv(dev);
znet->rx_cur = znet->rx_start;
znet->tx_cur = znet->tx_start;
@@ -914,7 +912,7 @@ static void update_stop_hit(short ioaddr, unsigned short rx_stop_offset)
static __exit void znet_cleanup (void)
{
if (znet_dev) {
- struct znet_private *znet = znet_dev->priv;
+ struct znet_private *znet = netdev_priv(znet_dev);
unregister_netdev (znet_dev);
kfree (znet->rx_start);
diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c
index 3926b2aa9cca..affd904deafc 100644
--- a/drivers/net/zorro8390.c
+++ b/drivers/net/zorro8390.c
@@ -122,7 +122,7 @@ static int __devinit zorro8390_init_one(struct zorro_dev *z,
break;
board = z->resource.start;
ioaddr = board+cards[i].offset;
- dev = ____alloc_ei_netdev(0);
+ dev = alloc_ei_netdev();
if (!dev)
return -ENOMEM;
if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, DRV_NAME)) {
@@ -139,6 +139,20 @@ static int __devinit zorro8390_init_one(struct zorro_dev *z,
return 0;
}
+static const struct net_device_ops zorro8390_netdev_ops = {
+ .ndo_open = zorro8390_open,
+ .ndo_stop = zorro8390_close,
+ .ndo_start_xmit = ei_start_xmit,
+ .ndo_tx_timeout = ei_tx_timeout,
+ .ndo_get_stats = ei_get_stats,
+ .ndo_set_multicast_list = ei_set_multicast_list,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = eth_change_mtu,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+ .ndo_poll_controller = ei_poll,
+#endif
+};
+
static int __devinit zorro8390_init(struct net_device *dev,
unsigned long board, const char *name,
unsigned long ioaddr)
@@ -151,7 +165,6 @@ static int __devinit zorro8390_init(struct net_device *dev,
0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
};
- DECLARE_MAC_BUF(mac);
/* Reset card. Who knows what dain-bramaged state it was left in. */
{
@@ -216,7 +229,7 @@ static int __devinit zorro8390_init(struct net_device *dev,
dev->dev_addr[i] = SA_prom[i];
#ifdef DEBUG
- printk("%s", print_mac(mac, dev->dev_addr));
+ printk("%pM", dev->dev_addr);
#endif
ei_status.name = name;
@@ -231,12 +244,8 @@ static int __devinit zorro8390_init(struct net_device *dev,
ei_status.block_output = &zorro8390_block_output;
ei_status.get_8390_hdr = &zorro8390_get_8390_hdr;
ei_status.reg_offset = zorro8390_offsets;
- dev->open = &zorro8390_open;
- dev->stop = &zorro8390_close;
-#ifdef CONFIG_NET_POLL_CONTROLLER
- dev->poll_controller = __ei_poll;
-#endif
+ dev->netdev_ops = &zorro8390_netdev_ops;
__NS8390_init(dev, 0);
err = register_netdev(dev);
if (err) {
@@ -244,8 +253,8 @@ static int __devinit zorro8390_init(struct net_device *dev,
return err;
}
- printk(KERN_INFO "%s: %s at 0x%08lx, Ethernet Address %s\n",
- dev->name, name, board, print_mac(mac, dev->dev_addr));
+ printk(KERN_INFO "%s: %s at 0x%08lx, Ethernet Address %pM\n",
+ dev->name, name, board, dev->dev_addr);
return 0;
}